From 65551cd827bbc85ea6a5c30dd6f193480afcd94a Mon Sep 17 00:00:00 2001 From: Suzumiya Date: Mon, 7 Sep 2026 12:34:09 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E6=8F=90=E5=8D=87=20AGC=20=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E8=87=B3=200.1.19=20=E5=B9=B6=E8=A1=A5=E5=85=85?= =?UTF-8?q?=E5=8F=91=E5=B8=83=E7=89=88=E6=9C=AC=E5=9B=9E=E5=86=99=E7=BA=A6?= =?UTF-8?q?=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - package.json 版本 0.1.12 -> 0.1.19,与 OSS latest.json 线上版本对齐,消除 dev 客户端每次启动误报发现新版本 - 同步更新根 package-lock.json、src-tauri/tauri.conf.json、src-tauri/Cargo.toml、Cargo.lock 中 AGC 包条目版本至 0.1.19,五处保持一致 - 在 AGC 更新技术方案文档的发布约定补充说明:发布新版本后必须手动将版本号变更提交回仓库,避免版本漂移 --- apps/ai-game-creator-shell/package.json | 2 +- apps/ai-game-creator-shell/src-tauri/Cargo.lock | 2 +- apps/ai-game-creator-shell/src-tauri/Cargo.toml | 2 +- apps/ai-game-creator-shell/src-tauri/tauri.conf.json | 2 +- .../【技术方案】AGC客户端更新检查与下载-2026-08-31.md | 7 +++++++ package-lock.json | 2 +- 6 files changed, 12 insertions(+), 5 deletions(-) diff --git a/apps/ai-game-creator-shell/package.json b/apps/ai-game-creator-shell/package.json index 50f3050c7..c5397c3b5 100644 --- a/apps/ai-game-creator-shell/package.json +++ b/apps/ai-game-creator-shell/package.json @@ -1,7 +1,7 @@ { "name": "@genarrative/ai-game-creator-shell", "private": true, - "version": "0.1.12", + "version": "0.1.19", "type": "module", "scripts": { "dev": "node scripts/start-tauri-dev.mjs", diff --git a/apps/ai-game-creator-shell/src-tauri/Cargo.lock b/apps/ai-game-creator-shell/src-tauri/Cargo.lock index f4ca27d53..4196e769b 100644 --- a/apps/ai-game-creator-shell/src-tauri/Cargo.lock +++ b/apps/ai-game-creator-shell/src-tauri/Cargo.lock @@ -1703,7 +1703,7 @@ dependencies = [ [[package]] name = "genarrative-ai-game-creator-shell" -version = "0.1.12" +version = "0.1.19" dependencies = [ "agent-runtime-core", "axum", diff --git a/apps/ai-game-creator-shell/src-tauri/Cargo.toml b/apps/ai-game-creator-shell/src-tauri/Cargo.toml index 7aa0e1cb4..1d3b2b20d 100644 --- a/apps/ai-game-creator-shell/src-tauri/Cargo.toml +++ b/apps/ai-game-creator-shell/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "genarrative-ai-game-creator-shell" -version = "0.1.12" +version = "0.1.19" edition = "2021" publish = false diff --git a/apps/ai-game-creator-shell/src-tauri/tauri.conf.json b/apps/ai-game-creator-shell/src-tauri/tauri.conf.json index 1eb8e0319..f9d8c1b0f 100644 --- a/apps/ai-game-creator-shell/src-tauri/tauri.conf.json +++ b/apps/ai-game-creator-shell/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "Genarrative AI Game Creator", - "version": "0.1.12", + "version": "0.1.19", "identifier": "world.genarrative.ai-game-creator", "build": { "beforeDevCommand": "npm --prefix ../.. run agc:serve", diff --git a/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md b/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md index 29eae7a7f..2ceda6e61 100644 --- a/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md +++ b/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md @@ -29,6 +29,13 @@ AGC 每次启动时由根窗口检查一次公开 OSS 更新清单。清单默 ## 发布约定 +> ⚠️ 发布新版本时,版本号提升只发生在构建/上传工作区内,**不会自动回写仓库**。 +> 因此每次发布完成后,必须手动把版本号变更提交回 `master`(范围覆盖 +> `package.json`、根 `package-lock.json`、`tauri.conf.json`、`Cargo.toml`、`Cargo.lock` +> 中的 AGC 包条目,且五处保持一致),否则仓库源码版本会长期停留在旧值, +> dev 客户端每次启动都会误报“发现新版本”,OSS 已发布版本与源码严重背离。 +> 提交标题建议使用“提升 AGC 版本至 x.y.z”。 + 当前发布目标固定为 Windows x64 NSIS。执行 `npm run ai-game-creator-shell:build` 会先读取 `VITE_AGC_UPDATE_MANIFEST_URL`(默认 `https://agc-dev.oss-rg-china-mainland.aliyuncs.com/agc/latest.json`)的 `latest.json`,取本地与 OSS 的较高版本并递增一个 patch,然后同步更新 package、Tauri 和 Cargo diff --git a/package-lock.json b/package-lock.json index 47cf1217e..627be402a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -93,7 +93,7 @@ }, "apps/ai-game-creator-shell": { "name": "@genarrative/ai-game-creator-shell", - "version": "0.1.12", + "version": "0.1.19", "dependencies": { "@cubone/react-file-manager": "^1.35.0", "@genarrative/image-canvas-core": "0.1.0", -- 2.52.0 From 78088e422af85395090b79ccd79d1e169fd47eae Mon Sep 17 00:00:00 2001 From: Suzumiya Date: Mon, 7 Sep 2026 12:52:03 +0800 Subject: [PATCH 2/8] =?UTF-8?q?AGC=20=E7=89=88=E6=9C=AC=E5=8F=B7=E4=BB=A5?= =?UTF-8?q?=E4=BB=93=E5=BA=93=E4=B8=BA=E5=87=86=EF=BC=8C=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=20bump-version=20=E6=8F=90=E5=8D=87=E7=89=88=E6=9C=AC=E5=91=BD?= =?UTF-8?q?=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 发布/构建不再自动递增版本、不再支持 AGC_RELEASE_VERSION 自由指定版本,改为读取仓库已提交的版本 - prepareReleaseVersion 只校验五个版本来源一致并返回仓库版本,不再改写版本文件 - 新增 apps/ai-game-creator-shell/scripts/bump-version.mjs,默认提升 patch,支持 minor/major/显式版本,写入五处并本地提交 - release:upload 发布前通过 assertVersionNotBelowOss 防降级:仓库版本低于 OSS 线上版本时中止,并提示先运行 bump-version - 新增根 npm run ai-game-creator-shell:bump-version 别名,并在 AGC 更新技术方案文档与 Jenkinsfile 中移除自由版本参数说明 --- apps/ai-game-creator-shell/package.json | 1 + .../scripts/build-release.mjs | 103 ++++++++++++++---- .../scripts/build-release.test.mjs | 13 ++- .../scripts/bump-version.mjs | 75 +++++++++++++ .../scripts/release-upload.mjs | 11 +- ...方案】AGC客户端更新检查与下载-2026-08-31.md | 61 +++++++---- .../Jenkinsfile.ai-game-creator-shell-build | 2 - package.json | 1 + 8 files changed, 217 insertions(+), 50 deletions(-) create mode 100644 apps/ai-game-creator-shell/scripts/bump-version.mjs diff --git a/apps/ai-game-creator-shell/package.json b/apps/ai-game-creator-shell/package.json index c5397c3b5..542010560 100644 --- a/apps/ai-game-creator-shell/package.json +++ b/apps/ai-game-creator-shell/package.json @@ -9,6 +9,7 @@ "dev-stack": "node scripts/start-dev-stack.mjs", "build": "node scripts/build-release.mjs", "release:upload": "node scripts/release-upload.mjs", + "bump-version": "node scripts/bump-version.mjs", "skill-pack:check": "node scripts/check-skill-pack.mjs", "skill-pack:sync": "node scripts/check-skill-pack.mjs --write", "skill-pack:test": "node --test scripts/check-skill-pack.test.mjs", diff --git a/apps/ai-game-creator-shell/scripts/build-release.mjs b/apps/ai-game-creator-shell/scripts/build-release.mjs index 03a61ba9d..a6c455ff3 100644 --- a/apps/ai-game-creator-shell/scripts/build-release.mjs +++ b/apps/ai-game-creator-shell/scripts/build-release.mjs @@ -49,16 +49,23 @@ function parseVersion(value, label) { return value; } -export function nextPatchVersion(localVersion, remoteVersion) { - const local = parseVersion(localVersion, '本地版本'); - const remote = - remoteVersion == null ? null : parseVersion(remoteVersion, 'OSS版本'); - const base = remote && compareVersions(remote, local) > 0 ? remote : local; - const [major, minor, patch] = base.split('.').map(Number); - if (patch === Number.MAX_SAFE_INTEGER) { - throw new Error(`版本号 patch 已达到上限:${base}`); +export function bumpVersion(current, target = 'patch') { + const [major, minor, patch] = + parseVersion(current, '当前版本').split('.').map(Number); + if (target === 'major') return `${major + 1}.0.0`; + if (target === 'minor') return `${major}.${minor + 1}.0`; + if (target === 'patch' || target == null) { + if (patch === Number.MAX_SAFE_INTEGER) { + throw new Error(`版本号 patch 已达到上限:${current}`); + } + return `${major}.${minor}.${patch + 1}`; } - return `${major}.${minor}.${patch + 1}`; + if (typeof target === 'string' && /^\d+\.\d+\.\d+$/u.test(target)) { + return parseVersion(target, '指定版本'); + } + throw new Error( + `无法识别的版本目标:${String(target)}(支持 patch / minor / major / 明确的三段版本号)`, + ); } async function readRemoteVersion() { @@ -88,14 +95,52 @@ function replaceVersionLine(source, version, pattern, label) { return source.replace(pattern, `$1${version}$3`); } -export async function prepareReleaseVersion() { - const localVersion = parseVersion(readPackageJson().version, '本地版本'); - const remoteVersion = await readRemoteVersion(); - const requestedVersion = process.env.AGC_RELEASE_VERSION?.trim(); - const nextVersion = requestedVersion - ? parseVersion(requestedVersion, '指定版本') - : nextPatchVersion(localVersion, remoteVersion); +const versionFileSources = [ + { + file: packageJsonPath, + pattern: /("version"\s*:\s*")([^"]+)(")/u, + label: 'package.json', + }, + { + file: rootPackageLockPath, + pattern: /("apps\/ai-game-creator-shell"\s*:\s*\{\s*\n\s*"name"\s*:\s*"@genarrative\/ai-game-creator-shell"\s*,\s*\n\s*"version"\s*:\s*")([^"]+)(")/u, + label: 'package-lock.json', + }, + { + file: tauriConfigPath, + pattern: /("version"\s*:\s*")([^"]+)(")/u, + label: 'tauri.conf.json', + }, + { + file: cargoManifestPath, + pattern: /(^\[package\][\s\S]*?^version\s*=\s*")([^"]+)(")/mu, + label: 'Cargo.toml', + }, + { + file: cargoLockPath, + pattern: /(^name\s*=\s*"genarrative-ai-game-creator-shell"\s*\nversion\s*=\s*")([^"]+)(")/mu, + label: 'Cargo.lock', + }, +]; +export function readLocalVersion() { + return parseVersion(readPackageJson().version, '本地版本'); +} + +export function validateVersionConsistency(expectedVersion) { + for (const source of versionFileSources) { + const match = fs.readFileSync(source.file, 'utf8').match(source.pattern); + const actual = match ? match[2].trim() : '<未找到>'; + if (actual !== expectedVersion) { + throw new Error( + `AGC 版本号不一致:${source.label} 应为 ${expectedVersion},实际 ${actual}`, + ); + } + } +} + +export function writeVersionFiles(version) { + const nextVersion = parseVersion(version, '目标版本'); const packageSource = fs.readFileSync(packageJsonPath, 'utf8'); fs.writeFileSync( packageJsonPath, @@ -151,14 +196,30 @@ export async function prepareReleaseVersion() { ), ); - console.log( - requestedVersion - ? `[ai-game-creator-shell] 使用指定版本 ${nextVersion}(本地 ${localVersion} / OSS ${remoteVersion ?? '不存在'})` - : `[ai-game-creator-shell] 版本 ${localVersion} / OSS ${remoteVersion ?? '不存在'} -> ${nextVersion}`, - ); return nextVersion; } +export function prepareReleaseVersion() { + const localVersion = readLocalVersion(); + validateVersionConsistency(localVersion); + console.log( + `[ai-game-creator-shell] 使用仓库版本 ${localVersion}(不再自动递增或自由指定版本)`, + ); + return localVersion; +} + +export async function assertVersionNotBelowOss(version) { + const remoteVersion = await readRemoteVersion(); + if (remoteVersion && compareVersions(version, remoteVersion) < 0) { + throw new Error( + `仓库版本 ${version} 低于线上 OSS 版本 ${remoteVersion}。请先运行 npm --prefix apps/ai-game-creator-shell run bump-version 提升版本后再发布。`, + ); + } + console.log( + `[ai-game-creator-shell] 线上 OSS 版本 ${remoteVersion ?? '不存在'},发布版本 ${version}`, + ); +} + export function runTauriBuild(args = []) { const noBundle = args.includes('--no-bundle'); const hasTarget = args.includes('--target'); 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 d2853082f..fdeb4200b 100644 --- a/apps/ai-game-creator-shell/scripts/build-release.test.mjs +++ b/apps/ai-game-creator-shell/scripts/build-release.test.mjs @@ -3,9 +3,9 @@ import { readFileSync } from 'node:fs'; import { test } from 'node:test'; import { + bumpVersion, compareVersions, createUpdateManifest, - nextPatchVersion, selectReleaseArtifact, } from './build-release.mjs'; @@ -55,11 +55,14 @@ test('manifest preserves multiline release notes', () => { } }); -test('next release version follows the higher local or OSS version', () => { +test('bump version follows the requested target', () => { assert.equal(compareVersions('0.1.15', '0.1.12'), 1); - assert.equal(nextPatchVersion('0.1.12', '0.1.15'), '0.1.16'); - assert.equal(nextPatchVersion('0.1.18', '0.1.15'), '0.1.19'); - assert.equal(nextPatchVersion('0.1.12', null), '0.1.13'); + assert.equal(compareVersions('0.1.12', '0.1.12'), 0); + assert.equal(bumpVersion('0.1.19', 'patch'), '0.1.20'); + assert.equal(bumpVersion('0.1.19'), '0.1.20'); + assert.equal(bumpVersion('0.1.19', 'minor'), '0.2.0'); + assert.equal(bumpVersion('0.1.19', 'major'), '1.0.0'); + assert.equal(bumpVersion('0.1.12', '0.1.25'), '0.1.25'); }); test('release upload forces overwrite for versioned artifact and latest pointer', () => { diff --git a/apps/ai-game-creator-shell/scripts/bump-version.mjs b/apps/ai-game-creator-shell/scripts/bump-version.mjs new file mode 100644 index 000000000..2723dffab --- /dev/null +++ b/apps/ai-game-creator-shell/scripts/bump-version.mjs @@ -0,0 +1,75 @@ +import { spawnSync } from 'node:child_process'; +import { fileURLToPath } from 'node:url'; +import path from 'node:path'; + +const appRoot = fileURLToPath(new URL('..', import.meta.url)); +const repoRoot = path.resolve(appRoot, '../..'); + +const { + bumpVersion, + readLocalVersion, + writeVersionFiles, +} = await import('./build-release.mjs'); + +const versionFiles = [ + 'apps/ai-game-creator-shell/package.json', + 'package-lock.json', + 'apps/ai-game-creator-shell/src-tauri/tauri.conf.json', + 'apps/ai-game-creator-shell/src-tauri/Cargo.toml', + 'apps/ai-game-creator-shell/src-tauri/Cargo.lock', +]; + +function parseArgs(argv) { + const args = argv.slice(2); + const explicitIndex = args.indexOf('--version'); + const explicit = explicitIndex >= 0 ? args[explicitIndex + 1] : null; + const target = + explicit ?? + args.find((arg) => arg === 'patch' || arg === 'minor' || arg === 'major') ?? + 'patch'; + return { target, noCommit: args.includes('--no-commit') }; +} + +function runGit(args) { + const result = spawnSync('git', args, { cwd: repoRoot, stdio: 'inherit' }); + if (result.error) throw result.error; + return result.status ?? 1; +} + +const { target, noCommit } = parseArgs(process.argv); +const current = readLocalVersion(); +const next = bumpVersion(current, target); +writeVersionFiles(next); + +if (noCommit) { + console.log( + `[bump-version] 版本 ${current} -> ${next}(dry-run,未提交,如需提交去掉 --no-commit)`, + ); + process.exit(0); +} + +const addStatus = runGit(['add', ...versionFiles]); +if (addStatus !== 0) process.exit(addStatus); + +const hasDiff = + spawnSync('git', ['diff', '--cached', '--quiet'], { + cwd: repoRoot, + }).status === 1; + +if (!hasDiff) { + console.log(`[bump-version] 版本未变化(已是 ${current}),未创建提交`); + process.exit(0); +} + +const commitStatus = runGit([ + 'commit', + '-m', + `提升 AGC 版本至 ${next}`, + '-m', + `- AGC 客户端版本由 ${current} 提升至 ${next}`, + '-m', + '- 同步更新 package.json、根 package-lock.json、tauri.conf.json、Cargo.toml、Cargo.lock 中的 AGC 包条目', +]); +if (commitStatus !== 0) process.exit(commitStatus); + +console.log(`[bump-version] 已提交版本 ${next}(本地提交,未推送)`); diff --git a/apps/ai-game-creator-shell/scripts/release-upload.mjs b/apps/ai-game-creator-shell/scripts/release-upload.mjs index ee5af4452..c0ee8bb0c 100644 --- a/apps/ai-game-creator-shell/scripts/release-upload.mjs +++ b/apps/ai-game-creator-shell/scripts/release-upload.mjs @@ -9,8 +9,12 @@ 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 { generateUpdateManifest, prepareReleaseVersion, runTauriBuild } = - await import('./build-release.mjs'); +const { + assertVersionNotBelowOss, + generateUpdateManifest, + prepareReleaseVersion, + runTauriBuild, +} = await import('./build-release.mjs'); function runOssutil(args) { const binary = process.env.OSSUTIL_BIN?.trim() || 'ossutil'; @@ -36,7 +40,8 @@ function runOssutil(args) { if (result.status !== 0) process.exit(result.status ?? 1); } -await prepareReleaseVersion(); +const releaseVersion = await prepareReleaseVersion(); +await assertVersionNotBelowOss(releaseVersion); runTauriBuild([]); const { artifact, manifestPath, manifest } = generateUpdateManifest(); const artifactKey = `agc/${manifest.version}/${path.basename(artifact)}`; diff --git a/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md b/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md index 2ceda6e61..73de52a2f 100644 --- a/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md +++ b/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md @@ -30,27 +30,50 @@ AGC 每次启动时由根窗口检查一次公开 OSS 更新清单。清单默 ## 发布约定 > ⚠️ 发布新版本时,版本号提升只发生在构建/上传工作区内,**不会自动回写仓库**。 -> 因此每次发布完成后,必须手动把版本号变更提交回 `master`(范围覆盖 -> `package.json`、根 `package-lock.json`、`tauri.conf.json`、`Cargo.toml`、`Cargo.lock` -> 中的 AGC 包条目,且五处保持一致),否则仓库源码版本会长期停留在旧值, -> dev 客户端每次启动都会误报“发现新版本”,OSS 已发布版本与源码严重背离。 -> 提交标题建议使用“提升 AGC 版本至 x.y.z”。 +> 🔑 版本号以仓库为准。发布流程不再自动递增版本,也不再支持 `AGC_RELEASE_VERSION` 自由指定版本。 +> 发布前必须先运行版本提升命令,把目标版本写回仓库并提交,发布只读取这份已提交的版本。 -当前发布目标固定为 Windows x64 NSIS。执行 `npm run ai-game-creator-shell:build` 会先读取 -`VITE_AGC_UPDATE_MANIFEST_URL`(默认 `https://agc-dev.oss-rg-china-mainland.aliyuncs.com/agc/latest.json`)的 -`latest.json`,取本地与 OSS 的较高版本并递增一个 patch,然后同步更新 package、Tauri 和 Cargo -版本后再向 Tauri 传入 `--target x86_64-pc-windows-msvc` 构建。OSS 清单首次不存在时按本地版本递增; -OSS 请求失败、清单格式错误或版本无效会终止发布,避免覆盖线上版本。构建完成后自动扫描 `.exe` -安装包,并在 `apps/ai-game-creator-shell/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/latest.json` -生成包含版本、下载地址、大小和 SHA-256 的清单。可通过 `AGC_BUILD_TARGET` 显式覆盖目标(发布仍应使用 -Windows x64),通过 `AGC_UPDATE_ARTIFACT` 指定要发布的安装包,通过 `AGC_UPDATE_OSS_BASE_URL` 指定 -OSS 前缀,通过 `AGC_RELEASE_VERSION` 指定三段版本号(仅在明确需要复现指定版本时使用),通过 -`AGC_UPDATE_RELEASE_NOTES` 写入发布说明,支持多行文本且保留内部换行;`--no-bundle` smoke 构建不会读取 OSS、修改版本或生成清单。 +**发布前先提升版本(开发者执行)** + +执行以下任一命令,会把 AGC 版本写入 `package.json`、根 `package-lock.json`、 +`tauri.conf.json`、`Cargo.toml`、`Cargo.lock` 五处并**本地提交**(不会推送): + +```bash +# 提升一个 patch(默认),例如 0.1.19 -> 0.1.20 +npm run ai-game-creator-shell:bump-version +npm run ai-game-creator-shell:bump-version -- patch + +# 提升 minor / major +npm run ai-game-creator-shell:bump-version -- minor +npm run ai-game-creator-shell:bump-version -- major + +# 指定明确的三段版本(一般只用于复现/回填) +npm run ai-game-creator-shell:bump-version -- --version 0.1.25 +``` + +提交标题固定为“提升 AGC 版本至 x.y.z”。只做本地提交,push 由开发者自行确认。 + +**发布只读仓库版本(`npm run ai-game-creator-shell:build` 与 `release:upload`)** + +构建/发布不再改写版本文件,而是读取仓库已提交版本,并在发布前做两件事: + +1. 校验五个版本来源一致,不一致会中止,防止漂移。 +2. 通过 `assertVersionNotBelowOss` 读取 OSS `latest.json`:若仓库版本**低于**线上版本会中止, + 并提示先运行 `bump-version`,避免回退线上版本;OSS 读取失败或清单格式错误同样会中止。 + 仓库版本等于或高于线上版本才放行。 + +当前发布目标固定为 Windows x64 NSIS,会向 Tauri 传入 `--target x86_64-pc-windows-msvc` 构建。 +构建完成后自动扫描 `.exe` 安装包,并在 +`apps/ai-game-creator-shell/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/latest.json` +生成包含版本、下载地址、大小和 SHA-256 的清单,版本取仓库 `package.json` 的 `version`。 +可通过 `AGC_BUILD_TARGET` 显式覆盖目标(发布仍应使用 Windows x64),通过 `AGC_UPDATE_ARTIFACT` +指定要发布的安装包,通过 `AGC_UPDATE_OSS_BASE_URL` 指定 OSS 前缀,通过 `AGC_UPDATE_RELEASE_NOTES` +写入发布说明(支持多行文本且保留内部换行);`--no-bundle` smoke 构建不会读取 OSS、修改版本或生成清单。 每次发布安装包上传完成后,再使用 ossutil 的 `--force` 覆盖上传同一目录生成的 `latest.json`,确保固定的 latest 指针和 `downloadUrl` 指向已存在的 OSS 对象;未显式强制覆盖时,ossutil 在目标已存在时会交互询问并按默认值跳过,不能作为 Jenkins 非交互发布方式。清单和安装包均使用公开可读对象,不在清单中保存凭据、签名或本地路径。构建脚本本身不负责上传 OSS,发布流水线通过 `release:upload` 完成上传。 如需一键构建并上传,可执行 `npm run ai-game-creator-shell:release:upload`。该命令要求本机已安装并配置 `ossutil`, -先按上述规则比较 OSS 版本、递增 patch、构建 Windows x64 NSIS,再上传安装包和 `latest.json`。默认上传到 +先按上述规则取仓库版本并校验、构建 Windows x64 NSIS,再上传安装包和 `latest.json`。默认上传到 `agc-dev` / `oss-rg-china-mainland.aliyuncs.com`,也可用 `AGC_OSS_BUCKET`、`AGC_OSS_ENDPOINT` 和 `OSSUTIL_BIN` 覆盖;本机执行时凭据由 ossutil 本机配置读取,不能写入仓库或命令行参数。 @@ -70,6 +93,6 @@ Jenkins Checkout 的 `git clean -fdx` 会清理该构建目录,因此每次全 Jenkins Job 在“Build and upload”阶段通过受保护凭据 ID `AliyunAccessKeyId` 和 `AliyunaccessKeySecret` 注入 AccessKey,仅在当前进程运行时传给 ossutil,不写入仓库、workspace 或构建日志; 本机运行仍使用 ossutil 配置。凭据必须具备 `PutObject` 权限;OSS 对客户端保持公共读即可,公共读本身不授予 -Jenkins 上传权限。由于版本号取决于 OSS 当前清单,Job 已关闭并发构建;若 Jenkins -上存在多个 AGC 发布 Job,还应使用同一个 Lockable Resource 串行化发布。Job 参数 -`AGC_RELEASE_VERSION` 留空时自动递增,填写后会使用指定版本并更新对应的 `latest.json`,因此回滚或测试旧版本前应确认不会覆盖线上更新入口。 +Jenkins 上传权限。由于版本号以仓库为准、发布只读仓库版本且禁止回退线上版本,Job 已关闭并发构建;若 Jenkins +上存在多个 AGC 发布 Job,还应使用同一个 Lockable Resource 串行化发布。发布前请先在仓库上运行 +`npm run ai-game-creator-shell:bump-version` 提升并提交版本,再触发发布流水线。 diff --git a/jenkins/Jenkinsfile.ai-game-creator-shell-build b/jenkins/Jenkinsfile.ai-game-creator-shell-build index 3e304cf63..31d5568be 100644 --- a/jenkins/Jenkinsfile.ai-game-creator-shell-build +++ b/jenkins/Jenkinsfile.ai-game-creator-shell-build @@ -21,7 +21,6 @@ pipeline { 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') text(name: 'AGC_UPDATE_RELEASE_NOTES', defaultValue: '', description: '可选,支持多行文本,写入 latest.json 的发布说明') string(name: 'OSSUTIL_BIN', defaultValue: 'ossutil', description: 'ossutil 或 ossutil.exe 的绝对路径/命令名') } @@ -127,7 +126,6 @@ pipeline { withEnv([ "PATH=${env.AGC_WINDOWS_PATH}", "OSSUTIL_BIN=${params.OSSUTIL_BIN}", - "AGC_RELEASE_VERSION=${params.AGC_RELEASE_VERSION}", "AGC_UPDATE_RELEASE_NOTES=${params.AGC_UPDATE_RELEASE_NOTES}", ]) { powershell ''' diff --git a/package.json b/package.json index 80aa34e94..ec97e50ac 100644 --- a/package.json +++ b/package.json @@ -172,6 +172,7 @@ "ai-game-creator-shell:dev-server": "npm --prefix apps/ai-game-creator-shell run dev-server", "ai-game-creator-shell:build": "npm --prefix apps/ai-game-creator-shell run build --", "ai-game-creator-shell:release:upload": "npm --prefix apps/ai-game-creator-shell run release:upload", + "ai-game-creator-shell:bump-version": "npm --prefix apps/ai-game-creator-shell run bump-version --", "ai-game-creator-shell:llm-status": "npm --prefix apps/ai-game-creator-shell run llm-status --", "ai-game-creator-shell:agent-task": "npm --prefix apps/ai-game-creator-shell run agent-task --", "agc:chat": "npm --prefix apps/ai-game-creator-shell run chat --", -- 2.52.0 From 57cd81d5518b7b51a11892c5313c3dbe1d68a38c Mon Sep 17 00:00:00 2001 From: Suzumiya Date: Mon, 7 Sep 2026 13:33:41 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20AGC=20=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E6=B5=8B=E8=AF=95=E5=9C=A8=20Windows=20=E4=B8=8A?= =?UTF-8?q?=E7=9A=84=E8=B7=AF=E5=BE=84=E9=97=AE=E9=A2=98=E5=B9=B6=E6=BE=84?= =?UTF-8?q?=E6=B8=85=20bump-version=20=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - build-release.test.mjs 用 fileURLToPath 替代 URL.pathname,修复 Windows 下 /C:/... 路径导致的 3 个用例失败(既有的跨平台问题) - bump-version.mjs 的 --no-commit 输出改为“已写入版本文件,未创建提交”,避免被误认为不改文件的干跑 --- .../ai-game-creator-shell/scripts/build-release.test.mjs | 9 ++++++--- apps/ai-game-creator-shell/scripts/bump-version.mjs | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) 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 fdeb4200b..912251c6e 100644 --- a/apps/ai-game-creator-shell/scripts/build-release.test.mjs +++ b/apps/ai-game-creator-shell/scripts/build-release.test.mjs @@ -1,6 +1,7 @@ import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; import { test } from 'node:test'; +import { fileURLToPath } from 'node:url'; import { bumpVersion, @@ -10,7 +11,9 @@ import { } from './build-release.mjs'; test('selects an explicit release artifact when configured', () => { - const artifactPath = new URL('../package.json', import.meta.url).pathname; + const artifactPath = fileURLToPath( + new URL('../package.json', import.meta.url), + ); const previous = process.env.AGC_UPDATE_ARTIFACT; process.env.AGC_UPDATE_ARTIFACT = artifactPath; try { @@ -30,7 +33,7 @@ test('does not select unsupported files', () => { test('manifest contains version, download URL and integrity fields', () => { const manifest = createUpdateManifest( - new URL('../package.json', import.meta.url).pathname, + fileURLToPath(new URL('../package.json', import.meta.url)), ); assert.match(manifest.version, /^\d+\.\d+\.\d+$/u); assert.match( @@ -46,7 +49,7 @@ test('manifest preserves multiline release notes', () => { process.env.AGC_UPDATE_RELEASE_NOTES = '第一行\n第二行\r\n第三行'; try { const manifest = createUpdateManifest( - new URL('../package.json', import.meta.url).pathname, + fileURLToPath(new URL('../package.json', import.meta.url)), ); assert.equal(manifest.releaseNotes, '第一行\n第二行\r\n第三行'); } finally { diff --git a/apps/ai-game-creator-shell/scripts/bump-version.mjs b/apps/ai-game-creator-shell/scripts/bump-version.mjs index 2723dffab..33205b4f3 100644 --- a/apps/ai-game-creator-shell/scripts/bump-version.mjs +++ b/apps/ai-game-creator-shell/scripts/bump-version.mjs @@ -43,7 +43,7 @@ writeVersionFiles(next); if (noCommit) { console.log( - `[bump-version] 版本 ${current} -> ${next}(dry-run,未提交,如需提交去掉 --no-commit)`, + `[bump-version] 版本 ${current} -> ${next}(已写入版本文件,未创建提交,可用 git diff 复核;去掉 --no-commit 即提交)`, ); process.exit(0); } -- 2.52.0 From f7a0adc6165584a456b4f5f0d6e12b80b4263c29 Mon Sep 17 00:00:00 2001 From: Suzumiya Date: Mon, 7 Sep 2026 13:38:17 +0800 Subject: [PATCH 4/8] =?UTF-8?q?bump-version=20=E9=BB=98=E8=AE=A4=E4=B8=8D?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=EF=BC=8C=E6=94=B9=E4=B8=BA=20--commit=20?= =?UTF-8?q?=E6=98=BE=E5=BC=8F=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - bump-version.mjs 默认只写入版本文件、不创建提交;需要提交时加 --commit - 增加保护:若工作区已带着一次未提交的提升,再 --commit 不会重复递增,直接提交现有改动 - 同步 AGC 更新技术方案文档的用法示例与说明 --- .../scripts/bump-version.mjs | 26 ++++++++++++++----- ...方案】AGC客户端更新检查与下载-2026-08-31.md | 14 +++++++--- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/apps/ai-game-creator-shell/scripts/bump-version.mjs b/apps/ai-game-creator-shell/scripts/bump-version.mjs index 33205b4f3..3911ce972 100644 --- a/apps/ai-game-creator-shell/scripts/bump-version.mjs +++ b/apps/ai-game-creator-shell/scripts/bump-version.mjs @@ -27,7 +27,7 @@ function parseArgs(argv) { explicit ?? args.find((arg) => arg === 'patch' || arg === 'minor' || arg === 'major') ?? 'patch'; - return { target, noCommit: args.includes('--no-commit') }; + return { target, commit: args.includes('--commit') }; } function runGit(args) { @@ -36,14 +36,28 @@ function runGit(args) { return result.status ?? 1; } -const { target, noCommit } = parseArgs(process.argv); +function hasUncommittedVersionChanges() { + return ( + spawnSync('git', ['diff', '--quiet', '--', ...versionFiles], { + cwd: repoRoot, + }).status === 1 + ); +} + +const { target, commit } = parseArgs(process.argv); const current = readLocalVersion(); -const next = bumpVersion(current, target); + +// 若版本文件已带着一次未提交的提升(例如先默认跑过一次),再 --commit 时不再重复递增,直接提交现有改动。 +const next = + commit && hasUncommittedVersionChanges() + ? current + : bumpVersion(current, target); + writeVersionFiles(next); -if (noCommit) { +if (!commit) { console.log( - `[bump-version] 版本 ${current} -> ${next}(已写入版本文件,未创建提交,可用 git diff 复核;去掉 --no-commit 即提交)`, + `[bump-version] 版本 ${current} -> ${next}(已写入版本文件,未创建提交;如需提交加 --commit)`, ); process.exit(0); } @@ -66,7 +80,7 @@ const commitStatus = runGit([ '-m', `提升 AGC 版本至 ${next}`, '-m', - `- AGC 客户端版本由 ${current} 提升至 ${next}`, + `- AGC 客户端版本提升至 ${next}`, '-m', '- 同步更新 package.json、根 package-lock.json、tauri.conf.json、Cargo.toml、Cargo.lock 中的 AGC 包条目', ]); diff --git a/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md b/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md index 73de52a2f..4d6fa256a 100644 --- a/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md +++ b/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md @@ -36,22 +36,30 @@ AGC 每次启动时由根窗口检查一次公开 OSS 更新清单。清单默 **发布前先提升版本(开发者执行)** 执行以下任一命令,会把 AGC 版本写入 `package.json`、根 `package-lock.json`、 -`tauri.conf.json`、`Cargo.toml`、`Cargo.lock` 五处并**本地提交**(不会推送): +`tauri.conf.json`、`Cargo.toml`、`Cargo.lock` 五处。**默认只写入版本文件、不会创建提交**; +需要创建提交时在命令末尾加 `--commit`(只做本地提交,push 由开发者自行确认): ```bash -# 提升一个 patch(默认),例如 0.1.19 -> 0.1.20 +# 提升一个 patch(默认),只写入版本文件,例如 0.1.19 -> 0.1.20 npm run ai-game-creator-shell:bump-version npm run ai-game-creator-shell:bump-version -- patch +# 提升版本并本地提交 +npm run ai-game-creator-shell:bump-version -- --commit + # 提升 minor / major npm run ai-game-creator-shell:bump-version -- minor npm run ai-game-creator-shell:bump-version -- major # 指定明确的三段版本(一般只用于复现/回填) npm run ai-game-creator-shell:bump-version -- --version 0.1.25 + +# 指定版本并提交 +npm run ai-game-creator-shell:bump-version -- --version 0.1.25 --commit ``` -提交标题固定为“提升 AGC 版本至 x.y.z”。只做本地提交,push 由开发者自行确认。 +若先用默认方式写入版本(未提交),再补 `--commit`,命令会识别到工作区已提升、直接提交现有改动, +**不会重复递增**。提交标题固定为“提升 AGC 版本至 x.y.z”。 **发布只读仓库版本(`npm run ai-game-creator-shell:build` 与 `release:upload`)** -- 2.52.0 From fcc3c39dad0b2db06ec672390dc9012f4df6d688 Mon Sep 17 00:00:00 2001 From: Suzumiya Date: Mon, 7 Sep 2026 14:03:41 +0800 Subject: [PATCH 5/8] =?UTF-8?q?bump-version=20=E6=8F=90=E4=BA=A4=E5=89=8D?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=EF=BC=8C=E5=AD=98=E5=9C=A8=E5=85=B6=E4=BB=96?= =?UTF-8?q?=E6=9A=82=E5=AD=98=E6=94=B9=E5=8A=A8=E6=97=B6=E4=B8=AD=E6=AD=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - --commit 在改动任何版本文件前先检查已暂存文件,发现版本文件外的暂存改动则中止并提示,避免误提交无关内容 - 同步 AGC 更新技术方案文档说明 --- .../scripts/bump-version.mjs | 32 +++++++++++++++++++ ...方案】AGC客户端更新检查与下载-2026-08-31.md | 3 +- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/apps/ai-game-creator-shell/scripts/bump-version.mjs b/apps/ai-game-creator-shell/scripts/bump-version.mjs index 3911ce972..9e4a9eb9a 100644 --- a/apps/ai-game-creator-shell/scripts/bump-version.mjs +++ b/apps/ai-game-creator-shell/scripts/bump-version.mjs @@ -44,7 +44,39 @@ function hasUncommittedVersionChanges() { ); } +function otherStagedFiles() { + const result = spawnSync( + 'git', + ['diff', '--cached', '--name-only'], + { cwd: repoRoot, encoding: 'utf8' }, + ); + if (result.status !== 0) { + throw new Error('无法读取已暂存文件列表'); + } + const versionSet = new Set(versionFiles); + return result.stdout + .split('\n') + .map((file) => file.trim()) + .filter(Boolean) + .filter((file) => !versionSet.has(file)); +} + const { target, commit } = parseArgs(process.argv); + +// 提交前先确认没有其他已暂存改动,避免把无关改动一并提交;若存在则在改动任何文件前中止。 +if (commit) { + const others = otherStagedFiles(); + if (others.length > 0) { + console.error( + `[bump-version] 检测到其他已暂存改动,为避免误提交,请先单独处理后再运行 --commit:\n ${others.join('\n ')}`, + ); + console.error( + '提示:用 git restore --staged 取消暂存,或先提交这些改动。', + ); + process.exit(1); + } +} + const current = readLocalVersion(); // 若版本文件已带着一次未提交的提升(例如先默认跑过一次),再 --commit 时不再重复递增,直接提交现有改动。 diff --git a/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md b/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md index 4d6fa256a..10a9367e4 100644 --- a/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md +++ b/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md @@ -59,7 +59,8 @@ npm run ai-game-creator-shell:bump-version -- --version 0.1.25 --commit ``` 若先用默认方式写入版本(未提交),再补 `--commit`,命令会识别到工作区已提升、直接提交现有改动, -**不会重复递增**。提交标题固定为“提升 AGC 版本至 x.y.z”。 +**不会重复递增**。提交前若检测到**除版本文件外的其他已暂存改动**,会中止并提示先处理,避免误提交无关内容。 +提交标题固定为“提升 AGC 版本至 x.y.z”。 **发布只读仓库版本(`npm run ai-game-creator-shell:build` 与 `release:upload`)** -- 2.52.0 From 64b9ccfb9d19507dc1aeaf2e19e4d666c81bdf27 Mon Sep 17 00:00:00 2001 From: Suzumiya Date: Mon, 7 Sep 2026 14:09:16 +0800 Subject: [PATCH 6/8] =?UTF-8?q?=E5=8F=91=E5=B8=83=E9=93=BE=E8=B7=AF?= =?UTF-8?q?=E5=8A=A0=E5=9B=BA=EF=BC=9A=E8=A6=81=E6=B1=82=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=B7=B2=E6=8F=90=E4=BA=A4=E5=90=8E=E5=86=8D=E5=8F=91=E5=B8=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 assertVersionCommitted:发布前确认 5 个版本来源相对 HEAD 已提交,避免仅 bump 未提交就 release 导致本地与 Jenkins 检出版本不一致 - release-upload 在取版本、OSS 防降级前调用该守卫 - 更新 AGC 更新技术方案文档,并补发布校验回归测试 --- .../scripts/build-release.mjs | 18 ++++++++++++++++++ .../scripts/build-release.test.mjs | 9 +++++++++ .../scripts/release-upload.mjs | 2 ++ ...术方案】AGC客户端更新检查与下载-2026-08-31.md | 4 +++- 4 files changed, 32 insertions(+), 1 deletion(-) 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 读取失败或清单格式错误同样会中止。 仓库版本等于或高于线上版本才放行。 -- 2.52.0 From 65012e89b6563086bafaf63f5a32bf0063324226 Mon Sep 17 00:00:00 2001 From: Suzumiya Date: Mon, 7 Sep 2026 14:10:13 +0800 Subject: [PATCH 7/8] =?UTF-8?q?=E7=BB=86=E5=8C=96=20AGC=20=E5=8F=91?= =?UTF-8?q?=E5=B8=83=E6=96=87=E6=A1=A3=EF=BC=9A=E5=8C=BA=E5=88=86=20build?= =?UTF-8?q?=20=E4=B8=8E=20release:upload=20=E7=9A=84=E6=A0=A1=E9=AA=8C?= =?UTF-8?q?=E8=8C=83=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - build 只校验五个版本来源一致;release:upload 在上传前额外校验版本已提交与防降级 --- .../【技术方案】AGC客户端更新检查与下载-2026-08-31.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md b/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md index a5bb692fe..757afc474 100644 --- a/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md +++ b/docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md @@ -62,14 +62,14 @@ npm run ai-game-creator-shell:bump-version -- --version 0.1.25 --commit **不会重复递增**。提交前若检测到**除版本文件外的其他已暂存改动**,会中止并提示先处理,避免误提交无关内容。 提交标题固定为“提升 AGC 版本至 x.y.z”。 -**发布只读仓库版本(`npm run ai-game-creator-shell:build` 与 `release:upload`)** +**构建/发布只读仓库版本(`npm run ai-game-creator-shell:build` 与 `release:upload`)** -构建/发布不再改写版本文件,而是读取仓库已提交版本,并在发布前做两件事: +构建与发布都不再改写版本文件,而是读取仓库版本。前者只校验五个版本来源一致(不一致会中止, +防止漂移);后者(`release:upload`)在上传前还会做两道校验: -1. 校验五个版本来源一致,不一致会中止,防止漂移。 -2. 校验版本相对 `HEAD` 已提交(`assertVersionCommitted`):若版本文件存在未提交改动会中止, +1. 校验版本相对 `HEAD` 已提交(`assertVersionCommitted`):若版本文件存在未提交改动会中止, 确保本地发布与 Jenkins 检出的是同一个版本。 -3. 通过 `assertVersionNotBelowOss` 读取 OSS `latest.json`:若仓库版本**低于**线上版本会中止, +2. 通过 `assertVersionNotBelowOss` 读取 OSS `latest.json`:若仓库版本**低于**线上版本会中止, 并提示先运行 `bump-version`,避免回退线上版本;OSS 读取失败或清单格式错误同样会中止。 仓库版本等于或高于线上版本才放行。 -- 2.52.0 From 2043f8c966a7ce09844cccde69b8bc1c4cacdb2f Mon Sep 17 00:00:00 2001 From: Suzumiya Date: Mon, 7 Sep 2026 14:59:30 +0800 Subject: [PATCH 8/8] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20bump-version=20?= =?UTF-8?q?=E8=84=9A=E6=9C=AC=E5=AF=BC=E5=85=A5=E6=8E=92=E5=BA=8F=E4=BB=A5?= =?UTF-8?q?=E9=80=9A=E8=BF=87=20lint:eslint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - bump-version.mjs 按 simple-import-sort 调整 node:child_process / node:path / node:url 导入顺序 --- apps/ai-game-creator-shell/scripts/bump-version.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ai-game-creator-shell/scripts/bump-version.mjs b/apps/ai-game-creator-shell/scripts/bump-version.mjs index 9e4a9eb9a..a5cb61483 100644 --- a/apps/ai-game-creator-shell/scripts/bump-version.mjs +++ b/apps/ai-game-creator-shell/scripts/bump-version.mjs @@ -1,6 +1,6 @@ import { spawnSync } from 'node:child_process'; -import { fileURLToPath } from 'node:url'; import path from 'node:path'; +import { fileURLToPath } from 'node:url'; const appRoot = fileURLToPath(new URL('..', import.meta.url)); const repoRoot = path.resolve(appRoot, '../..'); -- 2.52.0