运维 / CI·CD 2026年5月20日

2026-05-20 Xcode 16 描述文件路径多车道并发 Archive:在无头租用的 Apple Silicon 云 Mac 上落地(香港 / 东京 / 首尔 / 新加坡 / 美国

MacXCode 技术团队 2026年5月20日 约 18 分钟阅读

香港、东京、首尔、新加坡、美国租用Mac mini M4并以无头 SSH运行 Xcode 16 的团队,会碰到一个并不张扬的破坏性变更:描述文件(Provisioning Profile)不再只住在传统的 MobileDevice 目录里。Xcode 16UserData 为权威读写位置,而 2024 年以前的脚本、部分 Fastlane 动作与内部安装器仍只往旧路径复制 .mobileprovision。当你在单台租机上叠加多车道并发 xcodebuild archive 时,路径漂移会演变成签名竞态、虚假的「找不到描述文件」以及仅在 CI 上复现的 errSecInternalComponent。本文在开头给出策略:在主机上所有工具都确认兼容 Xcode 16 之前,双写镜像 UserData 与旧版路径;为每条车道配置独立 CI 钥匙串DerivedData 根目录;在标配 Mac mini M4 上把并发 Archive 车道默认限制为两条。正文提供路径对照表多车道矩阵无头签名排障八步上线清单与 FAQ,并与《钥匙串与描述文件 CI 基线》《自动与手动签名》《并发 xcodebuild 纪律》互相衔接。

谁会遇到描述文件路径漂移

失败信息很少直接写「目录错了」。更常见的是:车道 B 的 Archive 成功,车道 A 却报 No profile for team 'XXXXXXXXXX' matching,而两边明明导入同一 UUID。租机上问题会被放大:黄金镜像里残留 2024 年的安装脚本、插件仍只刷新 ~/Library/MobileDevice/Provisioning Profiles,新人本地的 Fastlane 却把文件下载进 UserData,夜间 cron 却只同步旧目录。多分支 CI 若共用同一 macOS 用户且未刻意分区,home 目录下的隐式全局状态会把「独立任务」绑在一起。

  • 发布工程师需要在单台 Mac mini M4 上为不同 Bundle ID 并发 Archive,并要求每条车道可预测地解析描述文件。
  • 平台组维护黄金镜像时必须写清:Xcode 16、xcodebuild 与辅助工具在 archive/exportArchive 时读哪条路径。
  • 安全评审要求证明车道 A 无法读取车道 B 的发行证书——热切换描述文件时,按车道隔离钥匙串 不可省略。

设计评审可从 MacXCode 首页 出发:Apple Silicon 贴近 Apple API,再判断哪些签名物料必须与租机检出同驻。若仍只复制到 MobileDevice,应视为阻碍多车道吞吐的技术债——请与《远程 Archive 指南》对照阅读(该文早于 UserData 变更)。

旧版 MobileDevice 与 Xcode 16 UserData 路径

Xcode 16 在通过 Xcode「账户」下载描述文件,或使用 xcodebuild -allowProvisioningUpdates 刷新 entitlement 时,会把磁盘上的权威位置视为 ~/Library/Developer/Xcode/UserData/Provisioning Profiles。旧路径 ~/Library/MobileDevice/Provisioning Profiles 仍被大量 CI 配方与脚本使用。在审计完所有入口之前,运维上的安全缺省是:每次轮换后把同一份 .mobileprovision 以 plist 内嵌的 UUID 为文件名,字节级一致地复制到两处(可用 security cms -D -i 读取 UUID)。

路径 典型消费者 Xcode 16 行为 租用机 CI 提示
~/Library/Developer/Xcode/UserData/Provisioning Profiles Xcode IDE、新版 xcodebuild GUI 下载的权威读写位置 复制前先 xcode-select 固定版本
~/Library/MobileDevice/Provisioning Profiles 旧脚本、部分 Fastlane 许多 CLI 流程仍会读取 脚本退役前继续镜像
车道暂存(如 /var/ci/lane-a/profiles 自定义安装器 不被直接读取,降低 home 竞态 每 job 再复制到两条 canonical 路径
ASC API + -allowProvisioningUpdates 自动签名流水线 可能只写入 UserData 见《Fastlane 与原生 ASC
数值护栏:轮换发行描述文件时保留 7–14 天 有效期重叠;进行中的 Archive 结束前不要删除旧 UUID。每次 Archive 前记录最新三个描述文件的 mtime,并与 security find-identity -v -p codesigning 一并写入日志,做法见《钥匙串基线》。

单台 Mac mini M4 上的多车道并发 Archive 矩阵

并发 Archive 不是「免费并行」:统一内存、NVMe 队列深度与签名会话状态在负载下仍会相互牵制。下表假设每条车道有独立 -derivedDataPath、独立 CI 钥匙串与双路径镜像的描述文件——细节见《并发 xcodebuild》与《Scheme + xcconfig 多分支》。

车道数 典型 NVMe 余量 统一内存 运维结论
1 条串行 Archive 系统卷至少 120GB 可用 16GB 起步,24GB 更舒适 共享 Release 列车默认方案
2 条并发 Archive 每车道在 /var/ci 预留 120–180GB 建议 24GB+ 标配 M4 的务实上限
3 条及以上 2TB 级 NVMe + 积极清理 32GB+,否则易压缩抖动 需有指标支撑;配合《磁盘清理
Archive + 重测试分片 根目录分离,勿共享 ModuleCache 为 XCTest 留 4GB 余量 优先串行 Archive 或分机

手动签名、显式描述文件说明符的车道级 archive 示例:

KEYCHAIN_PATH=/var/ci/lane-a/ci.keychain-db DERIVED=/var/ci/lane-a/dd xcodebuild -workspace App.xcworkspace -scheme Release -configuration Release -archivePath /var/ci/lane-a/out/App.xcarchive -derivedDataPath "$DERIVED" CODE_SIGN_STYLE=Manual PROVISIONING_PROFILE_SPECIFIER='MyApp AppStore' archive

无头签名排障:描述文件「已安装」仍失败

SSH 像交互式会话;launchd 与 CI runner 不是。升级到 Xcode 16 后最常见三类问题:只复制到 MobileDevice;证书进了登录钥匙串但 xcodebuild 指向空的 CI 钥匙串;车道 B 解锁了车道 A 仍占用的钥匙串。请把每次 Archive 的三段指纹当作例行输出:security list-keychainssecurity find-identity -v -p codesigning,以及对两个描述文件目录按 mtime 列出的最新三个 UUID。

codesignerrSecInternalComponent,在 archive 前非交互解锁 CI 钥匙串、配置 codesign 分区列表,并核对描述文件 entitlement 与目标能力是否一致(推送、App Group、Associated Domains 在门户修改后尤需复查)。自动签名 + ASC API 可能把路径问题推迟到导出阶段才暴露;手动车道会立刻显现。混用车道前请先读《自动与手动签名》。

切勿在共享租机上让两条车道共用同一登录钥匙串。在 /var/ci 下创建 ci-lane-a.keychain-dbci-lane-b.keychain-db,用 security import -k "$KEYCHAIN_PATH" -P "$P12_PASS" -T /usr/bin/codesign 导入发行 .p12,并在每个 job 生命周期内用 security list-keychains -s 限定搜索列表。
现象 高概率原因 下一步
Xcode 报告缺少描述文件 UserData 为空,仅写了旧路径 镜像 UUID 到 UserData 后重跑
errSecInternalComponent 钥匙串未解锁或分区列表错误 security unlock-keychain + set-key-partition-list
同提交车道 A 过、B 败 共享 DerivedData 或复制竞态 分离 -derivedDataPath,串行化复制
导出成功、上传被拒 描述文件类型或 entitlement 过期 对照《导出与 ASC 上传》清单

Archive 完成后请先上传 dSYM 再清理车道目录——《dSYM 符号化》假设 /var/ci/…/out 下归档仍可寻址。

八步上线:Xcode 16 路径 + 多车道 Archive

  1. xcode-select 固定到目标 Xcode 16.app,并把 xcodebuild -version 写入黄金镜像清单。
  2. 审计所有复制 .mobileprovision 的脚本,改为以 UUID 文件名双写 UserData 与 MobileDevice。
  3. 为每条车道创建 CI 钥匙串并导入发行证书,禁止互访对方钥匙串文件。
  4. 在 CI 环境块导出 KEYCHAIN_PATHPROVISIONING_PROFILE_SPECIFIER 与车道级 DERIVED_DATA_ROOT
  5. 每条车道干跑 xcodebuild -showBuildSettings,确认 CODE_SIGN_STYLE 与签名策略一致。
  6. 仅在 ASC API 凭证已密封监控时启用 -allowProvisioningUpdates
  7. 先稳定单车道 Archive,再开第二条车道并分离 NVMe 根与日志。
  8. 按周执行磁盘清理;轮换描述文件保留重叠,并在车道暂存目录保留热切换副本。

非交互安装描述文件(将 $PROFILE 换为车道暂存路径):

UUID=$(security cms -D -i "$PROFILE" | plutil -extract UUID raw -) && cp "$PROFILE" "$HOME/Library/Developer/Xcode/UserData/Provisioning Profiles/$UUID.mobileprovision" && cp "$PROFILE" "$HOME/Library/MobileDevice/Provisioning Profiles/$UUID.mobileprovision"

常见问题

Xcode 16 把描述文件存在哪里? 主路径为 ~/Library/Developer/Xcode/UserData/Provisioning Profiles。旧工具可能仍读 ~/Library/MobileDevice/Provisioning Profiles——在 CI 主机上应双写镜像直至全部安装器升级。

一台 Mac mini M4 能跑几条并发 Archive? 默认建议两条车道,各预留 120–180GB NVMe;第三条需 2TB 存储、积极清理与审慎内存规划。

SSH 上 codesign 报 errSecInternalComponent 常见原因? 多为钥匙串未解锁、CI 钥匙串分区列表错误或仅写入旧版路径而 Xcode 16 优先解析 UserData。

车道能否共享 DerivedData 提速? Release Archive 不建议——并行时 ModuleCache 与索引存储会竞态。请使用 per-lane -derivedDataPath;依赖缓存仅在单一写入者解析包后再以只读方式共享。

请把 博客列表帮助中心 加入值班书签,避免在聊天窗口里翻找这篇运维手册。

为何 Mac mini M4 租用适合多车道 Xcode 16 Archive

Apple Silicon M4 在诚实隔离 DerivedData、控制车道数量时,足以并行编译两个中等规模的 iOS 工程图。原生 macOS 代码签名可避免模拟 Mac 环境的钥匙串怪异问题——当三条夜间分支都要刷新发行描述文件时尤为关键。租用把 CapEx 变成可按发布周启停的费用:贴近 App Store Connect 可选东京,服务东盟流量可选新加坡,需要美西 API 端点则选美国节点。请在 定价页 对比区域,在 帮助中心 预演 SSH;新仓库接入无头租机时请与《远程 Archive》一并阅读。

租用 Apple Silicon,让 Xcode 16 签名可预测

HK / JP / KR / SG / US · 无头 SSH · 多车道 Archive 就绪