CI Cachingを解説: パイプラインを壊さずに高速化する
cachingはCIを高速化するための最もレバレッジの高い方法です - そしてkeyが間違っていると、微妙でデバッグの難しい失敗のよくある原因になります。
CIの時間のほとんどは、変わっていない作業をやり直すことに費やされます - 同じ依存関係をダウンロードし、同じlayerを再ビルドする。cachingはそれらのoutputを保存し、次のrunで復元します。正しく行えばすべてのjobから数分を削減できますが、間違って行うと古いデータを提供したり、静かに一度もhitしなかったりします。
cacheする価値があるもの
- 依存関係のディレクトリ(node_modules、~/.m2、~/.cargo、pip wheels)。
- build outputとコンパイラのcache(インクリメンタルbuild、ccache)。
- registryをバックエンドとするlayer cacheによるDockerのlayer。
cache keyとrestore key
cache keyは、cacheされた内容が変わるべきときにちょうど変わるべきです - 通常はlockfileのhashです。restore keyはフォールバックのプレフィックスを提供し、near-missでも何もない代わりに有用な古いcacheを復元できるようにします。広すぎるkeyは古いデータを提供し、狭すぎるkeyは一度もhitしません。
GitHub Actions cache config
key: deps-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
deps-よくある間違い
- 常に変わるもの(commit SHA)をkeyにする → hit率0%。
- 安定しすぎたものをkeyにする → 古い依存関係が永遠に提供される。
- どのみち再ビルドされるディレクトリをcacheするため、cacheが決して役立たない。
- cacheのサイズ制限を無視し、静かにホットなcacheを追い出す。
重要なポイント
- 高価でめったに変わらない作業をcacheする: 依存関係、build output、Dockerのlayer。
- lockfileのhashをkeyにする。フォールバックのプレフィックスとしてrestore-keysを使う。
- 間違ったkeyは古いデータを提供するか一度もhitしないかのどちらか - どちらも「cachingが何もしていない」ように見える。
よくある質問
What is CI caching explained?
Most CI time is spent re-doing work that has not changed: downloading the same dependencies, rebuilding the same layers. Caching stores those outputs and restores them on the next run. Done right it cuts minutes off every job; done wrong it serves stale data or silently never hits.