《Wails 打包分发:GitHub Actions 平台矩阵》
要点
本地 wails build 出一个能跑的 exe 用不了十分钟,”分发”才是量级跳变:三个平台的产物格式完全不同、CI 上各有各的依赖坑、签名与否直接决定用户双击时看到什么。这篇按”本地跑通三平台 → Actions 矩阵自动化 → 打 tag 发版”的顺序走通全流程,签名与自动更新按真实边界处理——是什么就是什么,不硬凑。工程底座是剪贴板工具实战,测试流程在测试篇已过一遍,发版前照单重跑。
本文不做:代码签名(为什么不做有整段说明,不是偷懒)、应用商店上架(微软商店是另一套打包口径)、自动更新的完整实现(v2 没有内建更新器,给一句务实的替代方案)。Wails 版本口径为 v2.10.1(2025-02-24 发布),Go 1.23 与 1.24 均可。
三平台的产物差异
先把”要发出去的东西”列清楚,三行三样:
- Windows:
wails build -clean -nsis,产物是裸 exe 加一个 NSIS 安装器(build/bin 下带 installer 字样的 exe)。NSIS 由 CLI 在首次使用时自动下载,不用预装。WebView2 运行时的处理策略默认是 download(用户机器缺了就现场下),对国内网络不一定友好,可换 embed 内嵌安装包,代价是体积涨。 - macOS:
wails build -clean -platform darwin/universal,产物是 .app 包。universal 一次编译同时含 Intel 与 Apple Silicon 两个架构,是给不知道用户用什么机器的自己上的保险。分发形态通常再套一层 DMG 镜像。 - Linux:
wails build -clean,产物就是单二进制——别被”简单”骗了,目标机器必须装了 GTK3 与 WebKit2GTK 运行库才能跑,这让它天然适合发 tar 包给懂 Linux 的人,不适合当大众安装包。deb/AppImage 属于后处理话题,本文不展开。
DMG 自己一行命令就能打,macOS 自带的 hdiutil 就够:
hdiutil create -volname "ClipboardTool"
-srcfolder build/bin/ClipboardTool.app
-ov -format UDZO ClipboardTool.dmg
一个反直觉的事实:交叉编译不存在
Go 单二进制让人习惯性地以为”一台 Linux 机器 GOOS 一改出三份”,Wails 走不通——它依赖各平台的 WebView 系统库,构建必须走 CGO,Windows 的包只能在 Windows 上出,macOS 的只能在 macOS 上出。这不是缺陷是成本结构:CI 矩阵的每个平台各跑各的 runner,一台机器只出一份产物。理解了这一点,后面的 Actions 配置就是把这个事实翻译成 YAML。
本地验证的节奏建议是”一验二托”:在自己最熟的平台(多半就是开发机)把构建产物从头到尾验一遍——安装、启动、卸载;另外两个平台第一次先托付给 CI 出 artifact,下载到对应系统的机器或虚拟机上验。三者全部人工过一遍之前,别把 Release 当成”可用”的标志。CI 的绿只说明构建成功,不说明用户双击之后的体验成立,这两件事的分界线只有人肉验证能画。
GitHub Actions 矩阵
workflow 的骨架是 matrix:三个 include 条目,各指定 runner 系统与目标平台,产物统一传 artifact。完整可用版本:
name: release
on:
push:
tags: ["v*"]
jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
platform: windows/amd64
extra: "-nsis"
- os: macos-latest
platform: darwin/universal
extra: ""
- os: ubuntu-22.04
platform: linux/amd64
extra: ""
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: "1.23"
- uses: actions/setup-node@v4
with:
node-version: "20"
- name: Linux 构建依赖
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev
- name: 安装 Wails CLI
run: go install github.com/wailsapp/wails/v2/cmd/wails@latest
- name: 构建
run: wails build -clean -platform ${{ matrix.platform }} ${{ matrix.extra }} -ldflags "-X main.version=${GITHUB_REF_NAME}"
- name: 打 DMG(仅 macOS)
if: runner.os == 'macOS'
run: hdiutil create -volname ClipboardTool -srcfolder build/bin/ClipboardTool.app -ov -format UDZO build/bin/ClipboardTool.dmg
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os }}
path: build/bin/*
前端构建不用单独写步骤:wails build 会按 wails.json 里的 frontend:install / frontend:build 命令自己装依赖、自己打包前端,setup-node 是给 npm 用的。Linux 那格故意写 ubuntu-22.04 而不是 ubuntu-latest——ubuntu-latest 已是 24.04,仓库里删掉了 Wails v2 依赖的 libwebkit2gtk-4.0-dev,构建直接报 pkg-config 找不到 webkit2gtk-4.0,这是 2024 年下半年起最常被问的 Wails CI 问题。两条出路:像上面一样钉在 22.04;或者装 4.1 的包并加构建标签 wails build -tags webkit2_41,前提是 CLI 版本够新。钉旧版本省事,标签方案长久,选哪条都行,但必须显式选,”latest 一下应该能跑”在这格必挂。
版本号注入值得单独说:main.go 里声明 var version = "dev",关于窗口或日志把它打出来,发版时 ldflags 把 tag 名灌进去。没这一步,用户报问题你说不清他跑的是哪个包——发版系统的第一功臣不是上传,是可追溯。
打 tag 即发版
发版的触发器就是一个 git tag。矩阵构建完成后把三份产物挂到 GitHub Release 上,软硬两步:tag 触发的 workflow 里加一个发布 job(needs: build),用软传播的做法把 artifact 汇总上传:
release:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
path: dist
- uses: softprops/action-gh-release@v2
with:
files: dist/**/*
generate_release_notes: true
预期结果:仓库 Releases 页出现新条目,Windows 安装器、macOS DMG(workflow 里的打 DMG 步骤产出)、Linux tar 包三样齐全,Release Notes 由 GH 自动按 PR 生成。验收方式:换台没装过开发环境的机器,Windows 双击安装器装上、能启动能记录剪贴板;macOS 解开 DMG 拖进 Applications 能跑;Linux 用户按 README 先装 webkit2gtk 运行库再跑二进制。
版本号策略顺手定死:从 v0.1.0 起步,语义化递增,tag 名必须与 ldflags 注入的版本串一致——发版脚本里两者取同一个变量,人为对齐迟早失手。tag 打错了别硬改 Release,删 tag 重打一次比解释一个”0.2.1 修了 0.2.0 的 bug 但版本串写着 0.2.0″的发布省心得多。个人工具的发布频率不高,把这套动作写成 README 里的三行清单,下一次发版照抄即可。
自动更新一句实话:Wails v2 没有内建更新器。务实的替代是应用启动时请求 GitHub Releases 的 API 比对最新 tag,弹个”有新版本”的提示加下载链接,更新动作交还给人。覆盖式的自动升级逻辑不要手写——下载校验、断点、回滚,每一项都是一个坑位,单机工具用”提示+人点”足够体面。
代码签名:这篇为什么不做
把账摊开。macOS 侧签名要 Apple Developer Program 的 99 美元/年,之后还要走 Developer ID 公证流程,证书与公证在 CI 里各要一组密钥管理;Windows 侧代码签名证书是年费数百美元量级的开销,且即便签了,新证书的 SmartScreen 信誉从零起步,初期用户该看到的警告照样看到。对个人开源工具,这笔钱买来的体验提升有限;不签名的真实代价要向用户交代清楚——macOS 首次打开右键菜单里选”打开”,或用 xattr -cr 清掉隔离属性;Windows 拿到 SmartScreen 提示时点”更多信息→仍要运行”。把这两行写进 README,比装作”专业软件”诚实。等哪天用户量真到了,签名是可以后补的基础设施,不改变本文的任何产物结构。
两条判据帮你判断什么时候值得回头补签名:一是出现了”不懂技术的用户装不上”的真实反馈,且这些用户占目标人群可观比例;二是工具开始对收费或承载敏感数据,无签名的包会加剧信任成本。两条都不占之前,把时间花在手测清单与版本追溯上,回报率高得多。
常见坑
- ubuntu-latest 拿来就用:24.04 没有 libwebkit2gtk-4.0-dev,构建在依赖检查处报错。钉 22.04 或换 -tags webkit2_41,二选一,别抱侥幸。
- macOS 只出 amd64 或只出 arm64:macos-latest 的 runner 是 Apple Silicon 机器,不写 darwin/universal 时产物架构随构建机走,Intel 用户拿到的包跑不起来。
- 忘记 fail-fast: false:三平台并行时一挂全停,修一个平台要等下一整轮。矩阵发布场景默认建议关掉。
- NSIS 安装器在没网的环境下装不动:webview2 策略默认 download,离线环境换 embed,并接受包体变大。
- 版本号全靠 README 声明:二进制里没有版本字符串,事后无法对账。ldflags 注入是底线配置。
验收清单
- 本地三平台命令各自跑通一次(Windows 上出 NSIS 包;借 mac/Linux 机器或 CI 验证另两个),产物齐全。
- push 一个 v0.1.0 tag,三平台 job 全绿,Release 页三份产物可下载。
- 换一台干净 Windows 虚拟机或机器装安装器,主功能(复制、去重、重启恢复)过一遍手测清单。
- 应用内版本号与 tag 一致:二进制 -ldflags 注入的值在关于页或日志里可见。
- README 写明无签名的安装指引(macOS 右键打开 / xattr -cr;Windows 仍要运行的路径)与 Linux 运行库依赖。
分发跑通后,Wails 线的六件套就贯通了:从实战的并发设计,到测试分层,再到这篇的出包与发版,一个桌面工具从想法到用户手里只剩三台 runner 的距离。桌面端系列之后想扩产品形态,优先盯 v3 的正式发布,而不是往 v2 上加不属于自己的能力。
本文数据核对时间:2025-04-04:Wails v2.10.1(2025-02-24 发布)+ Go 1.23/1.24(1.24 GA 2025-02-11)+ Actions 矩阵(ubuntu-22.04 / macos-latest / windows-latest,checkout@v4、setup-go@v5、setup-node@v4、upload-artifact@v4、softprops/action-gh-release@v2);Linux 依赖与 -tags webkit2_41 以 Wails v2 官方文档口径为准。