← 返回技术实践

CI/CD 实践

在 Mac mini M4 雲主机上搭建 iOS CI/CD 全流程

约 5 分钟閱讀

Mac mini M4 雲主机搭建 iOS CI/CD 实战 - Kvmkit

在團隊规模变大之后,"谁的电脑能出包"这件事本身就会变成瓶颈。我们把 iOS 项目的 CI/CD 整体迁移到Kvmkit 的 Mac mini M4 雲主机之后,出包等待時間明显缩短,簽署事故也几乎归零。这篇手记记录了从零搭建这套流水線时踩过的坑,以及最终收敛出来的Fastfile与快取策略,供同样在评估雲端 Mac 的團隊参考。

为什么選擇雲端 Mac mini M4 做 CI/CD

Xcode 的建置是典型的"计算密集 + 强相依性系統版本"的任务,本机 Runner 很难长期稳定维护。選擇雲端 Mac 節點主要基于三点判断:

  • 规格可控:映像固定 Xcode 与命令行工具版本,不会因为某人手动升级系統而"團隊里只有他能編譯"。
  • 随时扩容:发版前的回归测试可以临时多开几个節點并行跑,跑完即释放,不用为峰值常年预留硬體。
  • 7×24 值守:M4 晶片待机功耗低,夜间建置、定时安全扫描都可以放心常驻运行,不用担心电费或噪音。

我们踩过的第一个坑:以为「雲主机」等于「远程顯示器」,只用它做手动封裝。真正把收益吃透,是把它接入 CI 触发链之后才开始的。


CI/CD 流水線设计

阶段划分

一次完整的发版流水線,我们拆成了四个阶段:

  1. 代码拉取与相依性解析(SPM / CocoaPods)
  2. 单元测试与静态分析(并行执行)
  3. xcodebuild archive归档与簽署
  4. 上传 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 套餐方案,几分钟内就能拉起第一个建置節點。

需要技术支援或选型建议?

在使用 Mac 實例或 CI/CD 流水線过程中遇到问题,可先查看幫助中心;下单与计价见定價页。