From 500835407a6208b7de51e2ceaba841b4335075de Mon Sep 17 00:00:00 2001 From: kdletters Date: Tue, 22 Sep 2026 15:33:18 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20AGC=20Windows=20=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E7=9A=84=20NSIS=20=E5=9B=9E=E5=BD=92=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E8=B7=AF=E5=BE=84=E5=85=BC=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NSIS 缓存目录解析改为按目标平台使用 win32/posix path,避免 Windows 将 /tmp 解析到当前盘 回归测试改用 defaultAppRoot,并补齐 Windows/POSIX 路径断言,消除 C:\\C:\\ 拼坏与分隔符误判 同步 shared-memory,记录跨平台路径测试约束 --- .../scripts/nsis-toolset.mjs | 12 ++++++++--- .../scripts/nsis-toolset.test.mjs | 20 ++++++++++--------- docs/project-memory/shared-memory/pitfalls.md | 2 +- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/apps/ai-game-creator-shell/scripts/nsis-toolset.mjs b/apps/ai-game-creator-shell/scripts/nsis-toolset.mjs index d79c9f8a7..f52c82836 100644 --- a/apps/ai-game-creator-shell/scripts/nsis-toolset.mjs +++ b/apps/ai-game-creator-shell/scripts/nsis-toolset.mjs @@ -88,15 +88,21 @@ export function resolveNsisCacheDir( env = process.env, platform = process.platform, ) { + const pathImpl = platform === 'win32' ? path.win32 : path.posix; const explicit = env.AGC_TAURI_NSIS_CACHE_DIR?.trim(); - if (explicit) return path.resolve(explicit); + if (explicit) return pathImpl.resolve(explicit); // Jenkins Windows 节点以 SYSTEM 运行,ProgramData 稳定可写且不受工作区清理影响; // 缓存里只有待解压的原始归档,不会从该目录执行任何程序。 if (platform === 'win32') { const programData = env.ProgramData?.trim() || 'C:\\ProgramData'; - return path.join(programData, 'genarrative', 'tauri-nsis-cache'); + return pathImpl.join(programData, 'genarrative', 'tauri-nsis-cache'); } - return path.join(os.homedir(), '.cache', 'genarrative', 'tauri-nsis-cache'); + return pathImpl.join( + os.homedir(), + '.cache', + 'genarrative', + 'tauri-nsis-cache', + ); } /** 与 tauri-bundler 相同的镜像开关语义,便于构建机绕过不可达的 GitHub。 */ diff --git a/apps/ai-game-creator-shell/scripts/nsis-toolset.test.mjs b/apps/ai-game-creator-shell/scripts/nsis-toolset.test.mjs index 26faca27e..d5ce2fbf0 100644 --- a/apps/ai-game-creator-shell/scripts/nsis-toolset.test.mjs +++ b/apps/ai-game-creator-shell/scripts/nsis-toolset.test.mjs @@ -7,6 +7,7 @@ import { test } from 'node:test'; import JSZip from 'jszip'; import { + defaultAppRoot, ensureNsisToolset, extractNsisArchive, NSIS_ARCHIVE_ASSET_NAME, @@ -23,10 +24,7 @@ import { verifyNsisToolset, } from './nsis-toolset.mjs'; -const appRoot = path.resolve( - path.dirname(new URL(import.meta.url).pathname), - '..', -); +const appRoot = defaultAppRoot(); const silentLogger = { log() {}, warn() {} }; function createSandbox() { @@ -98,6 +96,14 @@ test('NSIS 工具链目录与 Tauri useLocalToolsDir 配置保持一致', () => }); test('缓存目录默认落在工作区之外并支持环境变量覆盖', () => { + assert.equal( + resolveNsisCacheDir({ AGC_TAURI_NSIS_CACHE_DIR: 'D:\\agc-cache' }, 'win32'), + 'D:\\agc-cache', + ); + assert.equal( + resolveNsisCacheDir({ ProgramData: 'D:\\ProgramData' }, 'win32'), + path.win32.join('D:\\ProgramData', 'genarrative', 'tauri-nsis-cache'), + ); assert.equal( resolveNsisCacheDir( { AGC_TAURI_NSIS_CACHE_DIR: '/tmp/agc-cache' }, @@ -105,13 +111,9 @@ test('缓存目录默认落在工作区之外并支持环境变量覆盖', () => ), '/tmp/agc-cache', ); - assert.equal( - resolveNsisCacheDir({ ProgramData: 'D:\\ProgramData' }, 'win32'), - path.join('D:\\ProgramData', 'genarrative', 'tauri-nsis-cache'), - ); assert.ok( resolveNsisCacheDir({}, 'linux').endsWith( - path.join('.cache', 'genarrative', 'tauri-nsis-cache'), + path.posix.join('.cache', 'genarrative', 'tauri-nsis-cache'), ), ); }); diff --git a/docs/project-memory/shared-memory/pitfalls.md b/docs/project-memory/shared-memory/pitfalls.md index 0e5823240..b229b2883 100644 --- a/docs/project-memory/shared-memory/pitfalls.md +++ b/docs/project-memory/shared-memory/pitfalls.md @@ -5455,7 +5455,7 @@ Cocos Creator 根目录由 `package.json.creator.version` 与普通 `assets/` - 原因:tauri-bundler 的 `download_and_verify` 现场从 GitHub 取 NSIS 工具链,只有一次机会、没有重试;响应体被截断即报 `io: unexpected end of file`,看起来像打包错误其实是网络问题。Checkout 阶段的 `git clean -fdx` 每次都会清掉 `target/.tauri`,所以每个构建都要重新下载,在受限网络下必然反复失败。 - 处理:新增 `apps/ai-game-creator-shell/scripts/nsis-toolset.mjs` 与 `ensure-nsis-toolset.mjs`,在 `buildRelease`(Windows 目标且需要打包时)与 Jenkins `Tauri NSIS toolchain` 阶段按固定 SHA1 预置 `target/.tauri/NSIS`:原始归档带 4 次重试,缓存在工作区外的 `%ProgramData%\genarrative\tauri-nsis-cache`(可用 `AGC_TAURI_NSIS_CACHE_DIR` 覆盖),镜像开关沿用 bundler 的 `TAURI_BUNDLER_TOOLS_GITHUB_MIRROR_TEMPLATE` / `TAURI_BUNDLER_TOOLS_GITHUB_MIRROR`。该阶段同时执行 `makensis.exe -VERSION`,把 2026-09-02 记录的缓存目录不可执行问题也提前到编译之前暴露。Checkout 阶段改为 `git clean -fdx -e apps/ai-game-creator-shell/src-tauri/target/.tauri`:Tauri 的工具缓存位于工作区内,裸 `git clean -fdx` 会连它一起删,排除后同一节点的稳态构建不再需要联网,只有冷缓存(新节点、工作区重建)才下载。 - 验证:`node --test apps/ai-game-creator-shell/scripts/nsis-toolset.test.mjs`(已就绪零下载复用、缓存离线还原、失败重试、哈希不符与归档越界失败关闭)与 `node --test apps/ai-game-creator-shell/scripts/build-release.test.mjs`;真实节点上该阶段必须早于 Rust 编译失败关闭。 -- 注意:不要改回 `bundle.useLocalToolsDir: false` 去用 `%LOCALAPPDATA%`,也不要依赖 PATH 里预装的 `makensis`;升级 `@tauri-apps/cli` 时同步核对归档 URL、SHA1 与必需文件清单。 +- 注意:不要改回 `bundle.useLocalToolsDir: false` 去用 `%LOCALAPPDATA%`,也不要依赖 PATH 里预装的 `makensis`;升级 `@tauri-apps/cli` 时同步核对归档 URL、SHA1 与必需文件清单。回归测试自身也必须跨平台:仓库根目录用 `fileURLToPath(new URL(...))` / `defaultAppRoot()` 解析,不能用 `URL.pathname` 得到 `/C:/...` 后再 `path.resolve`;模拟 Windows 与 POSIX 缓存路径时要分别使用 `path.win32` 与 `path.posix`,不要用当前节点的原生分隔符断言另一平台。 ## AGC 登录态续期必须同步本地运行时