云 Mac 上跑公证最常见的五条误判签名
公证链路的失败面比本地 Archive 更「网络化」:同一套脚本在笔记本上偶发成功,搬到云上却变成间歇性 In Progress,本质往往是出口路径、时钟、临时目录与钥匙串默认域四类因素在远程会话里被放大。下面五条签名不是为了堆术语,而是为了在值班群把讨论从「是不是苹果又挂了」拉回到可验证事实:当你能稳定复现其中任意两条,就应把「是否拆分公证机」写进风险登记册,而不是继续在同一台交互开发机上叠加更多 fastlane lane。
日志只报网络超时但本地 curl 苹果域名正常:典型是代理环境变量与 notarytool 子进程继承不一致,或上传阶段走了与交互 shell 不同的 PATH;应先在同一用户会话打印 env 与 scutil 代理状态,再对照一次最小 zip 上传,而不是先换区。
同一 bundle id 昨天能公证今天突然 Invalid:典型是 entitlements 与签名证书用途不匹配,或自动签名切换了 profile;应先 diff 构建产物内 _CodeSignature 与 export options,而不是先重装 Xcode。
stapler 成功但终端用户仍看到已损坏:典型是 staple 的对象不是最终分发入口文件,或后续流水线又对 zip 做了二次压缩;应以 CDN 或内网分发 URL 下载下来的字节与 staple 前哈希对齐。
多人分时共用一台云 Mac 时公证随机失败:典型是登录项与钥匙串解锁域互相污染,或两个用户共用同一默认钥匙串搜索顺序;应先核对是否把 Distribution 证书导入了登录钥匙串而非专用文件钥匙串。
磁盘余量大于 20GB 仍在上传阶段崩溃:典型是瞬时 zip 工作目录与 DerivedData 同盘竞争导致 IO 长尾,或 APFS 快照与清理任务撞车;应把临时目录改到独立路径并监控 iostat 而不是只看 df 汇总。
识别签名之后,下一步是把「公证机角色」写进架构图:控制面可以仍在笔记本,但签名与上传必须在单一用户与单一钥匙串文件域内闭环,否则你会在第三周把问题误报成「日本区线路不稳」。若你们已经在同一台机上跑 Git 大仓与 mono-repo 拉取,还要额外警惕 .git 与公证临时目录抢 IO;这类叠加故障在站内大仓 Runbook 里已有磁盘水位口径,可并行阅读作为周检补充。
专用公证机、混用机与纯 CI 机:一张表对齐停机面
工程上不存在「永远正确」的拓扑,只存在「你们能否解释每一次公证请求走了哪条钥匙串与哪条出口」。下表用粗粒度列帮助你在十分钟内对齐「我们到底缺哪一层隔离」,并把「成员交互、制品上传、合规叙事」三件事拆开到可审计字段。注意混用不是简单省钱,而是把失败模式从证书漂移迁移到排班与清理纪律:没有纪律时,混用矩阵再漂亮也只是把风险按钮做得更大。
| 维度 | 专用公证云 Mac | 公证与 Xcode 混用 | 纯无人 CI 构建机 |
|---|---|---|---|
| 证书与钥匙串风险 | 最低,单一用户与专用钥匙串文件域 | 中高,自动签名与手动证书并存时易串味 | 中,需严格限定导出与上传凭据轮换 |
| 人机交互与发版窗口 | 低干扰,适合固定发版日 | 高干扰,交互峰值与上传峰值叠加 | 无人值守,适合夜间批量 |
| 磁盘与 IO 面 | 可独立挂载临时目录与日志盘 | 与 DerivedData 与模拟器数据争用 | 可用浅克隆与制品缓存,但仍要防抢盘 |
| 多地区摆放 | 优先贴近负责签名的法务与运营时区 | 往往被迫贴近主力开发时区 | 优先贴近制品 registry 与主 Git 远端 |
| 租期组合 | 日租压测上传稳定性再锁月租 | 周租观察钥匙串漂移频率 | 月租或季租锁基线并配清理 Runbook |
公证稳定性的第一性原理不是 ping,而是「签名、上传、分发」三件事是否落在同一可审计用户会话里。
若你在新加坡、东京、首尔、香港、美国东部与美国西部混用不同规格,还要额外记录「哪台机器是哪一个 Apple Team 与哪一个钥匙串文件的单一事实来源」,否则排障时会把 entitlements 变更误当成区域问题。与「成员到云 Mac RTT」相比,公证更敏感的是系统时钟、代理与临时目录 IO;这三项在远程会话里比单纯延迟更难肉眼发现,却更容易在周五晚上集体爆发。
notarytool 与 stapler:先把命令骨架变成可审计事实
最稳的工程假设是:所有上传与查询都在同一 shell 继承链里执行,而不是「CI 里一段、ssh 进去再一段」。工程上建议把 App Store Connect API key 或 Apple ID 凭据写入专用 keychain profile,并在 Runbook 里冻结 notarytool 子命令顺序:先 store-credentials,再 submit,再用 log 拉 submission id,最后 staple 与 validate。任何「凭感觉少打一步 log」都会在第三周变成不可复盘事故。
xcrun notarytool store-credentials "AC_PROFILE" --keychain "$HOME/Library/Keychains/ci-notary.keychain-db" --apple-id "..." --team-id "..." --password "app-specific" xcrun notarytool submit ./Dist/MyApp.zip --keychain-profile "AC_PROFILE" --wait xcrun notarytool log <submission-id> --keychain-profile "AC_PROFILE" xcrun stapler staple ./Dist/MyApp.zip xcrun stapler validate ./Dist/MyApp.zip
钥匙串层面,团队应把「登录钥匙串」「系统钥匙串」「专用文件钥匙串」三类写进同一页 wiki,而不是散落在三个人的备忘录里。专用文件钥匙串配合 unlock 脚本可以把公证凭据与日常开发证书物理隔离,并在崩溃后快速整体替换文件而不是逐枚删证书。与多人分时共用相关的目录约定、SSH 用户分权与 Xcode pin,可直接对照站内隔离 Runbook 把「谁能碰公证 profile」写成表格字段而不是口头默契。
提示:把 notarytool log 的原始 JSON 与同一产物的 shasum 一并归档,比事后猜「是不是网络抖了一下」可靠三个数量级。
六步公证 Runbook:从日租压测到月租锁档
冻结角色与钥匙串文件路径:在变更单写明公证专用用户、keychain-db 绝对路径与 Team ID,禁止口头「先用登录钥匙串试一下」。
备份导出与描述文件清单:打包 exportOptions.plist、profiles 目录与 codesign 摘要到时间戳目录,确保回滚可执行。
在日租样本机跑最小上传:用固定小体积 zip 走完整 submit→log→staple→validate 再谈真实产物体积。
把临时目录与 DerivedData 拆盘或拆路径:避免 zip 阶段与索引阶段同盘 IO 叠加造成长尾超时。
打开时钟与代理观测:sntp 或系统时间服务、HTTP 代理、企业 MITM 证书三类必须有人认领告警路由。
通过后锁月租并写清理窗口:把周清 DerivedData、月清公证日志与 profiles 轮换写进同一日历,避免 silent drift。
三条可写进值班手册的硬阈值与规格水位
系统时钟漂移联防:若云 Mac 与权威时间源偏差持续超过约 120 秒且公证提交出现间歇性拒绝,应优先修 NTP 或托管方时间服务,而不是先扩容 CPU。
16GB/256GB 并发红线:当同一用户会话同时跑 Xcode 索引、公证 zip 与本地模拟器快照时,若 5 分钟滚动窗口内内存压力指示持续黄色且 Swap 写入速率高于舒适区,应视为配置事故并升档 24GB/512GB 或分机。
磁盘未用空间与临时目录:除 df 汇总外,建议为公证临时根目录单独保留至少约 30GB 可写余量给峰值 zip;低于约 15GB 时禁止再叠加大型 Archive 直到清理 Runbook 完成。
注意:上述秒级与容量阈值为工程沟通口径,不构成对具体硬件或云厂商 SLA 的承诺;跨区链路仍以你们实测为准。
仅依赖「出问题再全员重装」或「永远锁在唯一一台办公室 Mac」时,钥匙串叙事与上传稳定性会互相打架,团队只能用反复换机来吸收成本。相对地,把公证机与交互开发机拆成可路由、可观测、可回滚的两层,并在新加坡、日本、韩国、香港、美国东部与美国西部用日租或周租先跑样本,再决定是否把上传链路锁进月节奏,更符合短中期发版项目的现金流与风险节奏。纯笔记本热点或睡眠唤醒场景也常在上传长尾阶段暴露时钟与代理问题;纯靠家用网络跑 7×24 也会在第三周暴露凭据刷新与磁盘水位叠加。MESHLAUNCH 的 Mac Mini 云端租赁通常是更优解:它让你们在真实裸金属与稳定出口上验证公证矩阵,而不是把风险堆在「唯一一台生产机」上临场发挥。
优先使用专用用户与专用文件钥匙串,并把 DerivedData 与描述文件路径写进团队约定;细节见 多人分时隔离 Runbook,下单见 价格页。
把浅克隆、blobless 与 sparse-checkout 与周清节奏写进同一 Runbook;对照 Git 大仓磁盘策略,帮助见 帮助中心。
优先贴近负责签名与发版沟通的人员时区与网络出口稳定性,其次再对齐制品与 Git 远端;需要并行评估远程会话质量时可读 SSH 与 Mosh 验收矩阵。