给 Electron 自动更新加发布闸时,我会先把通道和回滚证据拆开
最近给一个 Electron 桌面端工具接自动更新,初版只做启动后检查版本、下载完成后提示重启。演示环境没问题,内测时却暴露出三个盲点:灰度用户说不清自己为什么收到某个版本,失败日志只剩下载异常,回滚时也无法确认哪些客户端还停留在旧 metadata 上。后来我把自动更新拆成发布闸、客户端观测和回滚证据三块处理。

原创示意图:把 CI 构建、签名校验、更新源、通道选择、客户端下载和回滚证据放在同一条链路里观察。 来源:Codex image generation
问题背景
Electron 官方的 autoUpdater 文档提供了检查、下载、安装和事件监听能力,更新教程也强调需要更新服务或静态元数据来告诉客户端可用版本。桌面端发布的麻烦在于,用户手里的客户端可能长期在线,也可能几周不启动。一次有问题的更新包发出去后,影响面取决于通道、签名、metadata 缓存、客户端下载时机和用户是否选择重启。
关键难点
第一个难点是通道边界。stable、beta、internal 如果只写在构建脚本里,事故排查时很容易混乱。我需要在产物、metadata、客户端配置和日志里都能看到同一个 channel。第二个难点是签名和更新源。Electron 的代码签名文档把签名作为桌面分发里的基础安全动作,自动更新链路也要让签名产物和发布 metadata 对齐。第三个难点是回滚。已经下载完成但还没有重启的客户端、命中灰度但下载失败的客户端、读取了旧缓存的客户端,都需要留下可复盘证据。
解决思路
我把链路分成三张表。package facts 记录版本号、commit、平台、签名状态、文件摘要和生成时间。release decision 记录 channel、灰度比例、目标平台、允许升级的最低版本和回滚开关。client observation 记录客户端看到的 updateInfo、下载结果、用户选择、安装前版本和错误摘要。
如果项目使用 electron-builder,官方文档里有 electron-updater、发布源和 staged rollout 相关配置。我会把 stagingPercentage 当成发布策略输入,写入发布记录,同时在客户端日志里记录本次是否命中灰度。线上反馈出现异常时,可以先判断它是构建问题、发布策略问题,还是客户端环境问题。
关键步骤
落地时我先改 CI。每个平台构建完成后生成 release manifest,包含 version、channel、artifactName、sha512、signingProfile 和 gitCommit。发布脚本只允许从 manifest 读取产物路径,避免人工手填包名。客户端侧把更新检查放到主窗口 ready 之后,由主进程统一执行。渲染进程只展示状态,不直接拼 update feed。更新事件整理成 checking、available、downloaded、failed、deferred 几类,并附带 requestId。发布侧保留 pauseChannel 和 rollbackToVersion 两个开关,每次变化都写入审计记录。
可复用经验
Electron 自动更新要从第一天就保留证据。通道决定谁会收到,签名决定包是否可信,metadata 决定客户端看到什么,事件日志决定事故能不能复盘。把这几层拆开后,自动更新就从一次性发布动作变成可观测、可暂停、可回滚的桌面端工作流。后面接 AI 助手、RAG 本地索引或自动化插件时,也可以沿用同一套发布闸。
主要来源
Electron autoUpdater、Updating Applications、Code Signing、electron-builder Auto Update