5 分钟内开通

专属 macOS Runner
告别构建队列

$21.2 / 天起 · 物理机独享
立即租用
完整 Xcode SSH 接入

云端 Mac 跑 Xcode CI/CD:从编译到 TestFlight 的完整实战

iOS 与 macOS 构建链路必须在真实 Apple 硬件上运行——这是 GitHub Actions 公共 macOS Runner 排队动辄半小时、 团队又买不起万元级 Mac Studio 的根本原因。本文记录在 SpinMac 云端 Mac mini M4 独享节点上, 完成 Xcode 环境配置、证书导入、Archive 签名、TestFlight 上传,以及挂载为 GitHub Actions 与 Jenkins 专属 Runner 的全流程, 并对比三种常见 CI 方案的适用边界。

为什么 iOS 构建离不开专属 macOS 环境?

与 Android 可以在 Linux 容器里跑 Gradle 不同,Apple 的构建工具链——xcodebuild、代码签名、 notarytool、App Store Connect API——全部绑定 macOS 与 Apple Silicon / Intel 物理机。 这意味着每一家有 iOS 产品的团队,迟早要面对「谁来提供这台 Mac」的问题。

常见痛点可以归纳为三类:公共 Runner 排队(GitHub Actions 免费 macOS 额度稀缺, 高峰时段 workflow 可能等待 20–45 分钟才分配到机器)、本地开发机被 CI 占用 (同事 push 代码后你的 Xcode 编译速度骤降、风扇狂转)、证书与密钥管理混乱 (多台机器各自导入 .p12,过期后无人知晓)。云端专属 Mac 节点可以同时解决前两个问题, 并为第三个问题提供单一可信环境。

测试环境

硬件:Mac mini M4 · 10 核 CPU · 16 GB 统一内存 · 256 GB SSD · 1 Gbps 独享带宽(SpinMac 日本节点)。
系统:macOS 15 Sequoia,Xcode 16.4。项目:SwiftUI 中型 App(约 12 万行、含 3 个 Extension target)。
CI 工具:GitHub Actions self-hosted runner 2.323.0、Jenkins 2.479 LTS + macOS agent。
签名:Apple Distribution 证书 + App Store Connect API Key(Issuer ID + Key ID + .p8)。

三种 CI 方案对比:该选哪一种?

在动手装 Xcode 之前,先明确你的团队处于哪条路径上。三种方案没有绝对优劣, 差异在于排队容忍度、月构建次数、合规要求

方案 典型成本 排队 / 并发 适合团队
GitHub 托管 macOS Runner 按分钟计费(约 $0.08/min 起) 共享池,高峰排队明显 月构建 < 500 分钟、可接受等待
自购 Mac mini 放机房 硬件 $599+ 一次性 + 电费运维 独占,但需自行维护系统与证书 有固定办公场所、长期高频构建
云端独享 Mac(按天租用) SpinMac $21.2/天起,无合同 物理机独占,即时可用 中小团队、阶段性发版、远程协作

我们的实测项目在中型 SwiftUI 工程上,xcodebuild archive 全量构建在 M4 节点耗时 约 4 分 12 秒(含 Swift 编译与链接);同一项目在 GitHub 托管 macOS-14 Runner 上, 排队 18 分钟后实际构建 5 分 40 秒——总耗时接近 24 分钟。对于需要「push 即测」的团队, 排队时间往往比构建本身更影响交付节奏。

4m 12s M4 节点 Archive 耗时
18m GitHub 托管排队(高峰)
1–5 min SpinMac 节点交付
16 GB 统一内存(无 swap)

云端节点环境初始化:Xcode 与签名材料

