Files
Genarrative/jenkins/Jenkinsfile.ai-game-creator-shell-build
kdletters e146859ea2
Project CI / AI game creator shell Rust shard 1/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (push) Has been cancelled
Project CI / AI game creator shell Rust smoke (push) Has been cancelled
Project CI / AI game creator shell Rust crates (push) Has been cancelled
Project CI / Backend tests (push) Has been cancelled
Project CI / Native shell tests (push) Has been cancelled
Project CI / Frontend tests (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
Project CI / AI game creator shell web tests (push) Has been cancelled
更新摘要锚点支持 CI 兜底
- 摘要锚点优先取渠道清单 commit,缺失时回退 CI 传入的上一次成功构建 COMMIT_HASH
- Jenkins 构建阶段解析上一次成功构建的 COMMIT_HASH 并注入 AGC_UPDATE_PREVIOUS_COMMIT,读取失败保持为空
- 新增锚点优先级与非法值忽略的定向用例
- 技术方案补充锚点兜底说明
2026-09-17 19:42:10 +08:00

192 lines
9.5 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
pipeline {
agent {
label 'windows && win2022'
}
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'
AGC_WINDOWS_PATH = 'C:\\Tools\\Git\\cmd;C:\\Program Files\\nodejs;C:\\Users\\Administrator\\.cargo\\bin;C:\\Tools\\ossutil;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Windows\\System32\\OpenSSH\\'
}
parameters {
string(name: 'SOURCE_BRANCH', defaultValue: 'master', description: '源码分支')
string(name: 'COMMIT_HASH', defaultValue: '', description: '可选,指定属于 SOURCE_BRANCH 的 Git commit')
string(name: 'AGC_RELEASE_VERSION', defaultValue: '', description: '可选,指定三段版本号;留空则按该渠道 OSS 与本地版本自动递增 patch')
choice(name: 'AGC_UPDATE_CHANNEL', choices: ['dev-win', 'dev-mac'], description: 'AGC 发布渠道;dev-win 在 Windows 节点执行,dev-mac 需在 macOS 构建机本地执行')
booleanParam(name: 'AGC_RELEASE_DRY_RUN', defaultValue: false, description: '勾选后只构建并打印将要执行的上传命令,不写入 OSS')
text(name: 'AGC_UPDATE_RELEASE_NOTES', defaultValue: '', description: '可选,支持多行文本;留空则由本次发布的客户端相关提交自动生成更新摘要')
string(name: 'OSSUTIL_BIN', defaultValue: 'ossutil', description: 'ossutil 或 ossutil.exe 的绝对路径/命令名')
}
stages {
stage('Checkout') {
steps {
withCredentials([sshUserPrivateKey(credentialsId: env.GIT_REMOTE_CREDENTIAL_ID, keyFileVariable: 'GIT_SSH_KEY', usernameVariable: 'GIT_SSH_USER')]) {
powershell '''
$ErrorActionPreference = 'Stop'
$env:GIT_SSH_COMMAND = "ssh -i `"$env:GIT_SSH_KEY`" -o StrictHostKeyChecking=no"
$git = 'C:\\Tools\\Git\\cmd\\git.exe'
if (-not (Test-Path $git)) { throw "找不到 Git: $git" }
if (Test-Path '.git') {
& $git fetch --tags --force --prune origin "+refs/heads/$($env:SOURCE_BRANCH):refs/remotes/origin/$($env:SOURCE_BRANCH)"
if ($LASTEXITCODE -ne 0) { throw 'Git fetch 失败' }
& $git clean -fdx
& $git reset --hard "origin/$($env:SOURCE_BRANCH)"
} else {
& $git clone --no-single-branch $env:GIT_REMOTE_URL .
if ($LASTEXITCODE -ne 0) { throw 'Git clone 失败' }
& $git fetch --tags --force origin "refs/heads/$($env:SOURCE_BRANCH):refs/remotes/origin/$($env:SOURCE_BRANCH)"
if ($LASTEXITCODE -ne 0) { throw 'Git fetch 分支失败' }
& $git checkout --detach "origin/$($env:SOURCE_BRANCH)"
}
$commit = ([string]$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(["PATH=${env.AGC_WINDOWS_PATH}", "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')) {
if (-not (Get-Command $commandName -ErrorAction SilentlyContinue)) {
throw "Windows AGC 节点缺少 $commandName,请先安装并加入 Jenkins Agent PATH。"
}
}
$ossutil = ([string]$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 "jenkins-user=$([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)"
Write-Host "local-app-data=$env:LOCALAPPDATA"
$targetTools = Join-Path $PWD 'apps/ai-game-creator-shell/src-tauri/target/.tauri'
New-Item -ItemType Directory -Force -Path $targetTools | Out-Null
$probe = Join-Path $targetTools '.jenkins-write-probe'
Set-Content -Path $probe -Value 'ok' -NoNewline
Remove-Item -LiteralPath $probe -Force
Write-Host "tauri-tools-dir=$targetTools"
'''
}
}
}
stage('Install dependencies') {
steps {
withEnv(["PATH=${env.AGC_WINDOWS_PATH}"]) {
powershell '''
$ErrorActionPreference = 'Stop'
npm ci --no-audit --no-fund
'''
}
}
}
stage('Build and upload') {
steps {
script {
// 摘要锚点兜底:清单里还没有 commit 字段时(首次启用摘要 / 换渠道),
// 用上一次成功构建的 COMMIT_HASH 作为「上次发布提交」。读取失败保持为空,
// 发布脚本会退回清单锚点或干脆不写摘要。
def anchor = ''
try {
def previousBuild = currentBuild.previousSuccessfulBuild
anchor = (previousBuild?.buildVariables?.COMMIT_HASH ?: '').toString().trim()
} catch (error) {
echo "读取上一次成功构建的 commit 失败,跳过摘要锚点兜底:${error}"
}
env.AGC_UPDATE_PREVIOUS_COMMIT = anchor
if (anchor) {
echo "更新摘要锚点兜底:${anchor.take(12)}"
}
}
withCredentials([
string(credentialsId: 'AliyunAccessKeyId', variable: 'AGC_OSS_ACCESS_KEY_ID'),
string(credentialsId: 'AliyunaccessKeySecret', variable: 'AGC_OSS_ACCESS_KEY_SECRET'),
string(credentialsId: 'AgcUpdaterSigningKey', variable: 'TAURI_SIGNING_PRIVATE_KEY'),
string(credentialsId: 'AgcUpdaterSigningKeyPassword', variable: 'TAURI_SIGNING_PRIVATE_KEY_PASSWORD'),
]) {
withEnv([
"PATH=${env.AGC_WINDOWS_PATH}",
"OSSUTIL_BIN=${params.OSSUTIL_BIN}",
"AGC_RELEASE_VERSION=${params.AGC_RELEASE_VERSION}",
"AGC_UPDATE_CHANNEL=${params.AGC_UPDATE_CHANNEL}",
"AGC_RELEASE_DRY_RUN=${params.AGC_RELEASE_DRY_RUN ? '1' : '0'}",
"AGC_UPDATE_PREVIOUS_COMMIT=${env.AGC_UPDATE_PREVIOUS_COMMIT ?: ''}",
"AGC_UPDATE_RELEASE_NOTES=${params.AGC_UPDATE_RELEASE_NOTES}",
]) {
powershell '''
$ErrorActionPreference = 'Stop'
npm run ai-game-creator-shell:release:upload
$buildExitCode = $LASTEXITCODE
if ($buildExitCode -ne 0) {
$nsis = Join-Path $PWD 'apps/ai-game-creator-shell/src-tauri/target/.tauri/NSIS/makensis.exe'
Write-Host "Tauri NSIS path=$nsis"
if (Test-Path $nsis) {
Get-Item $nsis | Select-Object FullName, Length, LastWriteTime
try { & $nsis -VERSION } catch { Write-Host "无法直接启动 Tauri NSIS$($_.Exception.Message)" }
} else {
Write-Host 'Tauri NSIS makensis.exe 不存在。'
}
throw "AGC 发布构建失败,退出码=$buildExitCode"
}
'''
}
}
}
}
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/**/*.sig,apps/ai-game-creator-shell/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/latest.json,apps/ai-game-creator-shell/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/legacy-latest.json,apps/ai-game-creator-shell/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/release-notes.txt,.jenkins-source-commit', fingerprint: true
}
}
}
post {
success {
echo params.AGC_RELEASE_DRY_RUN
? "AGC ${params.AGC_UPDATE_CHANNEL} 渠道演练完成:已构建并生成清单,未写入 OSS。"
: "AGC ${params.AGC_UPDATE_CHANNEL} 渠道安装包、签名与渠道清单已构建并上传 OSS。"
}
}
}