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だけで互換と判断 |
| 保存log | cacheが実在するか | 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設定差分を戻し、依存検証を省かない状態へ戻せるようにします。
