给 autoSSL 补上 GitHub Windows 打包与 Draft Release 的实战记录
autoSSL 这种桌面工具,如果只有“本地能跑”,其实离真正可交付还差一步。尤其是面向 Windows 用户时,团队里不可能永远靠某一台开发机手工打包,再靠聊天工具传安装包。只要产品准备进入更稳定的迭代阶段,GitHub 上可重复执行的 Windows 打包链路就会变成基础设施,而不是可选项。
这次我给 autoSSL 做的事情并不复杂,但很实用:把原来停留在本地 electron-builder 的打包方式,推进成了两条 GitHub Actions 工作流。一条负责在 windows-latest 上生成可下载的 Windows 构建产物,另一条负责在打 tag 或手动触发时生成 draft release。过程中还顺手处理了一个很典型的工程问题:项目里依赖了本地 file: 包,开发机没问题,到了 GitHub runner 却会直接装不上。
后续更新: 这套链路已经在 GitHub 上真实跑通,
macOS和Windows安装包都已产出,并且已经发布为公开 release:https://github.com/zzhi191/autossl-downloads/releases/tag/autossl-v1.0.0
为什么这一步值得做,而不是继续手工打包
很多 Electron 项目在比较早期的时候,都会停留在“开发者自己本地执行一次 npm run electron:build”的阶段。这种方式能用,但有几个问题会很快暴露出来:
- 产物不可重复验证。你今天在本地打出来的包,和我明天在另一台机器上打出来的包,未必完全一致。
- Windows 用户拿到安装包之后出了问题,团队很难回到“到底是哪次构建、基于哪个提交、用什么依赖状态打出来的”去定位。
- 一旦需要给外部用户、客户或测试团队发安装包,靠手工传文件会越来越乱。
- 如果后面要做增量更新、release 节点管理或者签名,手工模式会越来越像临时方案。
所以这次我对 autoSSL 的目标不是“把打包命令搬到 GitHub 上”,而是先把最小但完整的一条链路补齐:
- GitHub 上能针对 Windows 构建
- 构建产物能被标准化下载
- 打 tag 或手动触发时能生成 draft release
- 当前边界说清楚:可测试、可分发,但还是 unsigned
做到这一步,团队后面再讨论签名、自动更新、正式 release 策略,才有稳定基座。
这次我最后落成了哪两条工作流
autoSSL 现在有两条和 Windows 打包相关的 GitHub Actions:
1. autossl-windows-build.yml
这条工作流主要解决“先把 Windows 构建产物稳定跑出来”的问题。
它支持:
- 手动从 Actions 页面运行
- push 到
main/master/develop - 修改
autoSSL/**的 PR 时触发
它做的事情很直接:
- 在
windows-latest上 checkout 仓库 - 安装
autoSSL的依赖 - 执行前端构建
- 执行
npm run electron:build:win - 上传
.exe、.blockmap、latest*.yml为 workflow artifacts
这条工作流的意义,不是直接对外发版,而是先确认:GitHub 的 Windows runner 上,当前仓库确实能稳定把安装包打出来。
2. autossl-release-windows.yml
第二条工作流负责 draft release。
它支持两种触发方式:
- push 一个 tag,格式为
autossl-v* - 在 Actions 页面手动运行,并填写
release_tag
我后面又补了一层很小但很必要的防呆:手动触发时会校验 release_tag 格式,必须像:
autossl-v1.0.0
如果 tag 不规范,工作流会在一开始就失败,而不是到了发布那一步才出奇怪问题。
它最终会:
- 在
windows-latest上执行npm run electron:build:win - 创建一个 draft GitHub Release
- 把 Windows
.exe、.blockmap、latest*.yml附到 release 上
这一步的价值在于,autoSSL 不再只有“Actions 里有个 artifact”,而是已经进入了比较接近正式交付的节奏:一条明确的 release 工作流,和一个可复核的 draft release 节点。
这次真正有意思的坑,不是 Electron,而是本地 file: 依赖
如果只是给 Electron 项目加一条 Windows build workflow,很多人会以为事情到这里就结束了。但这次 autoSSL 有一个更贴近真实工程的问题:
"@certd/plugin-lib": "file:../packages/plugins/plugin-lib"
这在本地开发时很方便,因为开发者机器上可能有完整 monorepo 结构,file: 依赖可以直接引用本地包目录。但 GitHub runner 不会天然拥有这套本地目录结构。如果仓库本身又没有把 ../packages/plugins/plugin-lib 一起提交进去,那么工作流里直接 npm ci 大概率就会失败。
这个问题不罕见。很多项目在“本地开发舒服”和“CI 可复现”之间,都会先偏向前者,等到真要上流水线时才发现隐藏耦合。
我这次没有为了 CI 去改坏本地开发体验,而是选了一个更稳的过渡方案:
- 本地
package.json继续保留file:依赖,方便开发 - GitHub Actions 里在安装前,临时把
@certd/plugin-lib改成 npm 上可用的已发布版本
换句话说,我没有强行把开发态和发布态揉成一种依赖结构,而是明确承认它们不同,再在 CI 里做一层有意识的适配。
这类处理方式的好处是:
- 不破坏当前本地研发流程
- 可以尽快把 Windows 打包跑通
- 后面如果 monorepo 结构统一了,或者私有包分发方案成熟了,再回头收敛也不晚
当然,这也意味着当前 workflow 不是“完美状态”,而是“清楚边界的工程化过渡状态”。我反而觉得这种状态更真实。
实际怎么触发 Windows 构建和 draft release
如果你只是想确认 GitHub 上能不能把 Windows 包打出来,先跑 build workflow 就够了。
方式一:先跑 Windows Build
打开 Actions,运行:
AutoSSL Windows Build
跑完后,到 Artifacts 页面下载:
autossl-windows-bundle
里面会有:
*.exe*.blockmaplatest*.yml
这是最适合做“先验证 GitHub runner 构建链路是否可用”的一步。
方式二:直接出 draft release
如果你已经准备进入 release 节点,有两种方式。
方案 A:push tag
git tag autossl-v1.0.0
git push origin autossl-v1.0.0
方案 B:手动触发 release workflow
在 Actions 页面运行:
AutoSSL Release Windows
并填写:
release_tag = autossl-v1.0.0
跑完之后,到 GitHub Releases 页面,你会看到一个 draft release,附件就是这次 Windows 构建结果。
我更推荐的顺序是:
- 先至少成功跑一次
AutoSSL Windows Build - 确认当前仓库在 GitHub Windows runner 上构建无误
- 再跑 release workflow 出 draft release
这样比上来直接发 release 更稳,因为你把“构建问题”和“发布问题”拆开了。
现在这套方案已经解决了什么,还没解决什么
已经解决的部分
autoSSL可以在 GitHub 上针对 Windows 平台打包autoSSL可以在 GitHub 上针对 macOS 平台打包- 构建结果能通过 artifact 下载
- 可以通过 tag 或手动输入 tag 生成 draft release
- 首个公开 release 已经成功发布
- release 产物已经包含安装包和更新元数据
- 本地
file:依赖对 CI 的阻塞被显式兜住了
还没解决的部分
- Windows 签名证书还没接入,所以当前仍然是 unsigned 安装包
- 当前 release 名称和 tag 策略已经够用,但后面还可以继续做得更整洁
- Linux 发布策略还没有同步扩展
这几个边界并不是缺点本身,关键是它们被明确说出来了。很多流水线问题最麻烦的地方,不是功能没做,而是团队误以为“它已经可以正式发版了”。在我看来,知道自己当前处在哪一层成熟度,和补功能一样重要。
如果你也在做 Electron 桌面工具,这次经验里最值得复用的是什么
回头看,这次最有价值的不是某一行 YAML,而是三件事:
第一,先把 build 和 release 分开
很多项目一开始就想一步到位,结果 build、artifact、release、签名、自动更新全混在一条 workflow 里,出问题很难拆。
我现在更倾向于先分两层:
- 第一层:确认 GitHub runner 能稳定构建
- 第二层:在构建稳定的前提下再挂 release
这会让后面的排查和演进轻很多。
第二,不要回避开发态和发布态的差异
本地 file: 依赖和 CI 可复现性之间,本来就容易冲突。最怕的是一边假装两者完全一样,一边在流水线里反复踩坑。
更现实的做法是:
- 承认它们不同
- 明确在哪一层做适配
- 把这个适配写进 workflow 和文档,而不是留在某个人脑子里
第三,先把边界写清楚
比如这次我会明确写:
- 能在 GitHub 上打 Windows 包
- 能出 draft release
- 但当前仍是 unsigned
- 且还没在 GitHub 上真实跑通验证
这会直接减少误解。工程里很多返工,本质上都来自“大家以为它已经是下一阶段了”。
结语
给 autoSSL 补上 GitHub 上的 Windows 打包和 draft release 流水线,并不是什么惊天动地的大工程,但它是一个非常典型的“产品从能开发,往能交付迈一步”的动作。
真正有价值的,不只是多了两份 workflow 文件,而是这次顺手把几个关键问题一起理顺了:
- Windows 安装包怎么标准化生成
- draft release 怎么形成固定出口
- 本地
file:依赖怎么在 CI 里兜住 - 当前 release 的成熟度边界怎么说清楚
如果后面还要继续往前走,我会优先做这两件事:
- 继续补上 Windows 代码签名与 macOS 签名 / notarization
- 再考虑自动更新链路和更稳定的 release 节点管理
对桌面工具来说,很多时候最难的不是“写出功能”,而是把交付链路补成团队可以重复使用、别人也能接手的样子。autoSSL 这一步,我觉得已经开始像一个真正准备长期维护的产品了。
