GitHub Actionsで親repositoryのcheckoutは成功するのにprivate submoduleだけ取得できない場合、子repositoryへの認証を別に確認します。親のGITHUB_TOKENへwriteを追加しても、別repositoryへのアクセス範囲が自動的に増えるわけではありません。失敗した子のURL、固定commit、実際の認証経路を特定します。
本稿はprivate Git submoduleの取得診断です。repositoryアクセス、token発行、secret登録、SSH接続、checkoutやworkflow実行は実施していません。認証情報を含まない架空の確認表を使い、取得成功を測定した記事としては扱いません。
目次
親checkoutと子の取得を分ける
失敗stepと最初のerrorを確認します。親repositoryを取得できたことは、submoduleを取得したことではありません。checkout actionのsubmodules入力が未設定なのか、子を取得しに行って拒否されたのかを分けます。
表は横にスクロールできます
| 状況 | 最初の確認 | まだ断定しないこと |
|---|---|---|
| 子のdirectoryが空 | submodules入力と対象path | token失効 |
| Repository not found | 子URLとアクセス主体 | repository削除 |
| Permission denied (publickey) | SSH URLとkeyの適用 | HTTPS token不足 |
| nestedの子だけ失敗 | 再帰設定と各子のアクセス | 親のcheckout障害 |
| commitを取得できない | 親が固定した子SHAの存在 | 権限だけが原因 |
.gitmodulesのpathとURL、親commitが記録する子のSHAを確認します。ローカルにある古いcheckoutや、手元のSSH agentで成功した結果を、runnerの認証条件と同一視しないようにします。ログを共有するときは、URLに埋め込まれた認証情報も除きます。
checkoutの入力とバージョンを確認する
actions/checkoutの公式README(新しいタブで開く)は、submodules入力の既定をfalse、再帰取得をrecursiveとして説明しています。子が必要なのに無効なら、その設定を確認します。nested submoduleがある場合は、最上位の一件が取れたことだけで終えません。
実際に固定しているactionのバージョンまたはSHAと、その版の入力・runner要件を照合します。最新版へ変えれば認証問題も直ると考えず、runtime条件、変更点、取得範囲を分けて判断します。公式READMEの現行版にはforkコードを高権限eventでcheckoutする場合の保護も案内されています。認証エラーを理由にその保護を無効化する手順にはしません。
tokenの対象repositoryを照合する
公式READMEは、github.tokenが現在のrepositoryにscopeされ、別のprivate repository取得には別の認証が必要になることを説明しています。子のrepositoryへ読取可能な、組織で許可された認証方式を確認します。
表は横にスクロールできます
| 認証方式 | 確認する範囲 | 避ける対応 |
|---|---|---|
| GITHUB_TOKEN | 現在のrepository・job権限 | writeを付ければ別repoへ届くと仮定 |
| GitHub App token | installationと対象repository・権限 | 親だけのinstallationで全子取得を期待 |
| PAT | owner・対象repo・必要権限・有効状態 | 全repositoryの広いtokenへ即置換 |
| SSH key | 接続host・key・対象repoの許可 | host key検証を無効化 |
この表は認証方式の選択肢で、すべてを新規発行する指示ではありません。利用中の方式を一つ特定し、親と各子に必要な読取範囲だけを確認します。組織の承認やSSO等の条件がある場合は、管理者がそのtoken・identityの条件を確認します。secret値をechoして渡っているか試す方法は使いません。
HTTPSとSSH、nested先の違いを見る
子URLがHTTPSかSSHかを確認し、checkoutに渡したtokenまたはkeyが、その取得経路へ適用されるかを調べます。公式checkout資料には、ssh-keyがない場合のGitHub SSH URLからHTTPSへの変換条件もあります。自分の設定でどの経路になったかを確認し、URLの表記だけから利用keyを断定しません。
nested submoduleが別organizationや別hostなら、そのアクセス条件も別です。一つのSSH keyやtokenが、すべての階層へ使える前提にしないようにします。host keyの問題なら、信頼できる公式情報と組織手順に従って既知hostを設定し、StrictHostKeyCheckingを切って通す処置を避けます。
認証を通せても、親が指定した子commitが取得できなければ別問題です。子の履歴・参照状態とアクセス範囲を確認し、診断のために勝手に子の最新branchへ替えません。親が想定したバージョンと異なるコードを取れば、取得成功でも再現性が変わります。
eventによるsecret条件を確認する
通常のpushで成功しfork PRで失敗する場合は、同じ認証情報が提供される条件かを確認します。secretが渡らない経路へ、private submodule必須の処理を置いていないかを見ます。privileged eventへの切替で未信頼コードとsecretを同じjobへ集める対応にはしません。
secretが必要な信頼済み検証と、未信頼入力の検証をどう分けるかを、repositoryの運用担当と決めます。実行対象を制限する場合も、何を検証できなくなるかを明記します。取得をskipしたのに、必要な子コードまで検証済みと報告しないようにします。
取得結果を固定commitで確認する
変更前のaction設定、認証方式、対象repo、親・子SHAを残します。許可された検証では、各子が親の想定SHAで初期化され、必要なファイルがあり、nestedも含めた処理が進むことを確認します。認証成功のlogだけで、実際に必要なバージョンが揃ったと扱いません。
失敗したら、増やした入力や取得設定だけを戻せるようにします。検証用tokenを使った場合は、組織の期限・失効・secret管理手順へ戻します。完了記録には、失敗した階層、原因となったURL・認証・commit条件、変更した最小範囲、未検証のeventを残します。
