Kvmzen 博客
← 返回技术实践

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

CI/CD 实践 ·约 5 分钟阅读

Mac mini M4 云主机搭建 iOS CI/CD 实战 - Kvmzen

在团队规模变大之后,"谁的电脑能出包"这件事本身就会变成瓶颈。我们把 iOS 项目的 CI/CD 整体迁移到 Kvmzen 的 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: "Kvmzen")
  build_app(
    scheme: "Kvmzen",
    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 的最佳时机——查看 Kvmzen 套餐方案,几分钟内就能拉起第一个构建节点。

限时特惠

不只是一台 Mac,是你在云端的开发基地

独享算力 · 全球节点 · 按月订阅 · 无需购置硬件

返回首页
限时优惠 点击查看套餐