Appleの CIワークフロー向け公式資料 が示すように、CIではPackage.resolvedを管理対象にし、意図しない自動依存解決を止められます。したがって、Swift Package Managerのプライベート依存関係取得失敗では、最初にキャッシュを消したり共有鍵を追加したりせず、依存グラフの固定、実際のサービスアカウントの認証確認、最後にキャッシュの扱いという順で進めてください。
この順番なら、解析、Git接続、バイナリ取得、コンパイルという4つの失敗境界を分離できます。プライベート依存関係の読み取り用SSH IDは信頼ドメインごとに分け、依存解決ノードと本番署名ノードも原則として分離します。
SECTION 01 この記事を読むべき担当者
プライベートSwift Packageを含むiOS/macOSプロジェクトで、開発者のMacでは成功するのにCIだけが失敗している開発責任者向けです。
CIエージェント、サービスアカウント、リポジトリ権限を管理するプラットフォーム担当者、署名資産とリモートMacの隔離を審査するセキュリティ・IT責任者にも適しています。
SECTION 02 最初のマイルストーン:失敗段階と実行主体を固定する
ローカル成功とCI失敗は、まず身元の違いを疑う
開発者の対話型ターミナルは、ログインユーザーのHOME、~/.ssh/config、known_hosts、SSHエージェント、Git設定を自然に読み込みます。一方、CIでは別のmacOSアカウントがxcodebuildを実行するため、同じコマンドでも鍵、ホームディレクトリ、プロキシ、URL変換設定が異なります。
最初に保存するログは、次の4区分です。
| 区分 | 確認する証拠 | 交接条件 |
|---|---|---|
| 依存解析 | Package.resolvedの場所、解決対象、終了状態 |
使用するコミットと解決結果が一致している |
| Git接続 | 接続先、SSH認証結果、ホスト鍵確認 | 実行アカウントで読み取りが成功する |
| バイナリ取得 | バイナリTargetの実体、取得先、失敗端点 | ソース依存と別の取得経路を確認できる |
| コンパイル | 失敗Target、署名要求、SDK関連ログ | 依存取得の問題と分離できる |
ここで「ネットワーク障害」と一括りにしないことが重要です。依存解析の失敗をSSH鍵の追加で直そうとすると、権限を広げたまま原因が残ります。
まず実行主体を記録する
CIジョブ内で、実際にxcodebuildを起動するアカウントのユーザー名、HOME、現在の作業ディレクトリ、Gitの設定源を記録します。管理者のターミナルで成功した結果は、サービスアカウントの証拠にはなりません。
最小の再現タスクは、アプリ全体のビルドではなく依存解決に限定します。
xcodebuild -resolvePackageDependencies \
-disableAutomaticPackageResolution \
-scmProvider system
利用するオプションとCIでの依存解決手順は、Appleの継続的インテグレーション向けxcodebuild資料ではなく、正規URLのCIワークフロー向けApple資料に合わせて検証してください。
注意:管理者セッションでの成功、鍵を一時的に共有した成功、既存キャッシュを使った成功は、無人ジョブの復旧証拠として扱わないでください。
SECTION 03 アプリチームとコンポーネント担当の境界
Package.resolvedは何を固定するのか
Swift Package Managerは、マニフェストに書かれた依存条件から具体的なバージョンを解決します。公式の依存バージョン解決ドキュメントに沿って、トップレベルのプロジェクトまたはワークスペースに対応するPackage.resolvedを確認してください。
企業CIでは、次をアプリチームの完了条件にします。
- 対象プロジェクトまたはワークスペースの正しい場所にある。
- バージョン管理へ登録されている。
- 変更がコードレビューを通過している。
- 同じコミットをクリーンな作業領域で解決できる。
- 本番ビルドで意図しない依存更新が起きない。
依存更新のためのワークフローと、本番CIで再現性を優先するワークフローは分けます。自動更新を常時許可すると、認証障害とバージョン変更が同じジョブに現れ、原因の境界が曖昧になります。
企業CIでは、常にPackage.resolvedを登録すべきですか。
本番やリリース候補を再現するCIでは、登録して検証する方針が基本です。ただし、依存更新専用のジョブでは意図的に解決を更新し、その差分をレビューしてから固定ファイルへ反映します。更新ジョブと正式ビルドを同じ扱いにしないことがポイントです。
直接依存だけでなく、到達する全端点を棚卸しする
コンポーネント担当者は、アプリの直接依存だけでなく、伝播依存、バイナリTarget、レジストリ経由の依存も一覧化します。Swift Packageの依存宣言については、AppleのPackage.Dependency仕様を参照し、実際の取得経路と照合してください。
リポジトリ移転、URLの書き換え、ミラー設定、サブ依存の別ホスト化があると、トップレベルの接続確認だけでは不十分です。各端点について、読み取り専用か、認証方式は何か、撤回時にどの記録を更新するかを決めます。
xcodebuildでSSH鍵を使ってプライベートPackageを取得するには、何を確認しますか。
xcodebuildを実行する実ユーザーのSSH設定を使い、HOME、~/.ssh/config、known_hosts、鍵ファイル、SSHエージェントの状態を確認します。システムGit設定やURLマッピングが必要なら、採用するSCM Providerを明示し、管理者の環境を暗黙に継承しない構成にします。
SSH鍵は、依存関係を読むためのサービスアカウントに限定し、リポジトリ単位または信頼ドメイン単位で読み取り権限を付けます。作成、ローテーション、撤回の記録がない鍵は、障害対応後に残る監査リスクになります。
SECTION 04 CIプラットフォームとセキュリティ担当の実装手順
実際のサービスアカウントで5段階の復旧確認を行う
次の順番を変更しないでください。
-
依存グラフを固定する
Package.resolvedの対象パス、コミット、レビュー履歴を保存します。対象が違う場合は、認証調査へ進まずプロジェクト設定を直します。 -
実行ユーザーを特定する
xcodebuildを起動するmacOSアカウントで、HOMEと作業領域を記録します。CI管理画面に表示されるジョブ所有者ではなく、OS上の実行主体を証拠にします。 -
接続先を最小権限で検証する
直接依存、伝播依存、バイナリ取得先を個別に確認します。成功した接続先と失敗した端点を分け、全リポジトリへの広域権限を追加しません。 -
最小解析からコンパイルへ進む
依存解決、最小Targetのコンパイル、通常のビルドの順で進めます。各段階の終了状態とログを保存し、修正後も同じコミットで再実行します。 -
再起動後に無人復旧を確認する
SSHエージェント、Keychain、環境変数、作業領域の再生成を確認します。対話型セッションだけで復旧した場合は、完了扱いにしません。
Swift Package Managerのキャッシュは残すべきですか。それとも毎回消すべきですか。
通常は、最初から毎回消すのではなく、固定された依存グラフとクリーンな作業領域で再現できるかを先に確認します。キャッシュを消して成功した場合でも、破損、古い解決結果、認証、作業領域のどれが原因だったかを分離できなければ、恒久対策にはなりません。
キャッシュを無効化した検証は、障害の切り分けとクリーンノード受け入れ時に限定します。再利用する場合は、ジョブ間で認証情報や別プロジェクトの作業ファイルが混ざらない境界を設けます。
依存取得の資格情報と署名資産を分離する
プライベートソースの読み取り鍵を、Apple署名用秘密鍵、公開用API資格情報、共有管理者アカウントと同じ保管場所へ置かないでください。外部からの変更を含む信頼度の低いジョブには、本番依存と署名ノードの完全な権限を与えません。
推奨する境界は次のとおりです。
- 依存解析用の専用サービスアカウント。
- プロジェクトまたはリポジトリ単位の読み取り権限。
- ジョブ単位で作成する一時Keychain。
- 署名ノードとは別の作業領域。
- ジョブ終了後の鍵、Keychain、作業ファイルの消去。
- 失敗時に資格情報をログへ出さないマスキング。
Swift Package Managerの依存追加に関する公式文書と、Package Registryの認証仕様を、採用する取得方式の確認資料として使います。SSH、レジストリ、ミラーを混在させる場合は、資格情報の境界も方式ごとに記録します。
SECTION 05 リモートMacの受け入れと構成判断
クリーンなリモートMacでは、既存ノードのキャッシュを移植せず、同じコミットを使って依存解析、最小コンパイル、通常ビルド、再起動後の再実行を確認します。これにより、特定ノードに残ったSSH設定や作業ファイルが修復結果を偽装していないか判断できます。
共有リモートMacを使う場合も、ユーザーアカウント、資格情報、作業領域の3つを分離できなければ、プライベート依存の読み取りと本番署名を同居させないでください。AppleのPackage Registry構成を採用する場合は、公式レジストリ説明と実際のCI権限を照合します。
| 受け入れ項目 | 依存解析ノード | 本番署名ノード |
|---|---|---|
| 主な目的 | 固定済みPackageの取得とコンパイル | 承認済み成果物の署名と公開準備 |
| 必要な資格情報 | 読み取り専用の依存取得用ID | 署名用秘密鍵と公開用資格情報 |
| 共有可否 | 条件付きで可。アカウントと作業領域を分離 | 原則として専用化 |
| 再起動後の確認 | SSH設定、Keychain、作業領域を再生成 | 署名資産の注入と撤去を再確認 |
| 失敗時の交接 | 失敗端点と終了状態をアプリ担当へ | 成果物、署名ログ、撤回手順を公開担当へ |
条件分岐で、修復・分離・増設を選ぶ
Package.resolvedが不在または対象違いなら、まずアプリチームへ戻し、ノード増設はしません。- 実ユーザーのSSH設定だけが欠けているなら、サービスアカウントを修正し、広域権限は追加しません。
- 複数プロジェクトの鍵や作業領域が混ざるなら、共有ノードの利用を止め、分離ノードへ切り替えます。
- 依存解析は安定しても署名資産を分離できないなら、正式公開用の専用ノードを別にします。
- 再起動後や交換後に復旧できないなら、既存ノードのキャッシュ依存を疑い、クリーンなリモートMacで再受け入れします。
| 選択肢 | 選ぶ条件 | 避けるべき条件 |
|---|---|---|
| 既存ノードを修復 | 1つの実行アカウント、固定済み依存、分離済み作業領域がある | 管理者環境にだけ鍵がある |
| 共有ノードを分離 | プロジェクトごとに読み取り資格情報を分けられる | ジョブ間で同じ鍵と作業領域を使う |
| 専用ノードを増設 | 署名資産、外部変更、機密依存を別境界にする必要がある | 短期検証だけで物理接続要件がない |
| リモートMacを一時利用 | クリーン環境の再現確認や容量の一時追加が目的 | 長期の高負荷処理を固定運用したい |
自社購入のMacだけで運用すると、初期調達、保守交換、遠隔接続、容量増設を自社で抱え、共有ノードでは逆に資格情報と作業領域の分離設計が難しくなります。既存環境がその境界を満たさない場合は、VPSNIXのMacレンタル料金を確認し、隔離したリモートMacをクリーンな受け入れ用ノードとして試す方法があります。
ただし、長期にわたり一定の高負荷を処理する、専用の物理インターフェースが必要、社内規程で外部施設を認めていない場合は、自社所有の専用Macが適しています。反対に、CIの復旧確認、短期的なノード追加、既存共有環境からの分離検証が目的なら、レンタルの方が調達と返却を含む運用負担を抑えやすく、VPSNIXのヘルプセンターで接続方式と交付条件を確認してから、小さな隔離構成で検証するのが現実的です。