企业 Mac CI:notarytool 公证流水线与仅签名分发的并发隔离

多仓并行的 macOS 发版常在仅签名分发与走完 Apple 公证之间反复横跳:notarytool 上线后链路更短,但 ASC 提交、轮询与 staple 仍把 NVMe 暂存、上传带宽与登录钥匙串同时点燃。下文按分发口径、并发模型、队列与带宽、staple 验收拆解,姊妹篇可参考 match 与 ASC API 证书治理codesign 并发与钥匙串隔离

一、仅签名分发与 notarytool 公证:何时分叉

仅签名用于内部分发、企业证书或在受控网络里跑——构建短、不上传、不依赖 Apple 服务可用性。notarytool 公证面向公网下载与 Gatekeeper 放行:除了正确签名,还要 Hardened Runtime、Secure Timestamp、entitlements 收敛,再 notarytool submit --waitstapler staple。CI 矩阵把两条线画清:PR/夜间 → 仅签名烟雾包release/RC → 公证完整包,避免每个 commit 都打 ASC 的脸。

二、提交并发:公证不是"越多越快"

ASC 对单团队有并发提交与速率上限,超过会以 429/排队反压。共享节点把所有仓任意 fan-out 等于全队挨打。建议:全局公证槽位(信号量限并发提交),跨仓共用同一上限;同包 hash 去重避免重复上传;提交前 dry-run staplecheck 拦掉肯定失败的包;失败重试设指数退避,区分网络错与策略错(Hardened Runtime/entitlements 类不必重试)。

三、暂存盘峰值:ditto/zip 是写放大主战场

提交前 ditto -c -k --keepParentzip 会把 .app / .pkg 打成临时包,叠加多 Job 就是几十 GB 写入峰值。落地:暂存目录指向独立 APFS 卷(与 DerivedData、Git 缓存分离),用 tmpfs/RAM 盘盛装短命中间产物;产物清理在 Job trap EXIT 里走;预算先按"单包大小 × 并行槽位 × 2"留水位,再压测。

四、上传带宽:把公证拉出主管道

ASC 上传与制品分发、Pods/SPM 拉取抢同一条上行管道时,整机延迟全飘。隔离:给公证 Job 专用网络命名空间或 QoS 队列;高峰错峰提交(按时区/团队 release 窗口);多节点池里把公证标签固定到带宽宽裕的少量 Runner,下游 staple 与发布到 CDN 的步骤再分摊。监控加 p95 提交时长、轮询次数、上行吞吐三条曲线,比单看"成功率"灵敏。

五、staple 与验收:可复现的最后一公里

stapler staple 后必须 spctl -a -vv / codesign --verify --deep --strict --verbose=4 双验;离线验收用 stapler validate 模拟无网环境。把 UUID、submission log、ticket 哈希归档进制品元数据,便于灰度回滚定位。

六、落地 FAQ(节选)

  • 仅签名能上 Mac App Store 外的公网下载吗?10.15+ 强制公证,缺票会被 Gatekeeper 拦,必须走 notarytool。
  • 共享机怎么防"互相挤公证"?全局信号量 + 公证 Runner 标签隔离 + 提交去重三件套。
  • Hardened Runtime 漏开导致反复退?在签名阶段就强制 --options runtime 与 entitlements 白名单,CI 拒绝裸签。

在 Mac mini 上把"签名 + 公证 + 分发"跑成可重复

这条流水线吃稳定 macOS 基线、足够内存与 NVMe 余量Apple Silicon 让 ditto/zip 与 codesign --deep 不再卡 CPU;Mac mini M4 待机约 4W、静音适合作长驻 Runner;Gatekeeper、SIP、FileVault 把节点本身的攻击面收紧,公证流水线的可信度才立得住。先用独占节点把公证槽位、暂存卷与上传带宽三条曲线跑顺,再扩到共享池——Mac mini M4 仍是 2026 年最具性价比的起点;打开 Macstripe 首页 即可在多节点之间挑离 ASC 入口最近的区域,把公证与发布的尾延迟一起压下来。