期間限定

Apple Silicon クラウド Mac での iOS/macOS CI:codesign、Notarization、stapler とキーチェーン境界——再現可能なパイプラインと拒否コード早見表

CI デプロイとトラブルシュート
2026-05-07 約 8 分

iOS / macOS ビルドApple Siliconのクラウド Mac で回すとき、詰まりやすいのは Xcode のフラグより秘密鍵とキーチェーンの置き場です。CI 専用のファイル型キーチェーンに配布用 ID を閉じ込め、ジョブ開始時に明示的にアンロックし、codesign の入力(プロファイルとエンタイトルメント)を固定したうえで、notarytool 提出 → ポーリング → staplerユーザーが実際に受け取る外殻に対して実行する——本稿はインタラクティブな開発機と無人 Runner の境界を線引きし、最小の再現手順とログ断片に対する症状・原因・対応の早見表をまとめます。

この記事の要点

  1. CI 用に専用キーチェーン(ファイル)を用意し、配布証明書と秘密鍵だけをインポート。ログインキーチェーンの既定に依存しない。
  2. OTHER_CODE_SIGN_FLAGS=--keychain …CODE_SIGN_KEYCHAIN で検索対象を固定し、ビルドと同じシェルで security find-identity -v -p codesigning を確認する。
  3. アーカイブ/エクスポートのあと、notarytool で Gatekeeper が評価する成果物をそのまま提出し、Accepted 後に外側の zip / app / dmg へ xcrun stapler staplestapler validate まで Runbook に書く。
  4. 同一ホストで補助コンテナを動かす場合はディスクとマウントの前提を揃える。併せて Apple Silicon クラウド Mac で本番相当の Docker:arm64/amd64 イメージ、bind mount とビルドキャッシュのトラブルシュート手順(プランのリソース境界つき) を参照すると安全域が読みやすいです。
ノート PC とコード画面。クラウド Mac での署名・公証ワークフローを象徴するイメージ
ヒーロー画像は雰囲気用です。切り分けは実際の codesign -dv、公証ログ、配布物にチケットが載ったかで検証してください。

1. 無人ホストのキーチェーン境界

コンソール前に人がいない前提では、UI 承認やログインセッションの既定キーチェーンに依存したフローはイメージ更新後に壊れます。~/Library/Keychains/ci-signing.keychain-db のようなファイル型キーチェーンを一つ決め、Apple Distribution(または Developer ID)の証明書+秘密鍵をそこだけへ入れ、ジョブ先頭で security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" を実行してください。パスワードはシークレットストアから短寿命で注入し、リポジトリに平文を置かない。検索リストの先頭に CI 用チェーンを置きすぎると開発用 ID と衝突するので、明示的 --keychain とプロファイル UUID の突き合わせを当番手順に固定します。VPN 越しに Runner を触る場合は経路と MTU も安定要件に入ります。トンネルと DNS の観点は WireGuard とゲートウェイのペアリング:国境をまたぐ遠隔操作のトラブルシュート(MTU、非対称経路、DNS 分岐、遅延観測とクラウド Mac のリージョン・スペック選び) が参考になります。

2. codesign:エンタイトルメント、Hardened Runtime、ネスト

再現性は同じエンタイトルメント plist のハッシュ同じプロビジョニングプロファイルが毎回揃うことから始まります。エクスポート後に codesign --verify --deep --strict を app に通し、PlugIns や Frameworks 内のヘルパーごとにチーム ID と Hardened Runtime の整合を見ます。ネストの片方だけ古いと、本番ビルドでは通っても productbuildnotarytool の段で初めて errSecInternalComponent やエンタイトルメント不足が噴きます。.pkg では下位コンポーネントから順に署名し、最後にインストーラ証明書でパッケージ全体を閉じる順序を Runbook に書いておくと手戻りが減ります。

3. Notarization と stapler:順序が成果物

提出は notarytool と App Store Connect API キー(issuer、key ID、秘密鍵 .p8)が現実的です。キー素材はリポジトリ外に置き、環境変数でパスを渡す。Apple が Accepted を返す前に staple したり、内側の .app だけ staple して外側の zip を作り直したりすると、顧客側のハッシュと公証記録がずれて Gatekeeper が依然として検疫します。拒否時は submission ID を控え、notarytool log <id> の JSON から最初に失敗したルール ID をチケットに貼る運用にすると当番交代が楽です。

4. 最小チェックリスト

  1. CI キーチェーンをアンロックし、security find-identity で署名 ID を確認。
  2. プロファイル不整合の診断時だけ Derived Data を掃除。通常は依存とプロファイルをピン留めした増分ビルドを優先。
  3. 固定の ExportOptions.plist でアーカイブ/エクスポート。dSYM の送付は公証とは別ジョブに分離。
  4. 提出 → Accepted 待ち → stapler staplestapler validate。公開物とチェックサムを同じリリースノートに束ねる。

5. 症状・想定原因・推奨アクション(早見)

症状/ログ断片 起きやすい根本原因 推奨アクション
署名時 errSecInternalComponent CI キーチェーンで秘密鍵が使えない、ACL やアンロック漏れ 鍵+証明書を再インポート。ジョブ内でアンロックし --keychain を明示
No signing certificate found 検索リスト違い、プロファイル欠落 CODE_SIGN_KEYCHAIN を設定し ~/Library/MobileDevice/Provisioning Profiles の UUID を確認
公証 Invalid(Hardened Runtime 関連) 配布に許可されないエンタイトルメント、未署名のネスト Apple ドキュメントとエンタイトルメント差分。ネストを deep verify
CI 成功後もゲートキーパが検疫 配布物に staple していない、再 zip でチケットが外れる 最も外側の成果物へ staple。改パックは staple 後に行わない
notarytool 認証エラー issuer / key ID 誤り、時刻ずれ、失効キー キーローテーション、NTP、JSON キーをリポジトリ外で管理

6. まとめ

署名・公証・staple は一つの状態機械として扱い、各ステップの出力を次の入力としてログに残してください。キーチェーンのパス、プロファイル UUID、submission ID を同じ Runbook 行に集約すると、イメージ更新や鍵ローテのたびに「どの ID が生きていたか」を推測する時間が消えます。手順が固まったらクリーンイメージの冷えた Runnerで一度通し、再起動と資格情報更新に耐えることを証明すると安心です。

署名負荷の高い CI にはクラウド Mac mini が向く

Apple Silicon は arm64 ツールチェーンをネイティブで揃え、クロスエミュレーション由来の驚きを減らします。ユニファイドメモリは Xcode・シミュレータ・軽量エージェントを一つの予測しやすいプールに載せやすく、macOS の Gatekeeper や SIP と相まって改ざんリスクを雑多な Windows 系ビルド VM より抑えやすいです。M シリーズ Mac mini 級の待機電力は低く、7×24 の Runner に向き、共有 SaaS のキュー遅延やディスク I/O の近所ノイズから切り離した専用クラウド Macは署名スループットの安定にも効きます。

再現性の高い署名パイプラインを安定した Apple 純正ハードへ載せ替えたい場合、kvmboot のクラウド Mac mini M4 は現実的な第一歩です——プランと料金を確認することで、キーチェーン設計とプロビジョン済みティアを揃えやすくなります。