跨平台构建矩阵:三系统两架构的 CI 成本与发布前置时间

一个人只有一台 Mac,却要交付 macOS、Windows 与 Linux 三个平台、两种架构的安装包。构建矩阵决定了每月花多少 CI 分钟、发布要等多久。本文拆开必须用原生 runner 的组合、签名密钥在 CI 的注入边界,以及从打 tag 到三平台可下载的前置时间。

交付能力的第一道瓶颈,通常不是代码,而是你能在多短时间内产出全部平台的包。

一、一台机器,六个产物

以下情境为教学假设,人物、引语和数字不代表经核实的真实案例。

顾帆的产品支持 macOS、Windows 与 Linux,每个平台都要出 x64 与 arm64 两个包。他的手写清单是六个产物。

最初他全部在本地构建:Mac 上打 macOS 包,开虚拟机打 Windows 包,Linux 包在容器里跑。一次完整发布要花掉一个下午,而且经常在最后一个产物上失败,只能从头再来。

迁移到 CI 后,时间降到四十分钟,但账单也来了:六个组合、每个组合装依赖与编译,每月 CI 分钟数远超预期。

矩阵不是「都跑一遍」这么简单。 哪些组合可以交叉编译、哪些必须原生、哪些可以只出一个通用包,决定了成本结构。

二、矩阵里哪些组合是必需的

目标能否交叉编译建议
macOS x64可在 arm64 上交叉,但签名与公证更顺用 macOS runner
macOS arm64同上与 x64 同机出通用包
Windows x64可在 Linux 交叉,但签名与安装器易出问题用 Windows runner
Windows arm64生态尚不完整按需求决定是否出
Linux x64容器即可用 Linux runner
Linux arm64可交叉按用户群决定

macOS 两个架构优先合并为通用包。 通用包体积更大,但只需一次签名、一次公证、一次验收,维护成本明显低于两个独立产物。

通用包也有代价。 体积接近两个架构之和,下载更慢;用户量小、包体大的产品,拆成两个包反而更合适。

Windows 建议用原生 runner。 交叉编译能出二进制,但安装器、签名工具与运行库检测在交叉环境下更容易出现难以复现的失败。

原生 runner 的排队时间要计入。 高峰期等待可能比构建本身更长;固定发布窗口时,把排队算进前置时间。

Linux 是最适合容器化的目标。 依赖可从镜像固定,构建可重复;arm64 是否要出,取决于是否有真实用户。

容器镜像要固定版本。 用 latest 标签会让同一份代码在不同时间产出不同结果;镜像摘要比标签更可靠。

每个组合都要有明确的保留理由。 说不出「谁在用这个组合」的,先停掉;矩阵每多一格,发布就多一次可能失败的机会。

三、CI 成本与前置时间

CI 账单由三部分构成:矩阵格数、单次时长与重跑次数。

月 CI 成本 = 矩阵格数 × 单次分钟 × 月发布次数 × 单价

示例:6 格 × 25 分钟 × 4 次/月 × 0.008 美元/分钟
月成本 ≈ 4.8 美元(不含缓存与存储)

前置时间 = 三平台产物全部可下载的时间 − 打 tag 的时间

重跑率比单价更影响成本。 一次失败重跑等于双倍开销;失败集中在依赖安装与签名步骤时,优先做缓存与预检。

失败要按阶段归类。 依赖安装、编译、签名、上传四类失败的处理方式不同;混在一起看,只会得出「CI 不稳定」。

缓存要分层。 依赖缓存、构建缓存与工具链缓存分开管理;把所有东西塞进一个缓存键,命中率反而下降。

并行度受限于密钥与配额。 签名步骤通常不能并行太多,因为共用同一份证书;把不签名的编译与签名拆成两个阶段,可以缩短总时长。

密钥轮换要有窗口。 换证书当天不要发布新版本;先确认旧证书仍可用,再安排切换。

前置时间要按最慢的一格算。 五个组合二十分钟完成、一个组合五十分钟,用户看到的仍是五十分钟。

产物命名要可检索。 版本、构建号、平台、架构四段式命名,比「final_v2_new」更容易在半年后找到。

