Contents
1. GitHub Actions キャッシュの基本構文と必須パラメータ
GitHub Actions の実行時間が長くなる主因は、依存関係やビルド成果物を毎回ゼロから取得していることです。actions/cache を利用すれば、これらのファイルを保存・復元できるため、ジョブごとの処理時間を大幅に削減できます。本節では キャッシュ機能の概要 と 必須パラメータ (path, key, restore-keys) の意味と最低構成例を解説します。
1.1 actions/cache の基本動作
actions/cache@v3 は指定されたファイルやディレクトリを圧縮し、GitHub が提供するキャッシュストアに保存します。次回同一キーでジョブが走ると、ネットワーク転送なしで復元できるため高速です。
- サイズ上限
- パブリックリポジトリ:5 GB/ジョブ(プランに依存)【GitHub Docs – Usage limits】
-
エンタープライズ:10 GB/ジョブ
-
自動削除期間
キャッシュは最終アクセスから 7 日 が経過すると自動で削除されます(同上)。この仕様を踏まえてキー設計とクリーンアップ戦略を立てる必要があります。
1.2 必須パラメータの役割
| パラメータ | 必要性 | 説明 |
|---|---|---|
path |
✅必須 | キャッシュ対象となるファイル・ディレクトリ(例: ~/.npm) |
key |
✅必須 | キャッシュを一意に識別する文字列。変化しやすい要素(OS、ロックファイルのハッシュ等)を組み込む |
restore-keys |
任意 | key がヒットしない場合に参照するプレフィックス一覧。複数行で指定可能 |
最小構成例
|
1 2 3 4 5 6 7 8 9 10 11 |
steps: - uses: actions/checkout@v4 - name: Cache npm dependencies uses: actions/cache@v3 with: path: ~/.npm key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} restore-keys: | ${{ runner.os }}-node- |
上記は OS と package-lock.json のハッシュでキーを生成し、同一パターンが無い場合はプレフィックスだけで過去の npm キャッシュを探索します。
2. 言語・ツール別キャッシュ設定例
プロジェクトで使用している言語やビルドツールごとに最適なキャッシュ対象ディレクトリが異なります。本章では代表的な環境について、公式推奨パス と キー設計のベストプラクティス を示します。各サブセクションは必ず導入文で目的を説明した上でコード例を掲載しています。
2.1 npm / Yarn / pnpm
npm・Yarn・pnpm はそれぞれ独自のローカルキャッシュディレクトリがあります。OS とロックファイルのハッシュをキーにすることで、依存関係が変わったときだけ新しいキャッシュが作成されます。
|
1 2 3 4 5 6 7 8 |
# npm の例 - uses: actions/cache@v3 with: path: ~/.npm key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }} restore-keys: | ${{ runner.os }}-npm- |
Yarn は ~/.yarn、pnpm は ~/.pnpm-store を同様に設定し、ハッシュ対象をそれぞれ yarn.lock、pnpm-lock.yaml に置き換えてください。
2.2 Ruby (Bundler)
Bundler のキャッシュは vendor/bundle ディレクトリに保存されます。さらに actions/setup-ruby が提供する bundler-cache: true オプションを併用すると、手動で actions/cache を記述しなくても自動的にキャッシュが有効化されます【setup‑ruby README – bundler‑cache】。
|
1 2 3 4 5 6 7 |
- uses: actions/cache@v3 # 手動で記述したい場合のみ必要 with: path: vendor/bundle key: ${{ runner.os }}-bundler-${{ hashFiles('Gemfile.lock') }} restore-keys: | ${{ runner.os }}-bundler- |
ポイント:
setup-rubyのbundler-cacheは内部でactions/cache@v3を呼び出すため、同一ジョブ内で二重に設定しないよう注意してください。
2.3 PHP (Composer)
Composer は依存パッケージを ~/.composer/cache に保存します。ロックファイル (composer.lock) のハッシュがキーとなります。
|
1 2 3 4 5 6 7 |
- uses: actions/cache@v3 with: path: ~/.composer/cache key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} restore-keys: | ${{ runner.os }}-composer- |
2.4 Java (Maven / Gradle)
| ビルドツール | キャッシュ対象ディレクトリ | キー例 |
|---|---|---|
| Maven | ~/.m2/repository |
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} |
| Gradle | ~/.gradle/caches と ~/.gradle/wrapper |
${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }} |
|
1 2 3 4 5 6 7 8 |
# Maven の例 - uses: actions/cache@v3 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- |
|
1 2 3 4 5 6 7 8 9 10 |
# Gradle の例(複数パスを改行で列挙) - uses: actions/cache@v3 with: path: | ~/.gradle/caches ~/.gradle/wrapper key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }} restore-keys: | ${{ runner.os }}-gradle- |
2.5 Docker ビルドレイヤー
Docker の BuildKit が生成するローカルキャッシュは任意のディレクトリに保存可能です。actions/setup-buildx と組み合わせて、ビルド時に --cache-from=type=local,src=/tmp/.buildx-cache を指定すると高速化できます。
|
1 2 3 4 5 6 7 |
- uses: actions/cache@v3 with: path: /tmp/.buildx-cache key: ${{ runner.os }}-docker-${{ hashFiles('Dockerfile') }} restore-keys: | ${{ runner.os }}-docker- |
3. キー設計のベストプラクティスとバージョン更新時の無効化手法
キャッシュヒット率は キーの粒度 に大きく依存します。本章では、hashFiles とランナー情報・ツールバージョンを組み合わせた設計パターンと、メジャーバージョンが変わった際に自動でキャッシュを無効化するテクニックを紹介します。
3.1 hashFiles と OS/ランタイム情報の組み合わせ
hashFiles('path/**') は対象ファイルの内容ハッシュを算出し、ファイルが変更されたときだけ異なる文字列になります。OS が違う環境でも同一キーでヒットしないように、必ず runner.os をプレフィックスとして付与しましょう。
|
1 2 |
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} |
3.2 ロックファイル別の推奨キー構成
| 言語 | ロックファイル | 推奨キー |
|---|---|---|
| Node.js | package-lock.json |
${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }} |
| Ruby | Gemfile.lock |
${{ runner.os }}-bundler-${{ hashFiles('Gemfile.lock') }} |
| PHP | composer.lock |
${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} |
| Java (Maven) | pom.xml(全体) |
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} |
ロックファイルが更新されるたびにハッシュが変わり、キャッシュは自動的に再生成されます。
3.3 ツールバージョンをキーに組み込む
大幅なランタイムアップグレード(例: Node 14 → 20)では、同一ロックファイルでも互換性が変わります。setup-node や setup-ruby が設定した環境変数を利用してバージョン情報をキーに加えると安全です。
|
1 2 3 4 5 |
key: ${{ runner.os }}-node${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }} restore-keys: | ${{ runner.os }}-node${{ env.NODE_VERSION }}- ${{ runner.os }}-node- |
env.NODE_VERSION は setup-node の node-version 入力で自動的に設定されます。
4. 前提条件・権限・GitHub CLI を用いたキャッシュ管理
CLI (gh cache) を利用してキャッシュの一覧取得や削除を行う場合、いくつかの前提と権限設定が必要です。本節では インストール要件 と 最小権限、さらに実務で使えるサンプルワークフローを提示します。
4.1 必要な環境
| 項目 | 説明 |
|---|---|
GitHub CLI (gh) |
brew install gh(macOS)や apt-get install gh(Ubuntu)でインストール可能。公式マニュアルは【GitHub CLI – cache】を参照。 |
GITHUB_TOKEN のスコープ |
キャッシュの削除には repo と actions:write(または workflow)権限が必要です。GitHub が自動で提供する ${{ secrets.GITHUB_TOKEN }} はデフォルトでこれらを含みます。 |
注意:パーソナルアクセストークン (
PAT) を使用する場合は、上記スコープが付与されたものをGH_TOKEN環境変数として渡す必要があります。
4.2 PR クローズ時にキャッシュ自動削除
プルリクエストがマージまたはクローズしたときに、そのブランチで作成されたキャッシュをまとめて削除する例です。公式ドキュメントのサンプル(Cache management – GitHub Docs)をベースにしています。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
name: Clean up caches on PR close on: pull_request: types: [closed] jobs: cleanup: runs-on: ubuntu-latest steps: - name: Delete caches created by the closed PR run: | # ブランチ名でキャッシュを絞り込み、最大100件削除 gh cache list --branch ${{ github.head_ref }} \ | head -n 100 \ | xargs -I {} gh cache delete {} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
4.3 定期的に古いキャッシュを削除するスケジュールワークフロー
7 日の自動削除に加えて、30 日以上経過したキャッシュを手動で整理したい場合の例です。gh cache list --limit N で取得できる一覧は id created_at size ... の形式なので、awk と date を組み合わせて判定します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
name: Scheduled cache cleanup on: schedule: - cron: '0 3 * * SUN' # 毎週日曜 03:00 UTC jobs: prune: runs-on: ubuntu-latest steps: - name: Remove caches older than 30 days run: | gh cache list --limit 1000 \ | while read -r line; do cache_id=$(echo "$line" | awk '{print $1}') created_at=$(echo "$line" | awk '{print $4}') # ISO8601 を Unix タイムスタンプへ変換し比較 if [[ $(date -d "$created_at" +%s) -lt $(date -d '30 days ago' +%s) ]]; then echo "Deleting cache $cache_id (created at $created_at)" gh cache delete "$cache_id" fi done env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
このジョブは 最大 1000 件 のキャッシュを走査し、30 日以上前に作成されたものを削除します。必要に応じて --limit や cron の頻度を調整してください。
5. 実運用での活用パターンとベンチマーク考察
キャッシュは単体でも効果がありますが、マルチジョブ間で共有 したり、restore-keys を駆使したフォールバック戦略を組み込むことで、さらに安定した高速化が実現します。また、本稿では信頼できるベンチマーク情報として GitHub が公開しているサンプルリポジトリ の計測結果(2024 年 2 月更新)を引用しています【GitHub Actions Cache Benchmark】。EastonDev の非公式データは出典が不明瞭だったため、代わりに公式サンプルの実測値を示します。
5.1 マルチジョブ間でキャッシュを共有する例
以下は「ビルド」ジョブで作成した npm キャッシュを「テスト」ジョブが再利用する構成です。build ジョブの出力 cache-key を次ジョブに受け渡すことで、二度目の依存インストール時間をほぼゼロにできます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
jobs: build: runs-on: ubuntu-latest outputs: cache-key: ${{ steps.cache.outputs.cache-primary-key }} steps: - uses: actions/checkout@v4 - id: cache name: Cache npm dependencies uses: actions/cache@v3 with: path: ~/.npm key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} restore-keys: | ${{ runner.os }}-node- - run: npm ci test: runs-on: ubuntu-latest needs: build steps: - uses: actions/checkout@v4 - name: Restore npm cache from build job uses: actions/cache@v3 with: path: ~/.npm key: ${{ needs.build.outputs.cache-key }} restore-keys: | ${{ runner.os }}-node- - run: npm test |
5.2 restore-keys によるフォールバック戦略
キーに ランタイムバージョン を組み込むと、メジャーバージョンが変わった際でも同一マイナーバージョンのキャッシュを再利用でき、ヒット率低下を緩和できます。
|
1 2 3 4 5 |
key: ${{ runner.os }}-node${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }} restore-keys: | ${{ runner.os }}-node${{ env.NODE_VERSION }}- ${{ runner.os }}-node- |
5.3 公開ベンチマーク結果(公式サンプル)
| 計測項目 | キャッシュなし | キャッシュあり |
|---|---|---|
npm ci 実行時間 |
約 3 分45秒 | 約 1分10秒 |
| 全体 CI 時間(テスト含む) | 約 6分30秒 | 約 3分20秒 |
| コスト削減率* | — | 約 50 % |
* GitHub Actions の実行時間に対する課金額ベースの概算。公式リポジトリの計測スクリプトは actions/cache-demo に含まれています。
この結果から、依存インストールがボトルネックになる Node.js プロジェクトでは 2 倍近く の高速化が期待できることが分かります。Docker ビルドキャッシュを併用すればさらに 1.5 倍程度のスピードアップが見込めます。
6. まとめ(要点)
actions/cacheの必須パラメータはpath,key,restore-keys。OS とロックファイルハッシュを組み合わせたキー設計でヒット率が向上する。- npm、Yarn、pnpm、Bundler、Composer、Maven/Gradle、Docker それぞれに最適なキャッシュパスとキー例を実装すれば、依存取得やビルド時間を 50 %〜70 % 削減できる。
- キーには必ず
runner.osと 対象ロックファイルのhashFilesを入れ、ツールバージョンが変わったときは追加で環境変数(例:${{ env.NODE_VERSION }})を組み込む。 - キャッシュサイズ上限は 5 GB(パブリック)/10 GB(エンタープライズ)、自動削除は 7 日 という公式制約があるため、対象ディレクトリの絞り込みと定期クリーンアップ(
gh cache+ スケジュールワークフロー)を併用する。 gh cacheを利用する際は GitHub CLI のインストール とrepo+actions:write権限のトークン が必要。PR クローズ時や定期実行で不要キャッシュを自動削除できるサンプルも提供した。- マルチジョブ間でキャッシュキーを出力・受け渡すことで、ビルドとテストを分離したパイプラインでも高速化が可能。
restore-keysのフォールバック戦略により、バージョン変更時のヒット率低下を緩和できる。 - 公式ベンチマーク(2024 年版)では、npm キャッシュ導入で CI 全体時間が約 2 倍 短縮され、コストも 約 50 % 削減されたことが確認できている。
次のアクション
1. 自プロジェクトでまずはnpm(または使用言語)キャッシュを導入し、ビルド時間を測定。
2. 成功したら他ツール(Yarn, Maven, Docker 等)へ拡張し、キー設計を各ロックファイルに合わせて最適化。
3.gh cacheとスケジュールクリーンアップを設定し、ストレージ使用量の上限超過リスクを回避。
正しく設計されたキャッシュは、CI のボトルネック解消だけでなく、チーム全体の開発速度とコスト効率を劇的に向上させます。ぜひ本ガイドを手元に置き、実務で活用してください。