SpinMac 交付的 Mac mini 已预装完整 macOS 并拥有管理员权限。开通后通过 SSH 或浏览器 VNC 登录, 按以下顺序完成 CI 前置配置。建议把证书与描述文件集中存放在固定路径,后续 workflow 脚本统一引用。

  1. 01
    安装 Xcode 与命令行工具

    从 App Store 或 xcode-select 安装 Xcode 16.x,执行 sudo xcodebuild -license acceptxcodebuild -runFirstLaunch。验证:xcodebuild -version 应输出正确版本号。

  2. 02
    导入签名证书与 Provisioning Profile

    将 Distribution .p12 与密码通过安全通道传到 ~/certs/,用 security import 导入钥匙串;.mobileprovision 文件放入 ~/Library/MobileDevice/Provisioning Profiles/。CI 环境建议使用专用钥匙串并设置 -T /usr/bin/codesign 信任。

  3. 03
    配置 App Store Connect API Key

    在 Apple Developer 后台创建 API Key,将 AuthKey_XXXXXX.p8 存至 ~/private_keys/。上传 TestFlight 时配合 xcrun altoolfastlane pilot upload,避免交互式 Apple ID 登录。

  4. 04
    克隆仓库并缓存 DerivedData

    首次 git clone 后执行一次本地 Archive,确认签名链路通畅。将 DerivedData 保留在本地 SSD(256 GB 对中型项目足够),后续增量构建可节省 30–50% 时间。

钥匙串在 CI 中的常见坑

无头环境(SSH / Runner)下 codesign 失败,90% 是钥匙串未解锁或未授权。 在构建脚本开头加入:security unlock-keychain -p "$KEYCHAIN_PASSWORD" ~/Library/Keychains/ci.keychain-db, 并设置 set-key-partition-list 允许 codesign 访问私钥。切勿把密码明文写进 Git 仓库——用 GitHub Secrets 或 Jenkins Credentials 注入。

挂载 GitHub Actions 自托管 Runner

专属 Runner 注册后,workflow 可通过 runs-on: self-hosted 或自定义 label(如 macos-m4) 定向到这台云端 Mac,彻底绕开公共池排队。以下步骤在 SpinMac 节点上实测通过。

在 GitHub 仓库 Settings → Actions → Runners → New self-hosted runner,选择 macOS ARM64, 按页面提示下载并解压 actions-runner 包,然后执行:

./config.sh --url https://github.com/YOUR_ORG/YOUR_REPO --token RUNNER_TOKEN --labels macos-m4,ios-build --unattended

注册完成后安装为系统服务,确保节点重启后 Runner 自动上线: sudo ./svc.sh installsudo ./svc.sh start。 在 workflow YAML 中指定 label:

runs-on: [self-hosted, macos-m4]

典型 iOS 构建 job 核心步骤包括:检出代码 → 解锁钥匙串 → xcodebuild archivexcodebuild -exportArchivexcrun altool --upload-app 或 Fastlane upload_to_testflight。 我们在 M4 节点上跑通的一条 Fastlane lane 从 push 到 TestFlight 处理完成(含 Apple 侧排队)平均 约 11 分钟,其中本地构建与上传仅占 6 分钟出头。

安全提醒

自托管 Runner 能访问仓库代码与签名密钥,务必:限制仓库 collaborator 权限、定期轮换 Runner registration token、 不要在 fork PR 上自动触发带密钥的 workflow(使用 pull_request_target 需格外谨慎)。 团队共用节点时,可为不同项目注册不同 Runner 或配合 OpenClaw 沙箱隔离 Agent 操作范围。

Jenkins macOS Agent 配置要点

若团队已有 Jenkins 控制器(可运行在 Linux 上),macOS 构建能力通过 Agent 节点接入。 在 SpinMac 云端 Mac 上安装 JDK 17 与 Jenkins agent.jar,以 LaunchDaemon 方式常驻, 控制器通过 SSH 或 JNLP 拉取任务。

Jenkins 的优势在于流水线可视化与插件生态:Xcode 插件、Credentials Binding、 AnsiColor 日志着色、构建产物归档等。典型 Pipeline 片段逻辑为: 在 stage('Archive') 调用 sh 'xcodebuild ...', 在 stage('Upload') 调用 Fastlane 或 altool。 将 DEVELOPER_DIR 固定为 /Applications/Xcode.app/Contents/Developer, 避免多版本 Xcode 切换混乱。

与 GitHub Actions 相比,Jenkins 更适合多分支、多环境、需要人工审批闸门的企业内部流程。 云端 Mac 按天租用可以当作「弹性 Agent」:发版周开通节点、淡季释放,不必为全年 365 天运维一台机房 Mac。

Archive、签名与 TestFlight 上传实战

无论使用哪套 CI,最终产物链路一致:Archive 生成 .xcarchive → Export 生成 .ipa → 上传 App Store Connect。 命令行方式(不依赖 Xcode GUI)是 CI 的标准做法。

Archive 示例(Release 配置、指定 scheme 与输出路径):