夜间构建不能替代发布构建。 定时构建可以发现依赖漂移,但发布必须由明确的 tag 触发,并保留当时的完整日志。

四、密钥、产物与可复现

CI 里最危险的东西是签名密钥,最容易丢的东西是产物。

项目要求失败后果
密钥注入加密变量或密钥服务,按环境隔离泄露后可被冒名签名
密钥权限仅发布任务可读,PR 不可读任意分支都能产出可信包
产物保留至少保留最近若干版本与校验和回滚时找不到旧包
校验和每个产物生成并公开用户无法验证下载完整性
可复现固定工具链与依赖版本同 tag 两次构建结果不同

密钥不能出现在 PR 构建里。 外部贡献者提交的代码若能读取签名密钥,等于把发布权交出去;发布任务应只对受保护分支与 tag 开放。

只读密钥也要隔离。 构建只需读取依赖凭证,不应拥有发布权限;按任务拆分权限,泄露面更小。

产物要保留校验和。 用户下载后能核对哈希,是直装分发最基本的信任手段;校验和本身也要放在可长期访问的位置。

校验和要与发布公告一起发。 单独放在构建产物里,用户找不到;放在下载页与更新日志,才有人核对。

可复现构建要设边界。 完全可复现成本很高;一个人的产品至少做到「固定工具链版本、锁定依赖、记录构建环境」,让同一次发布可以解释。

构建日志要归档。 出问题时,日志是唯一能还原「当时到底跑了什么」的证据;只保留成功日志不够,失败日志同样要留。

五、行动清单与复算验收

  • 列出所有目标平台与架构,为每一格写明用户理由
  • 决定哪些组合合并为通用包,哪些停用
  • 把签名步骤与编译步骤分离,密钥只在发布任务可见
  • 为依赖、工具链与构建产物分别配置缓存
  • 记录连续三次发布的矩阵耗时与失败格
  • 为每个产物生成校验和,并与安装包一起发布
  • 固定工具链与依赖版本,记录构建环境
  • 归档成功与失败的构建日志,至少保留最近五个版本

验收标准:从打 tag 到三平台全部可下载,时间可预测且失败格可定位。 只回答「大概半小时」的,说明还没量过。

月 CI 成本 = 格数 × 单次分钟 × 月发布次数 × 单价
前置时间 = 最后一个产物可下载 − tag 时间
失败重跑率 = 重跑次数 ÷ 总构建次数

重跑率高于 20%:先修最常失败的那一格
前置时间波动超过 50%:说明有步骤在等待外部资源

使用边界与实操验收

本文只讲构建矩阵与 CI 成本,不涉及签名与公证的具体步骤(第 02、03 篇)、安装包格式(第 04 篇)与版本回滚(第 09 篇)。

多产品共享构建与部署底座属于共享底座:账号、计费、邮件与部署的复用边界 ;发布产物的长期归档属于代码与仓库:多远程、组织所有权、镜像与归档 。

本文也不主张「所有平台都要原生构建」。用户量极小的平台可以只提供交叉编译产物,并在下载页注明已验证范围;关键是把「验证过什么」说清楚,而不是假装全都验过。

验证以发布记录为准:连续五次发布,记录每格的耗时、失败原因与重跑次数。若某一格长期拖慢整体,优先考虑合并或停用,而不是加机器。

记录时把「排队时间」与「构建时间」分开。合并统计会让你误以为加机器有用,实际瓶颈在调度。

关键参考与核验范围

本文的矩阵与成本为教学演示,实际配额与单价请以所用 CI 服务为准。核验日期:2026-10-24。

上述两条只用于说明公开文档入口,不构成对任何 CI 服务的推荐。配额、镜像与计费方式会调整,实施前请核对当期文档。

系列导航

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「Indie」更多文章

  1. 开源项目验收:十项能力、四维评分与三种不该开源的项目
  2. 治理、fork 与退出:17 位贡献者、82% 的提交与一次改协议的代价
  3. 双许可与企业版:九家询价、两家成交与 4,800 美元