跳到主要内容

给 autoSSL 补上 GitHub Windows 打包与 Draft Release 的实战记录

· 阅读需 9 分钟
一介布衣
全栈开发者

autoSSL 这种桌面工具,如果只有“本地能跑”,其实离真正可交付还差一步。尤其是面向 Windows 用户时,团队里不可能永远靠某一台开发机手工打包,再靠聊天工具传安装包。只要产品准备进入更稳定的迭代阶段,GitHub 上可重复执行的 Windows 打包链路就会变成基础设施,而不是可选项。

这次我给 autoSSL 做的事情并不复杂,但很实用:把原来停留在本地 electron-builder 的打包方式,推进成了两条 GitHub Actions 工作流。一条负责在 windows-latest 上生成可下载的 Windows 构建产物,另一条负责在打 tag 或手动触发时生成 draft release。过程中还顺手处理了一个很典型的工程问题:项目里依赖了本地 file: 包,开发机没问题,到了 GitHub runner 却会直接装不上。

后续更新: 这套链路已经在 GitHub 上真实跑通,macOSWindows 安装包都已产出,并且已经发布为公开 release: https://github.com/zzhi191/autossl-downloads/releases/tag/autossl-v1.0.0

为什么这一步值得做,而不是继续手工打包

很多 Electron 项目在比较早期的时候,都会停留在“开发者自己本地执行一次 npm run electron:build”的阶段。这种方式能用,但有几个问题会很快暴露出来:

  • 产物不可重复验证。你今天在本地打出来的包,和我明天在另一台机器上打出来的包,未必完全一致。
  • Windows 用户拿到安装包之后出了问题,团队很难回到“到底是哪次构建、基于哪个提交、用什么依赖状态打出来的”去定位。
  • 一旦需要给外部用户、客户或测试团队发安装包,靠手工传文件会越来越乱。
  • 如果后面要做增量更新、release 节点管理或者签名,手工模式会越来越像临时方案。

所以这次我对 autoSSL 的目标不是“把打包命令搬到 GitHub 上”,而是先把最小但完整的一条链路补齐:

  1. GitHub 上能针对 Windows 构建
  2. 构建产物能被标准化下载
  3. 打 tag 或手动触发时能生成 draft release
  4. 当前边界说清楚:可测试、可分发,但还是 unsigned

做到这一步,团队后面再讨论签名、自动更新、正式 release 策略,才有稳定基座。

这次我最后落成了哪两条工作流

autoSSL 现在有两条和 Windows 打包相关的 GitHub Actions:

1. autossl-windows-build.yml

这条工作流主要解决“先把 Windows 构建产物稳定跑出来”的问题。

它支持:

  • 手动从 Actions 页面运行
  • push 到 main / master / develop
  • 修改 autoSSL/** 的 PR 时触发

它做的事情很直接:

  1. windows-latest 上 checkout 仓库
  2. 安装 autoSSL 的依赖
  3. 执行前端构建
  4. 执行 npm run electron:build:win
  5. 上传 .exe.blockmaplatest*.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 不规范,工作流会在一开始就失败,而不是到了发布那一步才出奇怪问题。

它最终会:

  1. windows-latest 上执行 npm run electron:build:win
  2. 创建一个 draft GitHub Release
  3. 把 Windows .exe.blockmaplatest*.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
  • *.blockmap
  • latest*.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 构建结果。

我更推荐的顺序是:

  1. 先至少成功跑一次 AutoSSL Windows Build
  2. 确认当前仓库在 GitHub Windows runner 上构建无误
  3. 再跑 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 的成熟度边界怎么说清楚

如果后面还要继续往前走,我会优先做这两件事:

  1. 继续补上 Windows 代码签名与 macOS 签名 / notarization
  2. 再考虑自动更新链路和更稳定的 release 节点管理

对桌面工具来说,很多时候最难的不是“写出功能”,而是把交付链路补成团队可以重复使用、别人也能接手的样子。autoSSL 这一步,我觉得已经开始像一个真正准备长期维护的产品了。