xcodebuild archive -workspace MyApp.xcworkspace -scheme MyApp -configuration Release -archivePath build/MyApp.xcarchive CODE_SIGN_STYLE=Manual PROVISIONING_PROFILE_SPECIFIER="MyApp AppStore"

Export 需配套 ExportOptions.plist(method 设为 app-store),然后:

xcodebuild -exportArchive -archivePath build/MyApp.xcarchive -exportPath build/export -exportOptionsPlist ExportOptions.plist

上传 TestFlight 推荐使用 API Key 方式,避免双因素认证在无人值守环境卡住:

xcrun altool --upload-app -f build/export/MyApp.ipa -t ios --apiKey KEY_ID --apiIssuer ISSUER_ID

在中型项目上,M4 的 10 核 CPU 使 Swift 并发编译明显快于旧款 Intel Mac CI 机; 16 GB 统一内存在全量 clean build 时仍有余量,未触发 swap。 若项目含大量 Swift Package 依赖,建议开启 -clonedSourcePackagesDirPath 缓存目录以缩短后续构建。

没有办公室机房,怎么稳定跑 iOS CI?

很多独立开发者和小团队的真实困境是:需要 macOS 构建,但不想为了一台 CI 机专门租办公室、 拉网线、处理断电与系统升级。公有云虚拟机无法满足(没有完整 macOS 与 Apple 签名链), 二手 Mac mini 放家里又面临上行带宽不稳、IP 变动、家人误关机等问题。

SpinMac 的定位是独享物理 Mac mini M4:不做虚拟化、不超售,每台机器 16 GB 内存与 1 Gbps 独享带宽,付款后 1–5 分钟自动开通。五地节点(新加坡、日本、韩国、中国香港、美国东部) 可按目标用户分布选择——例如面向日本市场的 App 可选东京节点,缩短上传 TestFlight 时的跨境延迟。

计费上,按天 $21.2 起、按周 $57.3、按月 $106.1,无长期合同。发版密集的一周开通节点挂载 Runner, 日常维护期释放,往往比全年自购机器加电费更划算。需要多机并行构建时,可选购 Thunderbolt 5 并联服务 组成 80 Gbps 集群,适合大型 monorepo 或多 App 矩阵同时 Archive。

  1. 01
    在 SpinMac 选择节点并开通

    登录控制台选区域与租期,付款后 SSH 凭据与 VNC 入口自动下发。详见帮助中心

  2. 02
    按本文第三节完成 Xcode 与签名配置

    建议将钥匙串与 API Key 路径写入环境变量,供 GitHub Actions / Jenkins 统一读取。

  3. 03
    注册 Runner 并触发首次 pipeline

    先跑通 Debug 构建,再切 Release Archive + TestFlight,逐步把 Fastlane 或原生脚本固化进仓库。

成本与选型:一张表收束

你的情况 推荐路径 云端 Mac 角色
独立开发者,月发版 1–2 次 发版日租 SpinMac + 手动 Archive 临时构建机,用完即释
5–15 人团队,每天多次 push 常驻 self-hosted Runner 按月租用,独占不排队
已有 Jenkins,缺 macOS Agent 云端 Mac 作弹性 Agent 峰值扩容,避免买新机
多 App 矩阵 + 夜间批量构建 TB5 集群并联 多台 M4 并行 Archive

iOS CI/CD 的技术门槛不在 Xcode 本身,而在稳定的 macOS 算力 + 可复现的签名环境。 公共 Runner 适合低频构建;自建机房适合有运维能力的成熟团队;云端独享 Mac 填补了 「不想排队、又不想买机器」的中间地带——按天计费、物理机性能可预期、全球节点就近部署。 把编译与签名搬到云上之后,本地 MacBook 可以专心写代码,而不是在深夜被 CI 任务抢走风扇与内存。

物理机独享 · 5 分钟内开通

给你的 iOS 项目一台不排队的 macOS 构建机

SpinMac Mac mini M4 独享节点:完整 macOS 与 Xcode、16 GB 统一内存、 SSH / VNC 接入,可挂载 GitHub Actions 与 Jenkins Runner,按天 $21.2 起。

$21.2 / 天起
芯片Apple M4
CPU10 核独享
内存16 GB 统一
带宽1 Gbps 独享
SLA99.9%
交付1–5 分钟