DevOps / CI・CD 2026年5月20日

2026-05-20:Xcode 16 のプロビジョニングプロファイル保存先マルチレーン同時 archiveを、ヘッドレスでリースした Apple Silicon クラウド Mac(香港 / 東京 / ソウル / シンガポール / 米国)で安定運用する

MacXCode Engineering Team 2026年5月20日 読了目安 約18分

香港・東京・ソウル・シンガポール・米国に近いリージョンで Mac mini M4 ビルダーをリースし、Xcode 16 を SSH 越しのヘッドレス環境で回しているチームは、静かな破壊的変更に直面します。プロビジョニングプロファイルが、昔ながらの MobileDevice ツリーだけに「住む」前提が崩れているのです。Xcode 16UserData 配下を正規の保存先として読み書きしますが、古いシェル、Fastlane の補助スクリプト、サードパーティ CLI は依然として .mobileprovision を Xcode 以前のパスへコピーします。そこへ1 台のリースホスト上で複数レーンの xcodebuild archive を同時実行を重ねると、保存先のズレは署名のレース条件、「プロファイルが見つからない」という幽霊エラー、開発用ノートでは再現しない errSecInternalComponent の断続失敗へと変わります。

本稿(2026-05-20)は方針を最初に明示します。ホスト上の全ツールが Xcode 16 前提に揃うまで、UserData とレガシー双方へプロファイルをミラーすること。レーン単位の CI キーチェーンDerivedData ルートを分離すること。そして、NVMe とユニファイドメモリの余裕を計測するまでは、標準構成の Mac mini M4 では同時 Archive レーンを2 本までに抑えること。本文ではパス比較表マルチレーンの判断表ヘッドレス署名のトリアージ8 ステップの導入、FAQ をまとめ、関連する キーチェーンとプロビジョニングの CI 基線自動署名と手動署名の使い分け並列 xcodebuild の運用規律と整合する運用指針を示します。

ヘッドレスのリース Mac で「保存先のズレ」が顕在化するのは誰か

障害はめったに「ディレクトリが違う」と名乗りません。レーン B の Archive は成功するのに、レーン A だけが No profile for team 'XXXXXXXXXX' matching を吐き、両方が同じ UUID を取り込んだはず、というパターンが典型です。リースホストでは波及範囲が広い。2024 年時点のヘルパーがゴールデンイメージに焼き込まれ、Jenkins プラグインは依然 ~/Library/MobileDevice/Provisioning Profiles を叩き、新入社員の Fastlane は UserData に落とす一方で夜間 cron はレガシー側だけ更新する、といった非対称が起きやすいからです。単一の macOS ユーザーで複数ブランチの CI を回すと、ホームを共有する各レーンが同じディレクトリを読みに行くため、意図的にパスを分割しない限りズレが増幅します。

  • リリースエンジニアが 1 台の Mac mini M4 で異なるバンドル ID の Archive を 2 本以上同時に走らせるなら、レーンごとにプロファイル解決を決定的にする必要があります。
  • プラットフォームチームはゴールデンイメージのドキュメントに、archiveexportArchive の各フェーズで Xcode 16、xcodebuild、周辺ツールがどのパスを参照するかを明記すべきです。
  • セキュリティレビューでは、レーン A がレーン B の配布証明書を読めないことの証跡が求められます。プロファイルをホットスワップするなら、レーン別キーチェーンは必須です。

設計レビューは MacXCode のホームが示す前提から始めます。Apple Silicon で Apple API に近づけ、リース先のチェックアウトとどの署名アーティファクトを同居させるかを地図に落とします。MobileDevice だけへコピーしている状態は、マルチレーンのスループットを阻む技術的負債です。リモート Archive のガイドは UserData シフト以前の前提が混ざるため、本稿と併読してください。

レガシー MobileDevice と Xcode 16 UserData の保存先比較

Xcode 16 は、Xcode のアカウント画面からプロファイルを取得したとき、あるいは xcodebuild -allowProvisioningUpdates が権限情報を更新したときに、~/Library/Developer/Xcode/UserData/Provisioning Profiles を主たるオンディスク保管場所として扱います。一方、多くの CI レシピ、古い Fastlane アクション、社内シェルのインストーラは ~/Library/MobileDevice/Provisioning Profiles だけを指し続けます。すべての入口を棚卸しするまで、運用上の安全策はローテーションのたびに両ツリーへバイト同一のコピーを置くことです。ファイル名は Apple が plist に埋め込む UUID(security cms -D -i file.mobileprovisionUUID キー)に合わせます。

