Files
HomeAgent/cmd/gui/package-config.test.mjs
JianFeeeee 8847ce4cfd fix(gui): 修发行打包的图标与资源漏装(Linux 包会缺星图依赖)
## 背景
上一提交修了 electron-packager 那条路径的 exe 图标。本提交处理另外两处
同类问题——**都是静默失败**:改了没人知道,坏了要等用户装上才发现。

## 1) package.json build 段(electron-builder 路径)
  · files 白名单漏了 icon.ico / icon-tray.png / icon-tray@2x.png
    ⇒ 这些文件不会被打进包,托盘与窗口图标在发行版里丢失
  · 补 win.target/win.icon;注意 electron-builder 的 icon 路径相对
    **项目目录**(package.json 所在)解析,不是相对输出目录
    (最初写成 'build/icon.ico',那会找不到文件 —— 已用存在性判据钉住)
  · icon.ico 含 256x256,满足 electron-builder 对 win 图标的要求

## 2) deploy/packaging/package-linux.sh(Linux 发行实际走这条)
  原实现手工 cp 七个文件:
    main.js / preload.js / package.json
    renderer/{index.html, app.js, style.css, mascot.svg}
  实测漏掉:
    · renderer/mascot.svg        —— 源码里根本不存在(真名 mascot.webp)
    · icon.svg / icon.ico / icon-tray*.png
    · renderer/icon.svg
    · renderer/vendor/*          ★★ 本次本地化新增的四个第三方库
                                  (three/OrbitControls/marked/purify)
                                  ⇒ Linux 发行包装完星图与 Markdown 渲染直接坏,
                                    且**没有任何构建报错**

改为:
  · renderer 按目录整体同步(cp -r "$gui_dir/renderer/.")
  · 根级 *.svg / *.ico / icon-tray*.png 同步
  · 新增必备文件校验:vendor 四库与 icon.svg 缺任一 ⇒ 报错并删目录跳过,
    沿用本脚本既有的"宁可不发,也不发装了跑不起来的包"原则

## 判据
新增 cmd/gui/package-config.test.mjs(进 npm test),14 条断言覆盖三条
打包路径的配置一致性。已做变异测试:Makefile 去 --icon、files 去 icon.ico、
package-linux.sh 还原逐文件 cp,三者均判红。

判据:cmd/gui npm test 全绿(60 条)。
2026-10-02 10:25:43 +08:00

139 lines
5.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// GUI 发行打包配置的一致性判据。
//
// ## 要判的是什么
//
// 两条打包路径的配置各自漏过东西,且都是**静默**失败:
//
// 1) electron-packager(make build-gui,Windows 发行 + 本机安装都走它)
// · 曾漏 --icon=icon.ico ⇒ exe 一直是 Electron 默认图标
// (已修:Makefile e79eff6)
//
// 2) package.json 的 build 段(electron-builder,Linux 发行走它)
// · files 白名单漏了 icon.ico / icon-tray*.png ⇒ 图标不进包
// · win.icon 路径写错(electron-builder 相对**项目目录**解析,
// 写 'build/icon.ico' 会找不到文件)
//
// 3) deploy/packaging/package-linux.sh 的手工组装曾逐文件 cp 七个文件,
// 漏掉 renderer/vendor/*(本地化的 four 个库)与全部图标文件
// ⇒ Linux 发行包装完星图与托盘图标直接坏,且**没有任何构建报错**
// (已修:改目录整体同步 + 必备文件校验)
//
// 打包配置类问题的特点是"改了没人知道、坏了要等用户装上才发现",
// 所以在这里钉死。
//
// 运行:node package-config.test.mjs
import { readFileSync, existsSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { dirname, join } from "node:path";
const here = dirname(fileURLToPath(import.meta.url));
const repoRoot = join(here, "..", "..");
const guiDir = here;
let failures = 0;
const check = (name, ok, detail) => {
if (ok) console.log(` ✓ ${name}`);
else {
failures++;
console.log(` ✗ ${name}${detail ? " — " + detail : ""}`);
}
};
// ── 1) Makefile: electron-packager 必须带 --icon ──────────────────────
const mk = readFileSync(join(repoRoot, "Makefile"), "utf8");
const buildGui = mk.slice(
mk.indexOf("build-gui:"),
mk.indexOf("\nbuild-static:"),
);
check("能定位 build-gui 目标", buildGui.length > 0);
check(
"★ build-gui 传 --icon(否则 exe 一直是 Electron 默认图标)",
/--icon[= ]\S*icon\.ico/.test(buildGui),
"缺 --icon ⇒ exe 内嵌图标为 Electron 默认",
);
check(
"build-gui 仍带 --no-sandbox",
/--no-sandbox/.test(buildGui),
"--no-sandbox 没了,本机可能起不来",
);
// ── 2) package.json build 段 ─────────────────────────────────────────
const pkg = JSON.parse(readFileSync(join(guiDir, "package.json"), "utf8"));
const files = pkg.build?.files || [];
check(
"★ files 白名单含 icon.ico",
files.includes("icon.ico"),
"files = " + JSON.stringify(files),
);
check(
"files 白名单含托盘图标",
files.includes("icon-tray.png") && files.includes("icon-tray@2x.png"),
"缺 icon-tray*.png ⇒ 托盘图标在发行包里丢失",
);
check(
"files 含 renderer/**/*(含 vendor/)",
files.some((f) => f.startsWith("renderer/")),
"renderer 未列入 ⇒ vendor 库不会进包",
);
// ── 3) win.icon 路径语义 ─────────────────────────────────────────────
// electron-builder 的 icon 相对**项目目录**(package.json 所在)解析。
// 写成 'build/icon.ico'(相对输出目录)会找不到文件。
const winIcon = pkg.build?.win?.icon;
check("配置了 win.icon", !!winIcon, "未配置 win.icon");
if (winIcon) {
check(
"★ win.icon 路径不是误写的 build/ 前缀",
!winIcon.startsWith("build/"),
`win.icon='${winIcon}' —— electron-builder 相对项目目录解析,` +
"带 build/ 前缀会找不到文件",
);
check(
"win.icon 指向的文件真实存在",
existsSync(join(guiDir, winIcon)),
`${winIcon} 不存在于 cmd/gui/`,
);
}
// ── 4) icon.ico 本身要含足够尺寸 ────────────────────────────────────
const ico = readFileSync(join(guiDir, "icon.ico"));
const isIco = ico.readUInt16LE(0) === 0 && ico.readUInt16LE(2) === 1;
check("icon.ico 是合法 ICO", isIco, "头部不是 00 00 01 00");
const icoCount = ico.readUInt16LE(4);
check(
"icon.ico 含多尺寸(含 256x256,electron-builder 需要)",
icoCount >= 2,
`只含 ${icoCount} 个尺寸`,
);
// ── 5) package-linux.sh 不得再逐文件手列 ────────────────────────────
const pkgLinux = readFileSync(
join(repoRoot, "deploy", "packaging", "package-linux.sh"),
"utf8",
);
check(
"★ package-linux.sh 按目录整体同步 renderer",
/cp -r "\$gui_dir\/renderer\/\."/.test(pkgLinux),
"仍在逐文件 cp ⇒ 新增资源(如 vendor/)不会被打进 Linux 包",
);
check(
"package-linux.sh 同步根级图标",
/cp "\$gui_dir"\/\*\.ico/.test(pkgLinux) &&
/icon-tray/.test(pkgLinux),
"未同步根级 ico / 托盘图标",
);
check(
"package-linux.sh 有必备文件校验",
/vendor\/three\.min\.js/.test(pkgLinux) && /rm -rf "\$gui_out"/.test(pkgLinux),
"缺必备文件校验 ⇒ 装完才发现坏包",
);
console.log("");
if (failures > 0) {
console.log(`全部失败:${failures} 条`);
process.exit(1);
}
console.log("全部通过");