GitHub Actionsのcache missで別branchのCacheを使えない理由を確認する

GitHub Actionsのcache missをbranch/ref scope・key/version・復元fallback・cache-mode・保存結果から確認します。

AIものさし編集部

GitHub Actionsのcache missでは、keyが同じかだけでなく、cacheを作ったbranch/refと、今回のrunが読めるscopeを確認します。別branchにcacheがあることは、今のrunから復元できる証拠にはなりません。部分一致で復元できた場合と、完全一致のcache-hitも分けます。

本稿は依存cacheの読取・保存条件を診断する手順です。GitHubのcache操作、workflow起動、cache削除、課金設定変更は行っていません。branch名やkeyは架空で、実repositoryの高速化を実測したものではありません。

復元runと保存runを並べる

失敗したrunのevent、ref、base branch、OS、利用action版、path、解決後のkeyとrestore-keysを記録します。比較対象のcacheについても、作成runとref、保存成功のlogを確認します。「前のjobが成功した」だけではcache保存が行われたと断定できません。

表は横にスクロールできます

比較項目調べる理由取り違えの例
refとevent読めるcache scopeを判断PRとpushの同名branch
解決後key変数・hashの違いを見るYAMLの式が同じなので同一
path・圧縮環境cache バージョンとの関係keyだけで互換と判断
保存logcacheが実在するかjob成功だけを証拠にする
restore結果完全一致とfallbackを分けるcache-hit falseで空と断定

secretを含む設定ファイルや認証情報を、調査用cacheへ追加しません。cacheが復元できる人と、その中身を見せてよい人の範囲も考えます。

branchの到達範囲を先に確認する

GitHub公式cache reference(新しいタブで開く)は、現在branchやdefault branch、PRの場合のbase branchなどにscope制限があると説明しています。親branchが子branchのcacheを読める、または同じmainから分かれた兄弟branch同士で読めるとは限りません。

架空例でfeature-aとfeature-bがmainから分かれている場合、feature-aが作ったcacheをfeature-bから当然に復元できるとは扱いません。共通の依存をdefault branchで信頼できるworkflowが保存し、対象runが読める範囲で再利用する設計を検討します。権限制限を解除してcacheを広げることを最初の修正にしません。

PR runで作られたcacheはmerge refに属し、そのPRの再実行に限られる場合があります。PRで保存したものをmainのpushや別PRが読めないとき、keyを短くする前に保存refを確認します。

keyとcache バージョンを分ける

keyの式では、OS、package manager、lockfileのhash、独自の版番号などが結果に影響します。対象lockfileが見つからず、想定したhashになっていない場合や、monorepoで別lockfileを参照する場合もあるため、実際に評価された値を確認します。tokenなどのsecretをkeyへ含めてはいけません。

同じkeyでも、pathや圧縮toolに関係するcache バージョンが違えば、利用できるcacheは変わります。OSを変えたrunや異なる保存pathを、keyだけで同じ条件と比較しないようにします。cross-OS利用を検討する場合も、対象actionと依存物の互換性を確認し、設定一つで全cacheを互換にできるとは考えません。

表は横にスクロールできます

観測切り分けること修正の候補
keyが毎回違う不要なrun ID等が混ざるか依存の同一性に必要な要素へ絞る
lock変更でmiss新しい依存用keyか正常なmissとして取得・保存
key同じ、path変更バージョンと保存対象設計を揃えて新cacheを作る
別OSだけmiss圧縮と依存互換性OS別cacheか対応方法を選ぶ

既存cacheの中身を書き換える前提にはしません。新しい依存状態を区別したいなら、理由のある新keyで保存する方針を決めます。

restore-keysは、互換なfallbackへ限定する

restore-keysは指定順にfallback候補を探すための設定です。prefixを広げれば復元できる可能性は増えますが、古い依存や別設定の内容が混ざる範囲も増えます。復元できることと、その後のinstallを省けることを別に判断します。

公式cache actionの説明では、完全一致のcache-hitと、部分一致などによる復元は区別されます。cache-hitがtrueでないという理由だけで「何も復元されていない」と断定せず、復元logと実際の対象pathを見ます。逆に復元logがあっても、依存関係の整合や検査がすべて不要になるわけではありません。

package managerが持つdownload cacheと、実行可能な依存directoryやbuild出力を混ぜないようにします。lockfileに従う通常のinstallを実行した場合の成否と、cacheを利用できた成否を分けて記録します。

restoreとsaveの許可を確認する

現在の公式資料にはcache-modeがあり、restoreを許可しないmodeならcache missとして扱われる場合が案内されています。実行環境が対応する仕様を確認し、workflow・job・reusable workflowの有効設定とlogを見ます。saveが許可されないrunでは、jobが成功しても次回用cacheが増えない場合があります。

低い信頼のeventで保存を制限する既定を、高速化のためだけにwriteへ広げません。外部PRの変更を実行する経路でcacheを作ると、それを信頼する別workflowへ影響する可能性があります。信頼できる保存経路とrestore-only経路を分ける設計を検討します。

正常なmissでもworkflowが成立するか確認する

cacheは依存取得を助けるもので、存在しないと正しい成果物を作れない設計になっていないか確認します。保持・容量・evictionでcacheがなくなる場合もあるため、削除や容量増加の前に、保存数と利用状況、無cache時の動作を調べます。課金枠を無断で増やす処置は不要です。

完了記録は、元のmiss理由、変更したkeyやpath、保存ref、復元方法、install・testの実行結果を分けます。検証用runを実行していない場合は未確認と残し、logを読み解いたことだけで高速化や実行成功を報告しません。変更が合わなければ今回のcache設定差分を戻し、依存検証を省かない状態へ戻せるようにします。