fix(pack): Windows 打包条目带目录前缀 —— 与 macOS 产物结构不一致
CI 在 f85acad 上红了:`✗ zip 内未找到条目 node.exe: release/nodeagent-win-x64.zip`
(而本地 macOS 全绿 —— 方向恰好相反)。根因是两平台用了不同打包器:
- macOS/Linux: `cd <dir> && zip -r <out> .` → 条目是裸名 `node.exe`
- Windows : `Compress-Archive -Path '<dir>\*'` → 条目带前缀 `<dir>/node.exe`
两处一起修:
1. `scripts/lib/zip-pe-arch.mjs`:条目名匹配改用 **basename**,兼容两种打包方式。
已用构造的带前缀 zip 实测通过,并注入错架构验证守卫仍会红。
2. `scripts/pack.mjs`:Windows 分支改用 .NET `ZipFile::CreateFromDirectory`
—— 它打包**目录内容**,条目同样是裸名,从根上消除两平台产物结构差异。
否则 CI 校验的产物与发布产物**不同构**,校验本身的价值打折;
且「解压后双击 install.cmd」的说明会因多一层目录而失配。
教训:**「本地全绿」≠「Windows 绿」** —— 平台差异只有真 runner 能暴露(第 N 次实证)。
This commit is contained in:
1 parent
f85acad5db
commit
5e6231493e
2 files changed
+18
-4
No files matched your search
@@ -49,7 +49,13 @@ export function readZipEntry(zipPath, entryName) {
|
||||
const commentLen = buf.readUInt16LE(off + 32);
|
||||
const localOff = buf.readUInt32LE(off + 42);
|
||||
const name = buf.toString('utf8', off + 46, off + 46 + nameLen);
|
||||
if (name === entryName) {
|
||||
// 条目名匹配用 **basename**,而不是完整名 —— 因为两平台的打包器不一样:
|
||||
// macOS/Linux:`cd <dir> && zip -r <out> .` → 条目是裸名 `node.exe`
|
||||
// Windows :`Compress-Archive -Path <dir>\*` → 条目带前缀 `<dir>/node.exe`
|
||||
// 2026-10-11 真例:只比完整名会让「本地(macOS)全绿、CI(Windows)全红」,
|
||||
// 且方向恰好相反 —— 而 CI 是唯一会跑 Windows 打包路径的地方。
|
||||
const entryBase = name.replace(/\\/g, '/').split('/').pop();
|
||||
if (entryBase === entryName) {
|
||||
const lNameLen = buf.readUInt16LE(localOff + 26);
|
||||
const lExtraLen = buf.readUInt16LE(localOff + 28);
|
||||
const start = localOff + 30 + lNameLen + lExtraLen;
|
||||
|
||||
+11
-3
@@ -249,15 +249,23 @@ async function main() {
|
||||
// 把预共享密钥打进包里等于公开密钥。install.cmd 在文件缺失时会自动生成新密钥
|
||||
// (生成在安装目录,只留在被控端本机),所以排除它不影响安装。
|
||||
if (process.platform === 'win32') {
|
||||
// Windows:GitHub runner / 多数 Windows 没有 Info-ZIP,改用 PowerShell 的 Compress-Archive。
|
||||
// 先删掉 PSK.txt(若存在)再压 —— Compress-Archive 无 -x 排除参数。
|
||||
// Windows:GitHub runner / 多数 Windows 没有 Info-ZIP。
|
||||
// 先删掉 PSK.txt(若存在)再压 —— 打包器无法按需排除单个文件。
|
||||
const psk = join(PKG_DIR, 'PSK.txt');
|
||||
if (existsSync(psk)) rmSync(psk, { force: true });
|
||||
// ⚠️ 刻意不用 `Compress-Archive -Path '<dir>\*'`:它会把**目录名当前缀**写进条目
|
||||
// (产物变成 `<dir>/node.exe`),而 macOS 的 `cd <dir> && zip -r .` 是**裸名** `node.exe`
|
||||
// —— 两平台产物**结构不一致**。看着是小事,代价却不小:
|
||||
// ① 按条目名取文件的校验会失配(2026-10-11 真例:CI 在 Windows 上报
|
||||
// 「zip 内未找到条目 node.exe」,而 macOS 本地全绿 → 方向恰好相反);
|
||||
// ② CI 校验的产物与发布产物**不同构**,校验价值打折。
|
||||
// 改用 .NET 的 ZipFile::CreateFromDirectory —— 它打包**目录内容**,条目同样是裸名。
|
||||
execFileSync(
|
||||
'powershell',
|
||||
[
|
||||
'-NoProfile', '-Command',
|
||||
`Compress-Archive -Path '${PKG_DIR}\*' -DestinationPath '${zipOut}' -Force`,
|
||||
`Add-Type -AssemblyName System.IO.Compression.FileSystem; ` +
|
||||
`[IO.Compression.ZipFile]::CreateFromDirectory('${PKG_DIR}', '${zipOut}')`,
|
||||
],
|
||||
{ stdio: 'inherit' },
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user