diff --git a/apps/ai-game-creator-shell/scripts/build-release.mjs b/apps/ai-game-creator-shell/scripts/build-release.mjs index a6c455ff3..501b5b20b 100644 --- a/apps/ai-game-creator-shell/scripts/build-release.mjs +++ b/apps/ai-game-creator-shell/scripts/build-release.mjs @@ -5,6 +5,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; const appRoot = fileURLToPath(new URL('..', import.meta.url)); +const repoRoot = path.resolve(appRoot, '../..'); const defaultReleaseTarget = 'x86_64-pc-windows-msvc'; const releaseTarget = process.env.AGC_BUILD_TARGET?.trim() || defaultReleaseTarget; @@ -199,6 +200,23 @@ export function writeVersionFiles(version) { return nextVersion; } +export function assertVersionCommitted() { + const repoPaths = versionFileSources.map((source) => + path.relative(repoRoot, source.file).replaceAll('\\', '/'), + ); + const changed = + spawnSync( + 'git', + ['diff', '--quiet', 'HEAD', '--', ...repoPaths], + { cwd: repoRoot }, + ).status === 1; + if (changed) { + throw new Error( + '版本文件相对 HEAD 存在未提交改动,请先提交后再发布:运行 npm --prefix apps/ai-game-creator-shell run bump-version -- --commit', + ); + } +} + export function prepareReleaseVersion() { const localVersion = readLocalVersion(); validateVersionConsistency(localVersion); diff --git a/apps/ai-game-creator-shell/scripts/build-release.test.mjs b/apps/ai-game-creator-shell/scripts/build-release.test.mjs index 912251c6e..5e00983c9 100644 --- a/apps/ai-game-creator-shell/scripts/build-release.test.mjs +++ b/apps/ai-game-creator-shell/scripts/build-release.test.mjs @@ -78,3 +78,12 @@ test('release upload forces overwrite for versioned artifact and latest pointer' 2, ); }); + +test('release upload verifies the version is committed and not below OSS', () => { + const source = readFileSync( + new URL('./release-upload.mjs', import.meta.url), + 'utf8', + ); + assert.match(source, /assertVersionCommitted\(\)/u); + assert.match(source, /assertVersionNotBelowOss\(/u); +}); diff --git a/apps/ai-game-creator-shell/scripts/release-upload.mjs b/apps/ai-game-creator-shell/scripts/release-upload.mjs index c0ee8bb0c..e71b27dd0 100644 --- a/apps/ai-game-creator-shell/scripts/release-upload.mjs +++ b/apps/ai-game-creator-shell/scripts/release-upload.mjs @@ -10,6 +10,7 @@ if (!/^[a-z0-9][a-z0-9.-]{1,62}$/u.test(bucket) || /[\r\n\0]/u.test(endpoint)) { process.env.AGC_UPDATE_OSS_BASE_URL ||= `https://${bucket}.${endpoint}/agc`; const { + assertVersionCommitted, assertVersionNotBelowOss, generateUpdateManifest, prepareReleaseVersion, @@ -41,6 +42,7 @@ function runOssutil(args) { } const releaseVersion = await prepareReleaseVersion(); +assertVersionCommitted(); await assertVersionNotBelowOss(releaseVersion); runTauriBuild([]); const { artifact, manifestPath, manifest } = generateUpdateManifest(); diff --git a/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md b/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md index 10a9367e4..a5bb692fe 100644 --- a/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md +++ b/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md @@ -67,7 +67,9 @@ npm run ai-game-creator-shell:bump-version -- --version 0.1.25 --commit 构建/发布不再改写版本文件,而是读取仓库已提交版本,并在发布前做两件事: 1. 校验五个版本来源一致,不一致会中止,防止漂移。 -2. 通过 `assertVersionNotBelowOss` 读取 OSS `latest.json`:若仓库版本**低于**线上版本会中止, +2. 校验版本相对 `HEAD` 已提交(`assertVersionCommitted`):若版本文件存在未提交改动会中止, + 确保本地发布与 Jenkins 检出的是同一个版本。 +3. 通过 `assertVersionNotBelowOss` 读取 OSS `latest.json`:若仓库版本**低于**线上版本会中止, 并提示先运行 `bump-version`,避免回退线上版本;OSS 读取失败或清单格式错误同样会中止。 仓库版本等于或高于线上版本才放行。