@echo off setlocal EnableExtensions EnableDelayedExpansion chcp 65001 >nul rem OpsXShell v2.1.x native Windows release builder. rem Run this script from Windows x64 with the MSVC Rust toolchain installed. cd /d "%~dp0.." set "VERSION_ARG=" set "CHECK_MODE=full" set "RUST_TARGET=x86_64-pc-windows-msvc" set "OUTPUT_PLATFORM=windows-x64" :parse_args if "%~1"=="" goto args_done set "ARG=%~1" if /I "!ARG!"=="-h" goto usage_ok if /I "!ARG!"=="--help" goto usage_ok if /I "!ARG!"=="--quick" ( set "CHECK_MODE=quick" shift goto parse_args ) if /I "!ARG!"=="--skip-checks" ( set "CHECK_MODE=none" shift goto parse_args ) if /I "!ARG!"=="win-x64" ( shift goto parse_args ) if /I "!ARG:~0,4!"=="v2.1" goto set_version_arg if /I "!ARG:~0,4!"=="2.1." goto set_version_arg call :fail "未知参数:!ARG!(使用 scripts\build.bat --help 查看用法)" exit /b 1 :set_version_arg if defined VERSION_ARG ( call :fail "只能指定一个版本号" exit /b 1 ) set "VERSION_ARG=!ARG!" if /I "!VERSION_ARG:~0,1!"=="v" set "VERSION_ARG=!VERSION_ARG:~1!" shift goto parse_args :args_done if /I not "%OS%"=="Windows_NT" ( call :fail "build.bat 必须在 Windows 环境运行" exit /b 1 ) for %%C in (node npm npx cargo rustc powershell) do ( where %%C >nul 2>nul if errorlevel 1 ( call :fail "缺少构建依赖:%%C" exit /b 1 ) ) for /f "usebackq delims=" %%V in (`node -p "require('./package.json').version"`) do set "CURRENT_VERSION=%%V" if not defined CURRENT_VERSION ( call :fail "无法读取 package.json 版本" exit /b 1 ) if defined VERSION_ARG ( set "VERSION=%VERSION_ARG%" ) else ( set "VERSION=%CURRENT_VERSION%" ) node -e "if (!/^2\.1\.\d+(?:[.-][0-9A-Za-z.-]+)?$/.test(process.argv[1])) process.exit(1)" "%VERSION%" if errorlevel 1 ( call :fail "版本必须是 v2.1.x 语义版本,当前输入:%VERSION%" exit /b 1 ) where rustup >nul 2>nul if not errorlevel 1 ( rustup target list --installed | findstr /X /C:"%RUST_TARGET%" >nul if errorlevel 1 ( call :fail "Rust target 未安装:%RUST_TARGET%;请先运行 rustup target add %RUST_TARGET%" exit /b 1 ) ) if defined VERSION_ARG if /I not "%VERSION%"=="%CURRENT_VERSION%" ( call :log "同步版本号到 v%VERSION%" node scripts\set-version.mjs "%VERSION%" if errorlevel 1 exit /b 1 ) node scripts\set-version.mjs --check "%VERSION%" if errorlevel 1 exit /b 1 if not exist node_modules\ ( call :log "安装锁定依赖" call npm ci if errorlevel 1 exit /b 1 ) set "GIT_SHA=unknown" where git >nul 2>nul if not errorlevel 1 ( for /f "delims=" %%G in ('git rev-parse --short HEAD 2^>nul') do set "GIT_SHA=%%G" ) call :log "OpsXShell v%VERSION% · win-x64 · !GIT_SHA!" if /I "%CHECK_MODE%"=="full" ( call :log "运行完整发布门禁" call npm run acceptance:full if errorlevel 1 exit /b 1 ) else if /I "%CHECK_MODE%"=="quick" ( call :log "运行快速发布门禁" call npm run acceptance:quick if errorlevel 1 exit /b 1 ) else ( call :log "已按参数跳过构建前门禁" ) node scripts\release-preflight.mjs windows if errorlevel 1 exit /b 1 call :log "构建 Windows x86_64 原生安装包" call npx tauri build --ci --target "%RUST_TARGET%" if errorlevel 1 exit /b 1 set "BUNDLE_ROOT=src-tauri\target\%RUST_TARGET%\release\bundle" node scripts\verify-release.mjs windows "%BUNDLE_ROOT%" if errorlevel 1 exit /b 1 set "OUTPUT_DIR=%CD%\release\v%VERSION%\%OUTPUT_PLATFORM%" if exist "%OUTPUT_DIR%" rmdir /S /Q "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%" if errorlevel 1 ( call :fail "无法创建输出目录:%OUTPUT_DIR%" exit /b 1 ) set /A ARTIFACT_COUNT=0 for %%F in ("%BUNDLE_ROOT%\nsis\*.exe" "%BUNDLE_ROOT%\msi\*.msi" "%BUNDLE_ROOT%\wix\*.msi") do ( if exist "%%~fF" ( copy /Y "%%~fF" "%OUTPUT_DIR%\%%~nxF" >nul if errorlevel 1 ( call :fail "复制安装包失败:%%~fF" exit /b 1 ) set /A ARTIFACT_COUNT+=1 ) ) if "%ARTIFACT_COUNT%"=="0" ( call :fail "构建完成但未找到 NSIS/MSI 安装包:%BUNDLE_ROOT%" exit /b 1 ) powershell -NoProfile -ExecutionPolicy Bypass -Command ^ "$files = Get-ChildItem -LiteralPath $env:OUTPUT_DIR -File ^| Where-Object { $_.Extension -in '.exe', '.msi' };" ^ "$lines = @($files ^| ForEach-Object { (Get-FileHash -Algorithm SHA256 -LiteralPath $_.FullName).Hash.ToLowerInvariant() + ' ' + $_.Name });" ^ "[System.IO.File]::WriteAllLines((Join-Path $env:OUTPUT_DIR 'SHA256SUMS.txt'), [string[]]$lines, (New-Object System.Text.UTF8Encoding($false)))" if errorlevel 1 ( call :fail "生成 SHA256SUMS.txt 失败" exit /b 1 ) call :log "构建完成:%OUTPUT_DIR%" dir "%OUTPUT_DIR%" echo. echo [build] SHA-256 type "%OUTPUT_DIR%\SHA256SUMS.txt" exit /b 0 :usage_ok call :usage exit /b 0 :usage echo OpsXShell Windows 原生安装包构建脚本 echo. echo 用法: echo scripts\build.bat [v2.1.x] [win-x64] [选项] echo. echo 选项: echo --quick 构建前只运行快速门禁 echo --skip-checks 跳过门禁,仅用于本地重复打包 echo -h, --help 显示帮助 echo. echo 示例: echo scripts\build.bat echo scripts\build.bat v2.1.1 echo scripts\build.bat v2.1.2 win-x64 --quick echo. echo 环境要求: echo Windows 10/11 x64、Node.js 18+、Rust MSVC toolchain、 echo Visual Studio 2022 Build Tools(Desktop development with C++)、 echo Windows 10/11 SDK、WebView2 Runtime。 echo. echo 说明: echo - 输出 NSIS/MSI 到 release\v版本\windows-x64 并生成 SHA256SUMS.txt。 echo - 脚本不会创建或推送 Git tag,也不会上传 Release。 echo - 正式签名需设置 REQUIRE_SIGNING=true 和 Windows 签名环境变量。 exit /b 0 :log echo. echo [build] %~1 exit /b 0 :fail echo. echo [build] ERROR: %~1 1>&2 exit /b 1