パス 主な利用者 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 コピー前のカスタムインストーラ 直接は読まれない。ホーム直下の競合を減らす ジョブごとに正規の両パスへ複製
ASC API + -allowProvisioningUpdates 自動署名パイプライン UserData のみを埋める場合がある API キーを封じる。詳細は Fastlane とネイティブ ASC の比較
数値ガードレール:配布用プロファイルをローテーションするときは、有効期間を7〜14 日重ねる。ローテーション途中で立ち上がったレーンが、進行中の Archive が残っている UUID を先に消さないこと。security find-identity -v -p codesigning と併せ、最新 3 件のプロファイル更新時刻をログへ残す手順は キーチェーン基線に沿います。

1 台の Mac mini M4 におけるマルチレーン同時 archive の判断表

同時 Archive はリースした Mac mini M4 上では「ただ並列化すれば速い」ものではありません。ユニファイドメモリ、NVMe のキュー深さ、署名セッションの状態は高負荷下で依然直列化します。下表は各レーンが専用の -derivedDataPath、専用 CI キーチェーン、ミラー済みプロファイルを使う前提です。パターンは 並列ジョブのガイドスキーム・xcconfig の多ブランチ運用に合わせてください。

レーン本数 NVMe 空き容量の目安 ユニファイドメモリ 運用判断
1 本(直列 Archive) システムボリュームで 120 GB 以上 16 GB が下限、24 GB が快適 共有リリース列車の既定。ログが最も単純
2 本(同時 Archive) /var/ci 配下でレーンあたり 120〜180 GB 24 GB 以上を推奨 標準 M4 の実務上限。DerivedData とキーチェーンを分離
3 本以上 2 TB 級 NVMe と積極的な掃除 32 GB 超。未満なら圧縮処理が詰まりやすい 計測後に限る。ディスク衛生を週次で組み込む
Archive + 重いテストシャード ルートを分離し、ModuleCache は共有しない XCTest 用に 4 GB 程度の余白 テスト後に直列 Archive、またはホスト分割を推奨

手動署名で明示的な specifier を渡すレーン単位の 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 ランナーはそうではありません。Xcode 16 へ上げた直後に多い失敗は、(1) MobileDevice だけへコピーした、(2) 配布アイデンティティをログインキーチェーンへ入れたのに xcodebuild は空の CI キーチェーンを見ている、(3) レーン B がキーチェーンを unlock したことでレーン A の排他前提が崩れた、という三つの型です。各 Archive を三要素のフィンガープリントとして扱ってください。security list-keychainssecurity find-identity -v -p codesigning、両プロファイルディレクトリの ls -lt で最新 3 UUID に絞る、の組み合わせです。

codesignerrSecInternalComponent を出したら、archive の前に CI キーチェーンを非対話で unlock し、codesign が読めるパーティションリストを設定し、プロファイルの entitlements がターゲットの Capability(Push、App Groups、Associated Domains など)と一致するかを確認します。ASC API を使う自動署名は export までパスのズレを隠すことがありますが、手動レーンは即座に表面化します。1 台に複数スタイルを混在させる前に 自動と手動のガイドを読んでください。

禁止:共有リースで複数レーンを同一のログインキーチェーンに載せること。/var/ci 以下に ci-lane-a.keychain-dbci-lane-b.keychain-db を作り、配布 .p12security import -k "$KEYCHAIN_PATH" -P "$P12_PASS" -T /usr/bin/codesign で取り込み、ジョブ存続期間だけ security list-keychains -s のスコープを切り替えます。
症状 想定原因 次のコマンド/修正
Xcode レポートにプロファイルが出ない UserData が空でレガシーのみ UUID ファイルを UserData にもミラーし archive を再実行
errSecInternalComponent ロックされたキーチェーン/パーティションリスト不備 security unlock-keychain -p "$PASS" "$KEYCHAIN_PATH" と set-key-partition-list
同一コミットでレーン A は成功、B は失敗 DerivedData 共有やプロファイル競合 -derivedDataPath を分離し、プロファイル複製を直列化
export は通るがアップロード拒否 プロファイル種別違い/entitlements 失効 export と ASC アップロードのチェックリストで検証

