远程 Mac 像长期 SSH 的 Linux 构建机,但 macOS 还有自动更新、GUI 弹窗与复杂开发者目录;同一台机混跑 Runner、桌面与调试时,方差会悄悄堆起来。下面七条用于平台自检:命中越多,越要把「还原按钮」写进 Runbook。
系统与 Xcode 静默升级:更新后 xcodebuild -version 与台账不一致,未验收易把环境问题误判成合并问题。
全局语言运行时漂移:brew/脚本装全局后,Runner 用户与登录用户 PATH 不一致,launchd 下常见「找不到 gem」。
DerivedData 共享污染:多项目共用默认缓存且无命名空间时,中断构建易留下坏状态,表现为随机编译红。
Keychain 与签名混用:发布与 CI 同用户时,证书轮换会波及所有 Job;无头解锁策略不清会放大不确定性。
磁盘水位与日志膨胀:不轮转日志、不回收制品时,系统盘被诊断与旧 archive 顶满,表现为 IO 超时或奇怪网络失败。
供应商维护窗口:底层迁移或网络策略调整会让固定出口假设失效;无探针与基线回归时排错易走弯路。
缺少黄金基线记录:说不清上次全员认可的干净基线是何时,救火时只能盲清理,成本高且易误删。
这些痛点的共同点,是把 macOS 当成「临时借用设备」而不是「合同化算力节点」。当你把底座换成可画像、可还原的独占远程 Mac,就能把问题从「谁改了什么」收敛成「是否超过漂移阈值、是否该走快照」。接下来用一张表把两种底座模型对齐到成本与风险,而不是停留在口号层。
这张表用于架构评审:左边是「养一台长期机」的收益与代价,右边是「把干净基线做成按钮」的收益与代价。真实团队往往是混合态:日常跑在长期节点上,按周或按大版本在维护窗里执行快照还原。
| 维度 | 长期在线独占节点 | 快照 / 黄金镜像回基线 |
|---|---|---|
| 主要收益 | 缓存命中高、冷启动少、排障资料多(日志连续) | 方差可快速清零,回归路径短,适合大升级后验收 |
| 主要风险 | 漂移累积、隐性全局依赖、「能 green 但不可解释」 | 还原耗时、若镜像含错会批量复现错误;需要版本化治理 |
| 磁盘策略 | 强调命名空间、配额、定期清理与审计 | 系统盘可回滚;缓存盘常独立,避免把 DerivedData bake 进镜像 |
| 适用流水线 | 高频提交、追求队列时延与增量构建 | 发布前门禁、Xcode 大版本切换、疑似环境污染救火 |
| 与 Runner 关系 | Runner 进程长期附着,labels 稳定 | 还原后需重新校验 Runner 服务账户、工作目录与权限 |
「像买 VPS 一样买 Mac」在 CI 底座里,意味着你既要有长期在线的算力合同,也要有一张能一键回到「已知良好」的退网策略。
若你正在实施 自托管 Runner,把「节点还原」写进 Runbook:还原要同时验收服务账户、工作目录与缓存卷,避免 Runner 在线但环境半残。
下列步骤假设你已有独占远程 Mac 与基本 SSH;不替代供应商具体快照产品手册,但给出平台工程应检查的最小闭环。顺序很重要:先冻结变更,再还原,再跑门禁,最后才恢复并发。
冻结写入与排队:维护窗开始时暂停 Runner 领取新 Job 或临时改 labels;避免还原过程中仍有任务写 DerivedData。
记录当前指纹:导出 sw_vers、xcodebuild -version、xcode-select -p 与关键 brew 包版本到工单,便于对比还原前后差异。
执行快照回滚或镜像重装:按供应商流程恢复系统卷;若使用黄金镜像,确保镜像版本号与内部变更记录一一对应,避免「最新镜像」语义不清。
重建最小工具链:用锁版本脚本安装 Xcode CLI、Ruby/Bundler 或你们固定栈;禁止维护窗里顺手 brew upgrade 无记录升级。
跑基线门禁 Job:选一条代表仓库(或专用 canary 工程)执行干净 clone + archive + 单测;通过后再扩大并发。与 可复现构建 的「干净 clone」定义对齐。
恢复 Runner 与监控:检查 launchd/服务状态、磁盘水位与日志目录权限;把还原事件写入台账,注明镜像版本与指纹三元组。
#!/usr/bin/env bash
set -euo pipefail
LOG="ci-baseline-$(date +%Y%m%d-%H%M).txt"
{
date -u
sw_vers
xcodebuild -version
xcode-select -p
which ruby; ruby -v || true
which node; node -v || true
} | tee "$LOG"
提示:若同一台机还承担 Fastlane 发布,还原后优先验证发布专用用户的 Keychain 与 API Key 挂载是否仍在预期路径,避免 CI 绿了但发布链路断了。
最常见的误配,是把团队共享的大型缓存 bake 进黄金镜像:镜像暴涨、升级痛苦;缓存应是可丢弃的加速层。更稳妥是镜像固化 OS + Xcode + 固定脚本;缓存放独立卷并按项目子目录命名。与 企业资源池 篇一致,多 App 共用节点要避免默认路径互踩,可按 ORG/REPO/BRANCH 分桶并定期清理过期目录。
注意:还原系统盘不等于自动清理数据卷;若怀疑缓存损坏,要有「只清缓存、不动签名材料」的操作清单,避免误删证书与 profile。
下列条目用于内部对齐;具体阈值以你们 SLA 与供应商能力为准。
个人笔记本易受睡眠与更新影响,纯 Linux 又跑不了官方 macOS 工具链;要把 iOS CI 做成可解释、可还原的平面,独占远程 Mac + 快照/镜像策略通常比人肉擦机器更稳。NodeMini 的 Mac Mini 云端租赁提供固定 SSH、清晰磁盘档位与可复制节点画像,让底座像运维 VPS 一样可交接、可扩容。