From 14f5963706be964fc734d5ff3e45b4bf5c37f33c Mon Sep 17 00:00:00 2001 From: Bill Date: Thu, 8 Oct 2026 13:25:01 +0800 Subject: [PATCH] build: drop MSI installer, NSIS exe only electron-updater never supported MSI auto-updates; the exe is the only installer from v1.0.22 on. release.cjs no longer expects/uploads the msi. --- AGENTS.md | 6 +++--- CHANGELOG.en.md | 3 +++ CHANGELOG.ja.md | 3 +++ CHANGELOG.md | 3 +++ CHANGELOG.zh-TW.md | 3 +++ electron-builder.yml | 15 ++------------- package.json | 2 +- scripts/release.cjs | 12 +++++------- 8 files changed, 23 insertions(+), 24 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 593b9b7..1afba15 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,7 +10,7 @@ Electron + electron-vite + React 终端工具(本地终端 / SSH / SFTP)。 - 测试:`npm test`(**npm 生命周期先自动跑 `pretest` 做类型检查**,再 `node tests/build-bundles.cjs` 重建 esbuild bundle,然后依次跑可离线运行的 18 个测试:ssh-loopback、commands-store、connections-store、settings-store、local-path-grants、lock-store、lock-controller、lock-shortcuts、hl-split-smoke、hl-rules、reserved-accelerators、ipc-guard、updater-fallback、log-sanitizer、sftp-timeout、terminal-title、zmodem-e2e、ssh-session-e2e、sysinfo-e2e;真实服务器测试需 JD_* 凭据,不在此列) - 依赖分类规则:**只有 `src/main/`/`src/preload/` 实际 import 的包才能进 `dependencies`**(node-pty/ssh2/zmodem.js/font-list/electron-updater);纯渲染层依赖一律 devDependencies(Vite 全量打包进 out/renderer,`externalizeDepsPlugin` 不作用渲染层)——这条让 asar 从 98MB 瘦到 8.1MB,加新依赖时别放错边 - 下载量统计:`node scripts/download-stats.cjs`(Gitea + GitHub release 资产的 download_count 汇总;GitHub 优先直连、失败自动回退 `HTTPS_PROXY`/本地 7897;更新通道无计数接口不计入) -- 打包:`npm run dist`(**生命周期先自动跑 `predist` → `npm test`,即类型检查 + 18 个离线测试全部通过后才 build/package**,typecheck 全程只跑一次;predist 末尾的 `npm install --package-lock-only` 会把 `package-lock.json` 根版本号对齐 `package.json`,**发布提交必须带上 package-lock.json**),产物在 `release/`(msi + exe + latest.yml + blockmap) +- 打包:`npm run dist`(**生命周期先自动跑 `predist` → `npm test`,即类型检查 + 18 个离线测试全部通过后才 build/package**,typecheck 全程只跑一次;predist 末尾的 `npm install --package-lock-only` 会把 `package-lock.json` 根版本号对齐 `package.json`,**发布提交必须带上 package-lock.json**),产物在 `release/`(exe + latest.yml + blockmap) - GitHub Actions:`.github/workflows/ci.yml` 在 windows-latest + Node 22 上跑 `npm ci` / `npm test`(含 pretest typecheck)/ `npm run build`,只做验证,不打包安装器、不发布 - 国内网络需镜像:`ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/ ELECTRON_BUILDER_BINARIES_MIRROR=https://npmmirror.com/mirrors/electron-builder-binaries/ npm run dist` - 依赖一致性闸门:`predist` 开头跑 `node scripts/verify-deps.cjs`(逐条比对 `node_modules` 与 `package-lock.json` 的版本,跨平台 optional 依赖缺失跳过;不一致就 exit 1)——`npm install --package-lock-only` **只重算 lockfile、不碰 node_modules**(本版 npm 还会把 `node_modules/.package-lock.json` 一并重写成理想树,制造「已经装好了」的假象),所以**改动依赖版本后必须真实 `npm install` 或 `npm ci` 再构建**,别指望 lockfile 对齐就等于树里换了包;v1.0.21 的中文输入法回归正是这个坑(`@xterm/xterm` 锁 6.1.0-beta.304,树里还是 6.0.0,打进去的是旧代码) @@ -34,7 +34,7 @@ Electron + electron-vite + React 终端工具(本地终端 / SSH / SFTP)。 2. `node scripts/sync-changelog.cjs` 把发布说明并入 `CHANGELOG*.md` —— **必须在 `npm run dist` 之前**:更新日志以 `?raw` 打进安装包(「关于」页离线读),`release.cjs` 也校验 `CHANGELOG.md` 已含该版本号 3. `npm run dist` 构建 4. `node scripts/release.cjs <版本号>`,例如 `node scripts/release.cjs 1.0.14`(**不带 skip 参数**,Gitea 与 GitHub 一起发) - - Gitea:release(msi + exe 资产)→ Gitea 更新通道(`api/packages/admin/generic/openterminal-update/stable`:exe.blockmap → exe → release-notes.md → **latest.yml 最后**) + - Gitea:release(exe 资产)→ Gitea 更新通道(`api/packages/admin/generic/openterminal-update/stable`:exe.blockmap → exe → release-notes.md → **latest.yml 最后**) - GitHub:release 资产再次随版本同步发布(exe + exe.blockmap + latest.yml),electron-updater 标准 GitHub provider 直接吃 release 资产 - 通道不再先删旧版:新版本文件全部传完、latest.yml 生效后才清掉上一版 exe/blockmap,中途失败不会把通道打空;同一版本可重复运行(release 复用、已传资产跳过) - 上传前先比通道版本:`assertNoDowngrade()` 读通道 latest.yml,若线上版本**高于**待发布版本就直接拒绝——三条本地护栏只比本地产物,旧分支发旧版本号会一路通过,覆盖 latest.yml 之后 `pruneChannel` 会把线上新版本的 exe/blockmap 删掉 @@ -47,7 +47,7 @@ Electron + electron-vite + React 终端工具(本地终端 / SSH / SFTP)。 - 检查更新:**GitHub 优先**(走系统代理;前置 20 秒连通性探测 `probeGithub`——探测失败/超时直接兜底 Gitea,不给 electron-updater 挂起的机会),失败回退国内 Gitea 通用包通道(强制直连,不走系统代理)。 electron-updater 用独立 session(partition `electron-updater`),代理模式在 `useFeed` 里按源切换 - 更新日志:Gitea 仓库是私有的(匿名 API 404),改为从更新通道的 `release-notes.md` 读取(直连 session `openterminal-update-direct`),再回退 Gitea/GitHub releases API -- electron-updater 不支持 MSI 自动更新,自动更新只走 NSIS exe +- 自动更新只走 NSIS exe;自 v1.0.22 起不再构建 MSI 安装包(electron-updater 本就不支持 MSI 自动更新) - 每次 checkForUpdates 都被 **30s 整体超时**包住(`withTimeout`):electron-updater 自带的 60s 只是 socket 空闲超时,慢滴流响应能一直占住它。超时按普通失败走 GitHub→Gitea 回退,但**被放弃的检查取消不掉**,而 electron-updater 对并发检查去重(返回同一个 in-flight promise),所以兜底那次共用被放弃的 promise——它同样被超时兜住,最终落到错误态,不会永远停在「检查中」 - 更新日志 / releases API 的 fetch 都带 `AbortSignal.timeout(15s)`(`directFetch` 与 `fetchChangelog` 里的 `net.fetch`):卡住的通道必须让位给下一个来源,不能把「关于」页吊住 diff --git a/CHANGELOG.en.md b/CHANGELOG.en.md index 72ab3da..00546aa 100644 --- a/CHANGELOG.en.md +++ b/CHANGELOG.en.md @@ -5,6 +5,9 @@ ### IME - **Fixed: Chinese IME candidate window not following the caret** (regression in v1.0.21): the v1.0.21 build environment had a terminal component dependency that did not match the locked version, so the installer shipped an older build without the upstream IME fix; this release restores the terminal component version used by v1.0.20, and the candidate window follows the caret again. +### Installer +- The MSI installer is discontinued (electron-updater never supported MSI auto-updates); the NSIS exe is now the only installer format. + ### Internal - The packaging pipeline now verifies dependency consistency before building: installed dependencies are compared against the lockfile and the build aborts on any mismatch, preventing this class of issue from recurring. diff --git a/CHANGELOG.ja.md b/CHANGELOG.ja.md index a651083..3466166 100644 --- a/CHANGELOG.ja.md +++ b/CHANGELOG.ja.md @@ -5,6 +5,9 @@ ### IME - **中国語 IME の候補ウィンドウがキャレットに追従しない問題を修正**(v1.0.21 でのリグレッション):v1.0.21 のビルド環境では端末コンポーネントの依存がロックされたバージョンと一致しておらず、インストーラーには上流の IME 修正を含まない古いビルドが同梱されていました。本バージョンでは v1.0.20 と同じ端末コンポーネントに戻し、候補ウィンドウが再びキャレットに追従します。 +### インストーラー +- MSI インストーラーの提供を終了しました(electron-updater は MSI の自動更新に非対応のため)。今後は NSIS exe インストーラーに統一されます。 + ### 内部 - パッケージング前に依存関係の整合性チェックを追加:インストール済み依存とロックファイルを照合し、不一致があればビルドを中止します。同種の問題の再発を防ぎます。 diff --git a/CHANGELOG.md b/CHANGELOG.md index e0f7e76..f15d3d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ ### 输入法 - **修复中文输入法候选窗不跟随光标**(v1.0.21 回归):v1.0.21 的构建环境中终端组件依赖未按锁定版本安装,安装包实际打进的是不含上游输入法修复的旧版本;本版本恢复 v1.0.20 所用的终端组件版本,候选窗重新紧贴光标。 +### 安装包 +- 不再提供 MSI 安装包(electron-updater 本就不支持 MSI 自动更新),统一使用 NSIS exe 安装包。 + ### 内部 - 打包流程新增依赖一致性校验:构建前自动比对实际安装的依赖与锁定清单,不一致即中止,防止同类问题再次发生。 diff --git a/CHANGELOG.zh-TW.md b/CHANGELOG.zh-TW.md index 34bc9a7..10878ff 100644 --- a/CHANGELOG.zh-TW.md +++ b/CHANGELOG.zh-TW.md @@ -5,6 +5,9 @@ ### 輸入法 - **修復中文輸入法候選視窗不跟隨游標**(v1.0.21 回歸):v1.0.21 的建置環境中終端機元件相依未按鎖定版本安裝,安裝包實際打包的是不含上游輸入法修復的舊版本;本版本恢復 v1.0.20 所用的終端機元件版本,候選視窗重新緊貼游標。 +### 安裝包 +- 不再提供 MSI 安裝包(electron-updater 本就不支援 MSI 自動更新),統一使用 NSIS exe 安裝包。 + ### 內部 - 打包流程新增相依一致性校驗:建置前自動比對實際安裝的相依與鎖定清單,不一致即中止,防止同類問題再次發生。 diff --git a/electron-builder.yml b/electron-builder.yml index 834f447..bdbf004 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -16,23 +16,12 @@ asarUnpack: # @lydell/node-pty ships prebuilt binaries; do not trigger a rebuild. npmRebuild: false -# Electron-updater only supports NSIS auto-updates (MSI has no update channel). -# The NSIS .exe + latest.yml get uploaded together; MSI is manual/enterprise only. +# NSIS exe is the only installer: electron-updater only supports NSIS +# auto-updates, so the MSI (no update channel) was dropped in v1.0.22. win: target: - - target: msi - target: nsis -msi: - oneClick: false - # Fixed upgrade code keeps the upgrade chain consistent across releases. - upgradeCode: "{5ab9f79e-e4eb-4052-9df6-3af3a301ab0a}" - artifactName: ${productName}-${version}-setup.${ext} - # Shortcuts need an ; build/icon.png (auto-converted to .ico) provides it. - # Without an icon the WiX shortcut Icon reference fails to link (LGHT0094). - createDesktopShortcut: true - createStartMenuShortcut: true - nsis: oneClick: false allowToChangeInstallationDirectory: true diff --git a/package.json b/package.json index cd4ef8b..ec1c41e 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "pretest": "npm run typecheck", "test": "node tests/build-bundles.cjs && node tests/ssh-loopback.mjs && node tests/commands-store.mjs && node tests/connections-store.mjs && node tests/settings-store.mjs && node tests/local-path-grants.mjs && node tests/lock-store.mjs && node tests/lock-controller.mjs && node tests/lock-shortcuts.mjs && node tests/reserved-accelerators.mjs && node tests/.terminal-title.cjs && node tests/ipc-guard.mjs && node tests/updater-fallback.mjs && node tests/log-sanitizer.mjs && node tests/sftp-timeout.mjs && node tests/.hl-split-smoke.cjs && node tests/.hl-rules.cjs && node tests/zmodem-e2e.mjs && node tests/ssh-session-e2e.mjs && node tests/sysinfo-e2e.mjs", "predist": "node scripts/verify-deps.cjs && npm test && npm install --package-lock-only", - "dist": "electron-vite build && electron-builder --win msi nsis", + "dist": "electron-vite build && electron-builder --win nsis", "dist:dir": "electron-vite build && electron-builder --win --dir" }, "dependencies": { diff --git a/scripts/release.cjs b/scripts/release.cjs index a05e43d..e8ee2aa 100644 --- a/scripts/release.cjs +++ b/scripts/release.cjs @@ -42,14 +42,12 @@ const env = Object.fromEntries( ) const notes = fs.readFileSync(path.join(ROOT, 'RELEASE_NOTES.md'), 'utf8') const R = path.join(ROOT, 'release') -const msi = path.join(R, `OpenTerminal-${V}-setup.msi`) const exe = path.join(R, `OpenTerminal-${V}-setup.exe`) -const files = [msi, exe] -// --channel-only republishes the update channel, which carries the NSIS exe and -// its blockmap (electron-updater cannot consume an MSI) — the msi is a release -// asset only, so demanding it here would block the repair path this mode exists -// for. The channel's own file list is validated in giteaChannel(). -for (const f of CHANNEL_ONLY ? [exe] : files) { +const files = [exe] +// Only the NSIS exe is built (the MSI was dropped in v1.0.22 — electron-updater +// never supported it). The channel's own file list is validated in +// giteaChannel(). +for (const f of files) { if (!fs.existsSync(f)) { console.error('missing build artifact:', f); process.exit(1) } } // Guard rails: the artifacts must belong to the version being published —