在團隊规模变大之后,"谁的电脑能出包"这件事本身就会变成瓶颈。我们把 iOS 项目的 CI/CD 整体迁移到Kvmkit 的 Mac mini M4 雲主机之后,出包等待時間明显缩短,簽署事故也几乎归零。这篇手记记录了从零搭建这套流水線时踩过的坑,以及最终收敛出来的Fastfile与快取策略,供同样在评估雲端 Mac 的團隊参考。
为什么選擇雲端 Mac mini M4 做 CI/CD
Xcode 的建置是典型的"计算密集 + 强相依性系統版本"的任务,本机 Runner 很难长期稳定维护。選擇雲端 Mac 節點主要基于三点判断:
- 规格可控:映像固定 Xcode 与命令行工具版本,不会因为某人手动升级系統而"團隊里只有他能編譯"。
- 随时扩容:发版前的回归测试可以临时多开几个節點并行跑,跑完即释放,不用为峰值常年预留硬體。
- 7×24 值守:M4 晶片待机功耗低,夜间建置、定时安全扫描都可以放心常驻运行,不用担心电费或噪音。
我们踩过的第一个坑:以为「雲主机」等于「远程顯示器」,只用它做手动封裝。真正把收益吃透,是把它接入 CI 触发链之后才开始的。
CI/CD 流水線设计
阶段划分
一次完整的发版流水線,我们拆成了四个阶段:
- 代码拉取与相依性解析(SPM / CocoaPods)
- 单元测试与静态分析(并行执行)
xcodebuild archive归档与簽署- 上传 TestFlight 并通知值班群
钩子与触发条件
main分支的每次合并会自动触发阶段 1-2;只有打上release/*标签才会繼續跑阶段 3-4,避免每次小改动都消耗簽署配额。本地调试 Fastlane 腳本时,我们习惯先用Ctrl+C中断一次完整跑批,单独重跑失败的那一步,能省下不少等待時間。
示例 Fastfile 片段
lane :ci_archive do
cocoapods
run_tests(scheme: "Kvmkit")
build_app(
scheme: "Kvmkit",
export_method: "app-store",
output_directory: "./build"
)
upload_to_testflight(skip_waiting_for_build_processing: true)
end
这段腳本本身并不复杂,关键是要让它在同一套映像基线上重复运行都能得到一致结果——这也是我们把映像版本号写进建置日志的原因,方便回溯某次失败是环境问题还是代码问题。
快取与相依性管理
快取没配好,雲端建置的速度优势会被下载相依性的時間吃掉。下面是我们线上跑了三个月后总结的对照表:
| 快取项 | 未启用快取 | 启用映像内快取 |
|---|---|---|
| CocoaPods 安装 | 约 4-6 分钟 | 约 30 秒 |
| SPM 相依性解析 | 约 3 分钟 | 约 15 秒 |
| DerivedData 增量編譯 | 接近全量編譯 | 命中率 80% 以上 |
几个术语的口径先对齐一下:
- DerivedData
- Xcode 的增量編譯产物快取目录,跨建置复用可以显著缩短二次編譯時間。
- SPM 快取
- Swift Package Manager 拉取到本地的包源码与解析结果快取,避免每次建置都重新拉取远端仓库。
- 映像基线
- 雲主机开机即用的系統快照,包含固定版本的 Xcode、CLT 与预热好的相依性快取。
常见问题排查
最容易被忽略的一点:憑證过期不会立刻报错,而是在上传 TestFlight 的最后一步才失败,这时候整条流水線已经空转了十几分钟。我们现在把憑證有效期检查放进了阶段 1,提前失败、提前告警。
早期我们用过一种"每晚全量清空快取重新建置一次"的笨办法来防止快取腐化,后来改成按映像版本号做快取失效(版本号不变就复用,升级映像才清空),既保住了速度,也不会让脏快取悄悄潜伏几周才暴露问题。
"不要相信一次绿色的 CI;要相信连续十次绿色的 CI。"——这是我们值班手册里反复强调的一句话,尤其适用于刚迁移到新雲節點的头两周。
常见问题
雲端 Mac mini 和自建 Mac Runner 相比,安全性上有什么区别?
雲端節點的系統映像由服務商统一维护基线版本,團隊仍需自行管理簽署憑證与 Provisioning Profile 的访问权限;建议只把憑證注入到运行时环境变量,不落地到映像里,退还節點前清空 keychain。
免费的 Xcode Cloud 额度能不能直接替代这整套流程?
小團隊用 Xcode Cloud 完全够用;但当并行建置数、自定义腳本或跨项目共享快取的需求变多之后,自建在雲端 Mac 節點上的流水線会更灵活,也更容易控制成本上限。
多个项目共用同一批雲端節點时,憑證应该怎么隔离?
建议每个项目使用独立的 keychain 或独立的钥匙串 profile,建置腳本在拉起阶段导入、结束阶段清空,避免不同项目的憑證互相污染同一把系統级 keychain。
把 CI/CD 放在 M4 Mac mini 上,才算真正省心
本文所有流程——Xcode、Fastlane、CocoaPods、SPM——在 macOS 上都是原生一等公民,不需要任何虚拟机或兼容层。Mac mini M4 统一記憶體架构让簽署、归档、上传这类 I/O 与计算混合任务不再互相拖累,约 4W的待机功耗也让 7×24 值守節點的电费几乎可以忽略。
和自建 Mac Runner 相比,雲端節點不用操心機房散热、系統更新窗口和硬體故障换机——这些运维负担全部转移出去,團隊可以把精力放回流水線本身的质量上。
如果你的團隊也在被"谁的电脑能編譯"困扰,现在就是把 CI 迁到雲端 Mac mini M4 的最佳时机——查看 Kvmkit 套餐方案,几分钟内就能拉起第一个建置節點。