把macOS渠道纳入定时发布并共用总版本号
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Failing after 17s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Failing after 19s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Failing after 19s
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Failing after 19s
Project CI / AI game creator shell Rust smoke (pull_request) Failing after 16s
Project CI / Native shell tests (pull_request) Failing after 16s
Project CI / Backend tests (pull_request) Failing after 16s
Project CI / AI game creator shell Rust crates (pull_request) Failing after 16s
Project CI / Frontend tests (pull_request) Failing after 7s
Project CI / Repository checks (pull_request) Failing after 11s
Project CI / AI game creator shell web tests (pull_request) Failing after 11s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Failing after 17s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Failing after 19s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Failing after 19s
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Failing after 19s
Project CI / AI game creator shell Rust smoke (pull_request) Failing after 16s
Project CI / Native shell tests (pull_request) Failing after 16s
Project CI / Backend tests (pull_request) Failing after 16s
Project CI / AI game creator shell Rust crates (pull_request) Failing after 16s
Project CI / Frontend tests (pull_request) Failing after 7s
Project CI / Repository checks (pull_request) Failing after 11s
Project CI / AI game creator shell web tests (pull_request) Failing after 11s
调度器在发号后同时触发macOS渠道构建,透传同一个总版本号与固定revision macOS Job改为默认真实发布,演练需显式勾选 新增SKIP_IF_SUPERSEDED:节点离线期间排队的旧构建在恢复后自行让位 补充生产门禁规则与回归断言 同步调度与运维文档口径
This commit is contained in:
@@ -90,10 +90,25 @@ test('CI pipeline is manual, publishes the macOS partition and never reuses a de
|
||||
!pipeline.includes('genarrative-agc-macos-local'),
|
||||
'Jenkinsfile 不得写死具体节点名',
|
||||
);
|
||||
// dry-run 必须是默认值:不显式取消勾选就不得写入 OSS。
|
||||
// 这条管线是正式发布入口(与 Windows 对称):默认真发布,演练需显式勾选。
|
||||
assert.match(
|
||||
pipeline,
|
||||
/booleanParam\(name: 'AGC_RELEASE_DRY_RUN', defaultValue: true/u,
|
||||
/booleanParam\(name: 'AGC_RELEASE_DRY_RUN', defaultValue: false/u,
|
||||
'Channel 发布默认必须是真发布,演练只能显式勾选',
|
||||
);
|
||||
// 节点是办公机:离线期间排队的旧构建必须自行让位,且跳过要覆盖后续全部阶段。
|
||||
assert.match(
|
||||
pipeline,
|
||||
/booleanParam\(name: 'SKIP_IF_SUPERSEDED', defaultValue: false/u,
|
||||
);
|
||||
assert.ok(
|
||||
pipeline.includes('.jenkins-superseded-by'),
|
||||
'必须记录被推进的标记供后续阶段判定',
|
||||
);
|
||||
assert.equal(
|
||||
(pipeline.match(/env\.AGC_BUILD_SUPERSEDED != 'true'/gu) ?? []).length,
|
||||
3,
|
||||
'Toolchain / Package / Archive 三个阶段都必须按跳过标记收口',
|
||||
);
|
||||
for (const forbidden of [
|
||||
'triggers {',
|
||||
|
||||
@@ -90,7 +90,7 @@ SpacetimeDB 任务统一先读取 `.codex/skills/genarrative-spacetimedb/SKILL.m
|
||||
|
||||
## Jenkins 定时版本调度
|
||||
|
||||
定时与版本比较只保留在 `Genarrative-Scheduled-Revision-Trigger` 一处:每小时用 `git ls-remote` 解析 `SOURCE_BRANCH` 远端 HEAD,与上一次触发过的 revision 比较,变化时才把同一个 `COMMIT_HASH` 同时传给 `Genarrative-Full-Build-And-Deploy` 与 `Genarrative-Agc-Windows-Build`,保证两条管线构建同一个版本。`Genarrative-Full-Build-And-Deploy` 与 `Genarrative-Agc-Windows-Build` 不得自带 `triggers` / `cron`,也不得在管线内再做一套版本去重;`npm run check:production-ops` 会拦住这两类回退。调度状态与生效步骤见 `docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。
|
||||
定时与版本比较只保留在 `Genarrative-Scheduled-Revision-Trigger` 一处:每小时用 `git ls-remote` 解析 `SOURCE_BRANCH` 远端 HEAD,与上一次触发过的 revision 比较,变化时才把同一个 `COMMIT_HASH` 传给 `Genarrative-Full-Build-And-Deploy`,并先经 `Genarrative-Agc-Global-Version-Issue` 发号、再把同一个总版本号透传给 `Genarrative-Agc-Windows-Build` 与 `Genarrative-Agc-MacOS-Build`,保证两个客户端的平台分区发布同一个版本。这三个下游 Job 都不得自带 `triggers` / `cron`,也不得在管线内再做一套版本去重;`npm run check:production-ops` 会拦住这两类回退。macOS 节点是日常办公机,调度触发它时置 `SKIP_IF_SUPERSEDED=true`:节点离线期间排队的旧构建在恢复后会自行让位,不发布过期版本。调度状态与生效步骤见 `docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。
|
||||
|
||||
## Gitea CI 依赖闭合
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -12,7 +12,8 @@ pipeline {
|
||||
string(name: 'COMMIT_HASH', defaultValue: '', description: '可选,固定属于源码分支的提交;不递增应用版本')
|
||||
string(name: 'AGC_UPDATE_CHANNEL', defaultValue: 'dev', description: 'AGC 发布渠道(基础名,不含系统):dev、release 或自定义小写名称;写入的分区固定为 <channel>-mac')
|
||||
string(name: 'AGC_RELEASE_VERSION', defaultValue: '', description: '可选三段版本号;留空则按 <channel>-mac 分区清单高水位递增 patch。首次发布建议显式指定,避免版本链回退')
|
||||
booleanParam(name: 'AGC_RELEASE_DRY_RUN', defaultValue: true, description: '勾选后只构建、验签并打印将上传的对象,不写 OSS;取消勾选才真正发布到 <channel>-mac 分区')
|
||||
booleanParam(name: 'AGC_RELEASE_DRY_RUN', defaultValue: false, description: '默认直接发布到 <channel>-mac 分区;勾选后只构建、验签并打印将上传的对象,不写 OSS(演练)')
|
||||
booleanParam(name: 'SKIP_IF_SUPERSEDED', defaultValue: false, description: '置真时:本次 COMMIT_HASH 若已被源码分支推进,则直接跳过而不构建。调度器触发本 Job 时置真,避免节点离线期间排队的旧构建在恢复后发布过期版本')
|
||||
string(name: 'AGC_UPDATE_RELEASE_NOTES', defaultValue: '', description: '可选单行更新摘要;留空则由发布脚本按提交自动汇总')
|
||||
string(name: 'OSSUTIL_BIN', defaultValue: 'ossutil', description: 'ossutil 命令名或绝对路径(Mac 节点默认装在 ~/.local/bin/ossutil)')
|
||||
string(name: 'CARGO_BUILD_JOBS', defaultValue: '8', description: '并行 rustc 任务数,默认吃满节点 8 核(4P+4E)。该值同时作为 rustc codegen 的 jobserver 令牌上限;节点只有 24 GB 内存且是日常办公机,若构建期间出现明显换页可临时调低。只影响本次构建')
|
||||
@@ -73,11 +74,31 @@ pipeline {
|
||||
# 不清除 node_modules/target 缓存;被跟踪内容始终来自上述 commit。
|
||||
git clean -fd
|
||||
git rev-parse HEAD > .jenkins-source-commit
|
||||
if [ "${SKIP_IF_SUPERSEDED}" = "true" ] && [ -n "$COMMIT_HASH" ]; then
|
||||
latest="$(git rev-parse "refs/remotes/origin/$SOURCE_BRANCH")"
|
||||
if [ "$latest" != "$(git rev-parse "$COMMIT_HASH^{commit}")" ]; then
|
||||
# 只置标记,由后面的 when 条件统一收口;不在 shell 里 exit 0,
|
||||
# 否则会带着旧 commit 继续往下构建。
|
||||
echo "[agc-macos] 本次 commit 已被 $SOURCE_BRANCH 推进:$COMMIT_HASH -> $latest,跳过发布"
|
||||
printf '%s' "$latest" > .jenkins-superseded-by
|
||||
fi
|
||||
fi
|
||||
'''
|
||||
}
|
||||
script {
|
||||
if (fileExists('.jenkins-superseded-by')) {
|
||||
env.AGC_BUILD_SUPERSEDED = 'true'
|
||||
currentBuild.result = 'NOT_BUILT'
|
||||
currentBuild.description = "${env.COMMIT_HASH} 已被 ${env.SOURCE_BRANCH} 推进到 ${readFile('.jenkins-superseded-by').trim().take(12)},跳过本轮发布"
|
||||
echo currentBuild.description
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Toolchain and dependencies') {
|
||||
when {
|
||||
expression { return env.AGC_BUILD_SUPERSEDED != 'true' }
|
||||
}
|
||||
steps {
|
||||
sh '''
|
||||
set -eu
|
||||
@@ -96,6 +117,9 @@ pipeline {
|
||||
}
|
||||
}
|
||||
stage('Package, verify and publish') {
|
||||
when {
|
||||
expression { return env.AGC_BUILD_SUPERSEDED != 'true' }
|
||||
}
|
||||
steps {
|
||||
withCredentials([
|
||||
string(credentialsId: 'AliyunAccessKeyId', variable: 'AGC_OSS_ACCESS_KEY_ID'),
|
||||
@@ -147,6 +171,9 @@ pipeline {
|
||||
}
|
||||
}
|
||||
stage('Archive release') {
|
||||
when {
|
||||
expression { return env.AGC_BUILD_SUPERSEDED != 'true' }
|
||||
}
|
||||
steps {
|
||||
archiveArtifacts artifacts: 'artifacts/*.dmg,artifacts/*.sha256,artifacts/latest.json,artifacts/*.sig,artifacts/release-notes.txt,artifacts/build-manifest.json,.jenkins-source-commit', fingerprint: true, allowEmptyArchive: false
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// 定时版本调度管线:解析远端分支版本,只有和上一次触发过的版本不同时,
|
||||
// 才用同一个固定 commit 触发 Full Build 与 AGC Windows Build 两个下游管线。
|
||||
// 才用同一个固定 commit 触发 Full Build、AGC 发号与 AGC Windows/macOS 渠道构建。
|
||||
pipeline {
|
||||
agent {
|
||||
label 'linux && genarrative-build'
|
||||
@@ -20,6 +20,7 @@ pipeline {
|
||||
GIT_REMOTE_CREDENTIAL_ID = 'genarrative-local-gitea-ssh'
|
||||
FULL_BUILD_JOB_NAME = 'Genarrative-Full-Build-And-Deploy'
|
||||
AGC_BUILD_JOB_NAME = 'Genarrative-Agc-Windows-Build'
|
||||
AGC_MACOS_BUILD_JOB_NAME = 'Genarrative-Agc-MacOS-Build'
|
||||
AGC_GLOBAL_VERSION_JOB_NAME = 'Genarrative-Agc-Global-Version-Issue'
|
||||
AGC_GLOBAL_VERSION_ARTIFACT = 'agc-global-version.txt'
|
||||
REVISION_STATE_FILE = '.jenkins-last-triggered-revision'
|
||||
@@ -177,6 +178,18 @@ pipeline {
|
||||
string(name: 'AGC_RELEASE_VERSION', value: env.AGC_GLOBAL_VERSION),
|
||||
]
|
||||
build job: env.AGC_BUILD_JOB_NAME, wait: false, propagate: false, parameters: agcParameters
|
||||
// macOS 与 Windows 共用发号 Job 下发的同一个总号:调度只透传号与固定 revision,
|
||||
// 不允许 Mac 侧自行发号,否则同一轮两个平台会拿到不同的号。
|
||||
def agcMacosParameters = [
|
||||
string(name: 'SOURCE_BRANCH', value: env.SOURCE_BRANCH),
|
||||
string(name: 'COMMIT_HASH', value: pinnedRevision),
|
||||
string(name: 'AGC_UPDATE_CHANNEL', value: 'dev'),
|
||||
string(name: 'AGC_RELEASE_VERSION', value: env.AGC_GLOBAL_VERSION),
|
||||
// Mac 节点是办公机:离线期间排队的旧构建在节点回来后必须自行让位,
|
||||
// 不允许发布一轮已经过期的版本。
|
||||
booleanParam(name: 'SKIP_IF_SUPERSEDED', value: true),
|
||||
]
|
||||
build job: env.AGC_MACOS_BUILD_JOB_NAME, wait: false, propagate: false, parameters: agcMacosParameters
|
||||
agcTriggered = true
|
||||
} else {
|
||||
echo "本轮提交不含 AGC 相关路径,跳过 ${env.AGC_BUILD_JOB_NAME};需要强制发布时勾选 FORCE_TRIGGER"
|
||||
@@ -185,6 +198,7 @@ pipeline {
|
||||
def triggered = []
|
||||
if (fullTriggered) { triggered.add(env.FULL_BUILD_JOB_NAME) }
|
||||
if (agcTriggered) { triggered.add(env.AGC_BUILD_JOB_NAME) }
|
||||
if (agcTriggered) { triggered.add(env.AGC_MACOS_BUILD_JOB_NAME) }
|
||||
def target = "${env.SOURCE_BRANCH}@${pinnedRevision.take(12)}"
|
||||
currentBuild.description = triggered.isEmpty()
|
||||
? "本轮提交与两条下游都无关,未触发任何发布:${target}"
|
||||
|
||||
@@ -7723,6 +7723,18 @@ for (const [snippet, reason] of [
|
||||
"AGC_GLOBAL_VERSION_ARTIFACT = 'agc-global-version.txt'",
|
||||
'必须从发号 Job 的归档产物读取总版本号',
|
||||
],
|
||||
[
|
||||
"AGC_MACOS_BUILD_JOB_NAME = 'Genarrative-Agc-MacOS-Build'",
|
||||
'必须把 macOS 渠道构建纳入同一轮调度',
|
||||
],
|
||||
[
|
||||
'build job: env.AGC_MACOS_BUILD_JOB_NAME, wait: false, propagate: false, parameters: agcMacosParameters',
|
||||
'必须用独立参数列表触发 macOS 渠道构建(pinnedParameters 只允许 Full Build 使用一次)',
|
||||
],
|
||||
[
|
||||
"booleanParam(name: 'SKIP_IF_SUPERSEDED', value: true)",
|
||||
'必须让节点离线期间排队的 macOS 旧构建自行让位,不发布过期版本',
|
||||
],
|
||||
]) {
|
||||
if (!scheduledRevisionTriggerContent.includes(snippet)) {
|
||||
failed = true;
|
||||
|
||||
Reference in New Issue
Block a user