Archive 後はレーンフォルダを消す前に dSYM を送ってください。dSYM とシンボリケーションは、アーカイブが /var/ci/…/out などレーン単位で辿れる前提を置いています。

Xcode 16 の保存先整備とマルチレーン archive を進める 8 ステップ

  1. xcode-select -p を意図した Xcode 16.app に固定し、xcodebuild -version をゴールデンイメージのマニフェストへ記録する。
  2. .mobileprovision をコピーする全スクリプトを棚卸しし、UUID ファイル名で UserData と MobileDevice の両方へ書き込むインストーラへ更新する。
  3. レーン別 CI キーチェーンを作成し配布証明書を取り込み、他レーンのキーチェーンファイルへアクセスできないようにする。
  4. CI の環境ブロックへ KEYCHAIN_PATHPROVISIONING_PROFILE_SPECIFIER(または UUID)、レーン専用の DERIVED_DATA_ROOT をエクスポートする。
  5. レーンごとにドライランの xcodebuild -showBuildSettings を実行し、CODE_SIGN_STYLE署名モードの方針と一致するか確認する。
  6. ASC API の資格情報を封じ監視できるときだけ -allowProvisioningUpdates を有効化する。詳細は ネイティブ ASC と Fastlane を参照。
  7. プロファイルのミラーが安定するまで Archive レーンは1 本から始め、NVMe ルートとログを分けた第 2 レーンを追加する。
  8. 週次で ディスク掃除を組み込み、重複期間を持ったプロファイルローテーションとレーン別ステージングのホットスワップを継続する。

非対話でのプロファイル配置例(ステージングパスは置き換え):

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 では両方へミラーしてください。

1 台の Mac mini M4 に同時に何本の archive レーンを載せられますか? レーンあたり 120〜180 GB の NVMe 空きを確保できる 2 本同時が実務的な既定です。3 本目は 2 TB 級ストレージと積極的なクリーンアップ、慎重なメモリ設計が前提になります。

SSH 越しの codesign が errSecInternalComponent で落ちるのはなぜですか? 多くの場合、キーチェーンがロックされたまま、CI キーチェーンのパーティションリストが欠けている、またはレガシーパスにしかプロファイルがなく Xcode 16 が UserData を先に解決する、のいずれかです。

DerivedData を共有すればビルドは速くなりませんか? リリース用 Archive では避けてください。並列 Archive 下では ModuleCache やインデックス保管が競合します。レーンごとに -derivedDataPath を分け、単一ライターがパッケージ解決を済ませた後に限り、読み取り専用の依存キャッシュを共有する設計に留めます。

ナビゲーションの衛生のため、ブログ一覧ヘルプセンターをブックマークしておけば、オンコールがチャット検索なしで本ランブックへ辿り着けます。

マルチレーンの Xcode 16 Archive に Mac mini M4 リースが合う理由

Apple Silicon の M4 は、DerivedData を分離しレーン本数を正直に抑えれば、中規模の iOS グラフを 2 本同時にコンパイルするのに十分なユニファイドメモリ帯域を持ちます。ネイティブ macOS のコード署名は、エミュレート環境で悩まされるキーチェーンの癖を避けられ、夜間に 3 ブランチが配布プロファイル更新を要求する状況でも有利です。リースはリリース週の突発需要に対する CapEx を減らします。東京で App Store Connect に近づけ、シンガポールで ASEAN 向け出口を取り、米国西海岸の API エンドポイントに合わせる、といった配置が可能で、列車が出たら縮小できます。リージョン比較は 料金ページ、SSH の手順確認は ヘルプを参照し、新規リポジトリをヘッドレスのリースへ載せるときは リモート Archive のワークフローと併せて読んでください。

Xcode 16 の署名が読みやすい場所で、Apple Silicon をリースする

HK / JP / KR / SG / US · ヘッドレス SSH · マルチレーン Archive 対応