From 0e2bee9fa7ef7980eff313a8908dc5b0b2cda635 Mon Sep 17 00:00:00 2001 From: kdletters Date: Mon, 31 Aug 2026 17:01:37 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20AGC=20Windows=20Jenkins=20?= =?UTF-8?q?=E6=9E=84=E5=BB=BA=E6=B5=81=E6=B0=B4=E7=BA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 Windows Agent 构建与上传流水线 补充 AGC Jenkins 节点工具链和 OSS 权限约定 --- ...方案】AGC客户端更新检查与下载-2026-08-31.md | 12 ++ .../Jenkinsfile.ai-game-creator-shell-build | 133 ++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 jenkins/Jenkinsfile.ai-game-creator-shell-build diff --git a/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md b/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md index 300ad78ea..f2b8e8c2a 100644 --- a/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md +++ b/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md @@ -45,3 +45,15 @@ OSS 前缀,通过 `AGC_UPDATE_RELEASE_NOTES` 写入发布说明;`--no-bundle 先按上述规则比较 OSS 版本、递增 patch、构建 Windows x64 NSIS,再上传安装包和 `latest.json`。默认上传到 `agc-dev` / `oss-rg-china-mainland.aliyuncs.com`,也可用 `AGC_OSS_BUCKET`、`AGC_OSS_ENDPOINT` 和 `OSSUTIL_BIN` 覆盖;凭据由 ossutil 本机配置读取,不能写入仓库或命令行参数。 + +## Jenkins Windows 构建节点 + +AGC 发布流水线使用 `jenkins/Jenkinsfile.ai-game-creator-shell-build`,节点标签固定为 +`windows && genarrative-agc-build`。节点应为 Windows Server 2022 x64 虚拟机,预装 Node.js 22、npm +10.9.7、Rust 1.96.0、Visual Studio Build Tools(MSVC 与 Windows SDK)、NSIS、Git 和 ossutil; +Jenkins Agent 服务必须能在同一用户环境中找到这些命令。流水线执行根 workspace 的 `npm ci`,然后调用 +`npm run ai-game-creator-shell:release:upload`,并归档 Windows 安装包、`latest.json` 与源码 commit。 + +Jenkins 节点上的 ossutil 必须使用具备 `PutObject` 权限的受保护配置;OSS 对客户端保持公共读即可, +公共读本身不授予 Jenkins 上传权限。由于版本号取决于 OSS 当前清单,Job 已关闭并发构建;若 Jenkins +上存在多个 AGC 发布 Job,还应使用同一个 Lockable Resource 串行化发布。 diff --git a/jenkins/Jenkinsfile.ai-game-creator-shell-build b/jenkins/Jenkinsfile.ai-game-creator-shell-build new file mode 100644 index 000000000..274a8d65d --- /dev/null +++ b/jenkins/Jenkinsfile.ai-game-creator-shell-build @@ -0,0 +1,133 @@ +pipeline { + agent { + label 'windows && genarrative-agc-build' + } + + options { + disableConcurrentBuilds() + skipDefaultCheckout(true) + buildDiscarder(logRotator(numToKeepStr: '20', artifactNumToKeepStr: '20')) + } + + environment { + GIT_REMOTE_URL = 'ssh://git@192.168.35.82:2222/GenarrativeAI/Genarrative.git' + GIT_REMOTE_CREDENTIAL_ID = 'genarrative-local-gitea-ssh' + GENARRATIVE_NPM_VERSION = '10.9.7' + AGC_OSS_BUCKET = 'agc-dev' + AGC_OSS_ENDPOINT = 'oss-rg-china-mainland.aliyuncs.com' + } + + parameters { + string(name: 'SOURCE_BRANCH', defaultValue: 'master', description: '源码分支') + string(name: 'COMMIT_HASH', defaultValue: '', description: '可选,指定属于 SOURCE_BRANCH 的 Git commit') + string(name: 'AGC_UPDATE_RELEASE_NOTES', defaultValue: '', description: '可选,写入 latest.json 的发布说明') + string(name: 'OSSUTIL_BIN', defaultValue: 'ossutil', description: 'ossutil 或 ossutil.exe 的绝对路径/命令名') + } + + stages { + stage('Checkout') { + steps { + checkout([ + $class: 'GitSCM', + branches: [[name: "*/${params.SOURCE_BRANCH}"]], + doGenerateSubmoduleConfigurations: false, + extensions: [ + [$class: 'CleanBeforeCheckout'], + [$class: 'CloneOption', shallow: false, noTags: false, timeout: 30], + ], + userRemoteConfigs: [[ + url: env.GIT_REMOTE_URL, + credentialsId: env.GIT_REMOTE_CREDENTIAL_ID, + refspec: "+refs/heads/${params.SOURCE_BRANCH}:refs/remotes/origin/${params.SOURCE_BRANCH}", + ]], + ]) + powershell ''' + $ErrorActionPreference = 'Stop' + $commit = $env:COMMIT_HASH.Trim() + if ($commit) { + if ($commit -notmatch '^[0-9a-fA-F]{7,64}$') { + throw 'COMMIT_HASH 必须是 7-64 位十六进制 Git commit。' + } + git cat-file -e "${commit}^{commit}" + if ($LASTEXITCODE -ne 0) { + throw "COMMIT_HASH 不存在: $commit" + } + $branchRef = "refs/remotes/origin/$($env:SOURCE_BRANCH)" + git merge-base --is-ancestor $commit $branchRef + if ($LASTEXITCODE -ne 0) { + throw "COMMIT_HASH 不属于 SOURCE_BRANCH: $($env:SOURCE_BRANCH)" + } + git checkout --detach $commit + } + $resolved = (git rev-parse HEAD).Trim() + Set-Content -Path '.jenkins-source-commit' -Value $resolved -NoNewline + Write-Host "源码 commit=$resolved" + ''' + } + } + + stage('Toolchain preflight') { + steps { + withEnv(["OSSUTIL_BIN=${params.OSSUTIL_BIN}"]) { + powershell ''' + $ErrorActionPreference = 'Stop' + $actualNpm = (npm --version).Trim() + if ($actualNpm -ne $env:GENARRATIVE_NPM_VERSION) { + throw "npm 版本不匹配:期望 $($env:GENARRATIVE_NPM_VERSION),实际 $actualNpm" + } + foreach ($commandName in @('node', 'npm', 'rustc', 'cargo', 'makensis')) { + if (-not (Get-Command $commandName -ErrorAction SilentlyContinue)) { + throw "Windows AGC 节点缺少 $commandName,请先安装并加入 Jenkins Agent PATH。" + } + } + $ossutil = $env:OSSUTIL_BIN.Trim() + if (-not $ossutil) { $ossutil = 'ossutil' } + if (-not (Get-Command $ossutil -ErrorAction SilentlyContinue)) { + throw "Windows AGC 节点缺少 ossutil:$ossutil" + } + Write-Host "node=$((node --version).Trim())" + Write-Host "npm=$actualNpm" + Write-Host "rustc=$((rustc --version).Trim())" + Write-Host "cargo=$((cargo --version).Trim())" + Write-Host "makensis=$((makensis -VERSION | Select-Object -First 1).Trim())" + ''' + } + } + } + + stage('Install dependencies') { + steps { + powershell ''' + $ErrorActionPreference = 'Stop' + npm ci --no-audit --no-fund + ''' + } + } + + stage('Build and upload') { + steps { + withEnv([ + "OSSUTIL_BIN=${params.OSSUTIL_BIN}", + "AGC_UPDATE_RELEASE_NOTES=${params.AGC_UPDATE_RELEASE_NOTES}", + ]) { + powershell ''' + $ErrorActionPreference = 'Stop' + npm run ai-game-creator-shell:release:upload + ''' + } + } + } + + stage('Archive release') { + steps { + archiveArtifacts artifacts: 'apps/ai-game-creator-shell/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/**/*.exe,apps/ai-game-creator-shell/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/latest.json,.jenkins-source-commit', fingerprint: true + } + } + } + + post { + success { + echo 'AGC Windows x64 安装包已构建并上传 OSS。' + } + } +}