Electron GitHub Actions 自动发包
打 tag 自动触发 → 多平台并行打包 → 产物自动上传到 GitHub Releases
手动在自己电脑上 build:win / build:mac / build:linux 打包,有两个痛点:一是一台电脑通常只能打自己这个系统的包,二是每次发版都要手动跑命令、手动传文件。用 GitHub Actions 可以做到:只在你想发版时打一个 tag,云端就自动帮你把三大平台的安装包都打好并挂到 Releases 上。
一、整体流程
核心思想:打包这件事交给云端的多台机器并行做,你只负责「打 tag」这个动作。
二、前置:electron-builder 的发布源配置
要让 electron-builder 知道「打完包传到哪」,需要在 electron-builder.yml 里配置 publish 为 github:
同时建议在 package.json 里补全仓库信息(开源项目规范,也方便 electron-builder 兜底读取):
这套
publish配置同时也是「自动更新」功能的更新源,运行时更新的详细做法见本目录的《Electron 自动更新升级》。发包和自动更新用的是同一份配置。
三、为什么用 tag 触发,而不是每次 push
发包是低频、重量级操作(三平台并行、每次几分钟、消耗 CI 额度),绝不能每次 git push 都跑。所以工作流只监听「推送 tag」这一种事件:
关键:push 下面只写了 tags、没有写 branches。效果如下:
这样日常开发随便推,只有明确要发版时打 vX.Y.Z 才会启动打包。
四、编写工作流
在仓库根目录新建 .github/workflows/release.yml:
几个要点解释:
matrix:一次定义三个平台,GitHub 会开三台不同系统的 runner 并行跑。想只发某个平台,删掉对应行即可。--publish always:强制打完就上传。不加这个参数默认不会上传。npx electron-builder:electron-builder 是 devDependency,npm ci之后就能直接用。
五、GH_TOKEN 从哪来
不需要你手动申请 token。 GitHub Actions 每次运行会自动注入一个临时的 secrets.GITHUB_TOKEN,把它赋值给 electron-builder 认识的环境变量 GH_TOKEN 即可:
要让这个 token 有「创建 Release、上传文件」的权限,两处二选一(工作流里写了 permissions 一般就够):
- 工作流顶部声明(推荐,已在上面写了):
- 或仓库
Settings → Actions → General → Workflow permissions选 Read and write permissions。
如果上传产物时报 403 Forbidden,基本都是权限没给够,检查上面两处。
六、版本号与 tag 必须对应
electron-builder 是按 package.json 里的 version 决定往哪个 Release 传的(tag 名 = v + version)。所以规矩是:先改版本号,再打对应的 tag,两者必须一致。
改版本号有两种方式,先理解 npm version 到底做了什么,就不会搞混了。
方式 A:npm version 一条命令搞定(推荐)
在工作区干净(没有任何未提交改动)的前提下运行:
它会一口气做三件事:
- 改
package.json(和package-lock.json)里的version - 自动
git commit这次改动(提交信息默认就是x.y.z) - 自动
git tag vx.y.z(v前缀是 npm 默认加的,正好对上工作流的v*)
⚠️ 前提是工作区必须干净。只要还有任何没提交的改动,它会直接报 Git working directory not clean 并拒绝执行——所以要先把代码改动都提交完,再跑 npm version。
跑完后,commit 和 tag 都还只在本地,要推两次:
为什么要推两次?
git push origin vx.y.z只推 tag,不会连带把那条 commit 推上去;漏了前面的git push,远程分支就少了这次版本提交。
方式 B:只改文件、自己控制提交
如果你想把「版本号改动」和「别的代码改动」放进同一个 commit,用 --no-git-tag-version 让 npm 只改文件、不提交、不打 tag:
直接手动编辑
package.json的version字段,效果和方式 B 一样——改完文件后自己 commit、打 tag、推送。
特例:如果 package.json 里的 version 已经是目标值了,npm version x.y.z 会报 Version not changed 拒绝执行。这时跳过 npm version,提交完直接手动打 tag 即可:git tag vx.y.z && git push origin vx.y.z。
最后再强调一遍:如果 tag 和 version 对不上(比如 version 是 1.0.0 却推了 v2.0.0 的 tag),electron-builder 仍会往 v1.0.0 的 Release 传,导致「tag 和产物对不上」。务必保持一致。
七、草稿 Release vs 直接发布
electron-builder 默认把产物传到一个 草稿(draft)Release,不会立刻公开。好处是可以先检查产物、补写更新日志,确认没问题再手动点 Publish release。
想让它跳过草稿、直接公开,在配置里加:
八、各平台注意点
代码签名(Windows 证书 / macOS 开发者证书)需要把证书和密码放进仓库 Secrets 再在工作流里引用,属于进阶话题,开源项目初期通常先发未签名版本。
九、完整发布操作(两种方式任选其一)
两种方式殊途同归,最终都是「远程有对应的 commit + 一个 vx.y.z 的 tag」,剩下的打包发布全由 CI 完成。选一种你顺手的即可。
方式 A:先提交干净,再用 npm version 自动打 tag
版本 bump 是独立的一条提交(信息就是版本号),历史清爽。缺点是跑 npm version 前必须先把工作区清空。
方式 B:把版本号和改动合进一个提交,再手动打 tag
版本 bump 和功能代码放在同一个 commit 里,适合「改完功能顺手发版」的场景。不要求工作区提前干净。
关键差异只在「版本提交」这一步:方式 A 让
npm version自动单独提交 + 打 tag(要求工作区干净);方式 B 用--no-git-tag-version只改文件,提交和打 tag 都自己来(可与其它改动合并)。两者都别漏了推送——commit 用git push,tag 用git push origin vx.y.z,缺一不可。
推完 tag 后(两种方式完全一样):
- 打开仓库 Actions 页,看到三平台的构建任务在跑。
- 全部跑完后,进 Releases 页,会有一个草稿 Release,里面挂着各平台安装包。
- 检查无误 → 编辑更新日志 → 点 Publish release 正式发布。
十、常见问题
Q:普通 push 会不会触发打包?
不会。工作流只监听 v* tag,日常推代码完全不受影响。
Q:git push --tags 会触发吗?
如果这次连带推送的 tag 里包含新的 v* tag,会触发——这是符合预期的。只要不打 v 开头的 tag 就不会。
Q:npm version 报 Git working directory not clean 怎么办?
说明还有改动没提交(你在用方式 A)。先 git status 看一眼,把所有改动 git add . && git commit 提交干净,再跑 npm version;或者改用方式 B 的 --no-git-tag-version。
Q:npm version 报 Version not changed 怎么办?
说明 package.json 的 version 已经是你要发的版本号了。跳过 npm version,直接手动打 tag:git tag vx.y.z && git push origin vx.y.z。
Q:某个平台失败了怎么办?
fail-fast: false 保证其它平台继续跑。修好后重新推 tag(需先删除旧 tag 或用新版本号),或在 Actions 页面点 Re-run。
Q:CI 太慢 / 只想发一个平台?
把 matrix.include 里不需要的平台行删掉即可,比如只留 windows-latest。
Q:想每次 push 到主分支就做代码检查(但不打包)?
那是另一个独立的 CI 工作流(只跑 lint + typecheck),和这个发布工作流互不影响,可单独再建一个 ci.yml。
相关阅读
- 《Windows 下 Electron 打包配置指南》——本地打包与 electron-builder.yml 详解
- 《Electron 自动更新升级》——运行时从 Releases 拉取更新,与本文共用同一份 publish 配置

