Skip to main content

依存関係をキャッシュしてワークフローのスピードを上げる

ワークフローを高速化して効率を上げるために、依存関係や広く再利用されるファイルに対するキャッシュを作成して利用できます。

ワークフローの依存関係のキャッシングについて

ワークフローの実行は、しばしば他の実行と同じ出力あるいはダウンロードされた依存関係を再利用します。 たとえばMaven、Gradle、npm、Yarnといったパッケージ及び依存関係管理ツールは、ダウンロードされた依存関係のローカルキャッシュを保持します。

依存関係などのファイルの再生成にかかる時間を短縮しやすくするために、GitHub ではワークフロー内で頻繁に使われるファイルをキャッシュできます。

ジョブの依存関係をキャッシュするには、GitHub の cache アクションを使用できます。 このアクションは、一意のキーによって識別されるキャッシュを作成し、復元します。 なお、以下に示すパッケージ マネージャーをキャッシュする場合、それぞれの setup-* アクションを使用するには、最小構成が必要となります。これにより、依存関係キャッシュが作成され、復元されます。

パッケージ マネージャーキャッシュの setup-* アクション
npm、Yarn、pnpmsetup-node
pip、pipenv、Poetrysetup-python
Gradle、Mavensetup-java
RubyGemssetup-ruby
Go go.sumsetup-go
.NET NuGetsetup-dotnet

警告: キャッシュには、機密情報を保存しないことをお勧めします。 たとえばキャッシュパス内のファイルに保存されたアクセストークンあるいはログインクレデンシャルなどがセンシティブな情報です。 また、docker login のようなコマンド ライン インターフェイス (CLI) プログラムでは、アクセス資格情報を構成ファイルに保存できます。 読み取りアクセスを持つ人は誰でも、リポジトリに pull request を作成し、キャッシュの内容にアクセスできます。 リポジトリのフォークも、ベースブランチ上にPull Requestを作成し、ベースブランチ上のキャッシュにアクセスできます。

成果物の比較と依存関係のキャッシング

成果物とキャッシングは、GitHubにファイルを保存できるようにするので似ていますが、それぞれの機能のユースケースは異なっており、入れ替えて使うことはできません。

  • パッケージ管理システムからのビルドの依存関係など、ジョブまたはワークフローの実行の間で頻繁に変更されないファイルを再利用する場合は、キャッシュを使用します。
  • ビルドされたバイナリやビルド ログなど、ワークフローの実行が終了した後に表示するためにジョブによって生成されたファイルを保存する場合は、成果物を使用します。

ワークフロー実行の成果物について詳しくは、「ワークフローからのデータの格納と共有」をご覧ください。

キャッシュへのアクセスについての制限

アクセス制限を使用すると、さまざまなブランチまたはタグ間に論理境界を作成することで、キャッシュを分離しセキュリティで保護することができます。 ワークフロー実行では、現在のブランチまたは既定のブランチ (通常は main) で作成されたキャッシュを復元できます。 pull request に対してワークフロー実行がトリガーされた場合は、ベース ブランチで作成されたキャッシュを復元することもできます (フォークされたリポジトリのベース ブランチも含む)。 たとえば、ブランチ feature-b にベース ブランチ feature-a がある場合、pull request でトリガーされたワークフロー実行では、既定のブランチ main、ベース ブランチ feature-a、および現在のブランチ feature-b で作成されたキャッシュにアクセスできます。

ワークフロー実行では、子ブランチまたは兄弟ブランチ用に作成されたキャッシュを復元することはできません。 たとえば、子ブランチ feature-b 用に作成されたキャッシュに、親ブランチ main でトリガーされたワークフロー実行からアクセスすることはできません。 同様に、ベース main を持つブランチ feature-a 用に作成されたキャッシュに、ベース main を持つその兄弟ブランチ feature-c からアクセスすることはできません。 また、ワークフロー実行では、異なるタグ名に対して作成されたキャッシュを復元することもできません。 たとえば、タグ release-a に対してベース main で作成されたキャッシュに、タグ release-b に対してベース main でトリガーされたワークフロー実行からアクセスすることはできません。

pull request でトリガーされたワークフロー実行によってキャッシュが作成される場合、そのキャッシュは merge ref (refs/pull/.../merge) に対して作成されます。 このため、このキャッシュのスコープは制限され、pull request の再実行によってのみ復元できます。 ベース ブランチ、またはそのベース ブランチを対象とする他の pull request では、復元できません。

リポジトリ内の複数のワークフロー実行で、キャッシュを共有できます。 あるワークフロー実行でブランチ用に作成されたキャッシュは、同じリポジトリとブランチの別のワークフロー実行からアクセスおよび復元できます。

cache アクションの使用

cache action アクションは、指定した key に基づいてキャッシュの復元を試みます。 アクションがそのキーと "厳密に" 一致するキャッシュを見つけた場合、構成した path にキャッシュされたファイルが復元されます。 必要に応じて、key が既存のキャッシュと一致しない場合に使用する restore-keys のリストを指定できます。 restore-keys のリストは、別のブランチからキャッシュを復元する場合に便利です。restore-keys はキャッシュ キーと "部分的に" 一致する可能性があるためです。 restore-keys の照合の詳細については、「キャッシュ キーのマッチング」を参照してください。

指定した key との完全な一致があった場合は、キャッシュ ヒットと見なされます。 指定した key と完全に一致するキャッシュがなかった場合は、キャッシュ ミスと見なされます。 キャッシュ ミスの場合は、ジョブが正常に完了すると、このアクションによって新しいキャッシュが自動的に作成されます。 新しいキャッシュでは、指定した key が使用され、path で指定したファイルが含められます。 この処理方法について詳しくは、「キャッシュ ヒットとキャッシュ ミス」を参照してください。

既存のキャッシュの内容を変更することはできません。 代わりに、新しいキーを使って新しいキャッシュを作成できます。

cache アクションの入力パラメーター

  • key: 必須 キャッシュの保存時に作成されたキーと、キャッシュの検索に使用されるキー。 変数、コンテキスト値、静的な文字列、関数の任意の組み合わせが使えます。 キーの長さは最大で512文字であり、キーが最大長よりも長いとアクションは失敗します。

  • path: 必須 キャッシュまたは復元するランナー上のパス。

    • 1 つのパスを指定することも、複数のパスを別々の行に追加することもできます。 たとえば次のような点です。

      - name: Cache Gradle packages
        uses: actions/cache@v3
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
      
    • ディレクトリまたは単一ファイルのいずれかを指定できます。glob パターンがサポートされています。

    • 絶対パス、またはワークスペース ディレクトリに対する相対パスを指定できます。

  • restore-keys: オプション 代替の復元キーを含んだ文字列。各復元キーは新しい行に配置されます。 key に対するキャッシュ ヒットが発生しない場合は、キャッシュを検索して復元するために、これらの復元キーが指定された順序で使用されます。 たとえば次のような点です。

    restore-keys: |
      npm-feature-${{ hashFiles('package-lock.json') }}
      npm-feature-
      npm-
    
  • enableCrossOsArchive: 省略可能 ブール値。有効の場合、キャッシュが作成されたオペレーティング システムに関係なく、Windows ランナーがキャッシュを保存または復元できます。 このパラメーターが設定されていない場合、既定値は false になります。 詳しくは、Actions Cache に関するドキュメントの「Cross OS cache (クロス OS キャッシュ)」を参照してください。

cache アクションの出力パラメーター

  • cache-hit: キーに対して完全一致が見つかったかどうかを示すブール値。

キャッシュ ヒットとキャッシュ ミス

key が既存のキャッシュと厳密に一致した場合、それは "キャッシュ ヒット" と呼ばれ、アクションによってキャッシュされたファイルが path ディレクトリに復元されます。

key が既存のキャッシュと一致しない場合 (これは キャッシュ ミス と呼ばれます)、ジョブが正常に完了すると、新しいキャッシュが作成されます。

キャッシュ ミスが発生した場合、アクションはユーザーが指定した restore-keys の一致も検索します。

  1. restore-keys を指定した場合、cache アクションは restore-keys のリストに一致するすべてのキャッシュを順次検索します。
    • 完全に一致する場合、アクションはキャッシュ内のファイルを path ディレクトリに復元します。
    • 完全なマッチがなかった場合、アクションはリストアキーに対する部分一致を検索します。 アクションで部分的な一致が見つかると、最新のキャッシュが path ディレクトリに復元されます。
  2. cache アクションが完了し、ジョブの次のステップが実行されます。
  3. ジョブが正常に完了すると、アクションは path ディレクトリのコンテンツを含んだ新しいキャッシュを自動的に作成します。

キャッシュ照合プロセスの詳細については、「キャッシュキーのマッチング」を参照してください。

cache アクションの使用例

次の例では、package-lock.json ファイル内のパッケージが変更されたとき、またはランナーのオペレーティング システムが変更されたときに、新しいキャッシュを作成します。 キャッシュ キーは、コンテキストと式を使用して、ランナーのオペレーティング システムと package-lock.json ファイルの SHA-256 ハッシュを含むキーを生成します。

YAML
name: Caching with npm
on: push
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Cache node modules
        id: cache-npm
        uses: actions/cache@v3
        env:
          cache-name: cache-node-modules
        with:
          # npm cache files are stored in `~/.npm` on Linux/macOS
          path: ~/.npm
          key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-build-${{ env.cache-name }}-
            ${{ runner.os }}-build-
            ${{ runner.os }}-

      - if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }}
        name: List the state of node modules
        continue-on-error: true
        run: npm list

      - name: Install dependencies
        run: npm install

      - name: Build
        run: npm run build

      - name: Test
        run: npm test

コンテキストを使ったキャッシュキーの作成

キャッシュキーには、コンテキスト、関数、リテラル、GitHub Actionsがサポートする演算子を含めることができます。 詳細については、「ワークフロー実行に関するコンテキスト情報へのアクセス」および「ワークフローとアクションで式を評価する」を参照してください。

式を使用して key を作成すると、依存関係が変更されたときに新しいキャッシュを自動的に作成できます。

たとえば、npm package-lock.json ファイルのハッシュを計算する式を使用して key を作成できます。 その場合、package-lock.json ファイルを構成する依存関係が変更されると、キャッシュ キーが変更され、新しいキャッシュが自動的に作成されます。

npm-${{ hashFiles('package-lock.json') }}

GitHub は、式 hash "package-lock.json" を評価して最終的な key を導き出します。

npm-d5ea0750

cache アクションの出力の使用

cache アクションの出力を使用すると、キャッシュ ヒットやキャッシュ ミスが発生したどうかに基づいて操作を実行することができます。 指定した key のキャッシュに完全一致が見つかった場合、cache-hit の出力は true に設定されます。

上記のワークフロー例では、キャッシュ ミスが発生した場合に、Node モジュールの状態をリストする手順があります。

- if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }}
  name: List the state of node modules
  continue-on-error: true
  run: npm list

キャッシュキーのマッチング

cache アクションは、最初にワークフロー実行を含むブランチで、key とキャッシュ "バージョン" のキャッシュ ヒットを検索します。 ヒットがない場合は、restore-keys と "バージョン" を検索します。 それでも現在のブランチにヒットがない場合、cache アクションは既定のブランチに対して同じ手順を再試行します。 検索中はスコープの制限が適用されることに注意してください。 詳しくは、「キャッシュへのアクセスについての制限」を参照してください。

キャッシュ バージョンは、キャッシュの作成時に使用された path と圧縮ツールのメタデータを使って、キャッシュにスタンプを付ける方法です。 これにより、使用するワークフロー実行が、実際に圧縮を解除して使用できるキャッシュと一意に一致することが保証されます。 詳しくは、Actions Cache に関するドキュメントの「Cache Version (キャッシュ バージョン)」を参照してください。

restore-keys では、key でキャッシュ ミスが発生した場合に使用する代替復元キーのリストを指定できます。 特定の度合いが強いものから弱いものへ並べて複数のリストアキーを作成できます。 cache アクションは restore-keys を順番に検索します。 キーが直接マッチしなかった場合、アクションはリストアキーでプレフィックスされたキーを検索します。 リストアキーに対して複数の部分一致があった場合、アクションは最も最近に作成されたキャッシュを返します。

複数のリストアキーの利用例

restore-keys: |
  npm-feature-${{ hashFiles('package-lock.json') }}
  npm-feature-
  npm-

ランナーは式を評価し、次の restore-keys に解決します。

restore-keys: |
  npm-feature-d5ea0750
  npm-feature-
  npm-

復元キー npm-feature- は、文字列 npm-feature- で始まるすべてのキーと一致します。 たとえば、npm-feature-fd3052de および npm-feature-a9b253ff の両方のキーと復元キーが一致します。 最も最近の期日に作成されたキャッシュが使われます。 この例でのキーは、以下の順序で検索されます。

  1. npm-feature-d5ea0750 は特定のハッシュと一致します。
  2. npm-feature-npm-feature- というプレフィックスが付いたキャッシュ キーと一致します。
  3. npm-npm- というプレフィックスが付いたすべてのキーと一致します。

検索の優先度の例

key:
  npm-feature-d5ea0750
restore-keys: |
  npm-feature-
  npm-

たとえば、pull request が feature ブランチを含んでいて、既定のブランチ (main) をターゲットとしている場合、アクションは keyrestore-keys を次の順序で検索します。

  1. feature ブランチ内npm-feature-d5ea0750のキー
  2. feature ブランチ内のキー npm-feature-
  3. feature ブランチ内のキー npm-
  4. main ブランチ内のキー npm-feature-d5ea0750
  5. main ブランチ内のキー npm-feature-
  6. main ブランチ内のキー npm-

利用制限と退去のポリシー

GitHubは、7日間以上アクセスされていないキャッシュエントリを削除します。 保存できるキャッシュの数に制限はありませんが、リポジトリ内のすべてのキャッシュの合計サイズは制限されています。 既定では、リポジトリあたり 10 GB の制限ですが、この制限は、エンタープライズ所有者やリポジトリ管理者が設定したポリシーによって変わる場合があります。 リポジトリがその最大キャッシュ ストレージに達すると、キャッシュの削除ポリシーによって、リポジトリ内の最も古いキャッシュが削除されてスペースが作成されます。

この制限を超えると、GitHub は新しいキャッシュを保存しますが、合計サイズがリポジトリの制限を下回るまでキャッシュの削除を開始します。 キャッシュの削除プロセスが原因で、キャッシュのスラッシングが発生する場合があります。その場合は、キャッシュが高い頻度で作成および削除されます。 これを軽減するには、リポジトリのキャッシュを確認し、修正手順を実行できます (特定のワークフローからキャッシュを削除するなど)。 詳細については、「キャッシュの管理」を参照してください。リポジトリのキャッシュ サイズ制限を増やすこともできます。 詳しくは、「リポジトリの GitHub Actions の設定を管理する」を参照してください。

キャッシュの管理

ワークフローから作成されたキャッシュを管理する場合、次の操作を実行できます。

  • リポジトリの全キャッシュ エントリの一覧を表示する。
  • 特定のメタデータを使って、キャッシュの一覧のフィルター処理と並べ替えを行う (キャッシュ サイズ、作成日時、最終アクセス日時など)。
  • リポジトリからキャッシュ エントリを削除する。
  • リポジトリと組織の集計されたキャッシュ使用状況を監視する。

リポジトリのキャッシュを管理する方法は複数あります。

  • 以下に示すように、GitHub Web インターフェイスを使う。

  • REST API を使う。 詳しくは、「GitHub Actions キャッシュの REST API エンドポイント」を参照してください。

  • コマンド・ラインからキャッシュを管理するための gh cache サブコマンドのインストール。 詳しくは、「GitHub CLI のドキュメント」をご覧ください。

    注: これを手動で行う場合は、バージョン 2.32.0 以降の CLI がインストールされていることを確認してください。

キャッシュ エントリの表示

Web インターフェイスを使って、リポジトリのキャッシュ エントリの一覧を表示できます。 キャッシュの一覧では、各キャッシュで使用されているディスク領域の量、キャッシュが作成された日時、キャッシュが最後に使用された日時を確認できます。

  1. GitHub で、リポジトリのメイン ページに移動します。

  2. リポジトリ名の下にある [アクション] をクリックします。

    "github/docs" リポジトリのタブのスクリーンショット。 [アクション] タブがオレンジ色の枠線で強調表示されています。

  3. 左サイドバーの [管理] セクションで、 [キャッシュ] をクリックします。

  4. リポジトリのキャッシュ エントリの一覧を確認します。

    • 特定のブランチ用に使用されるキャッシュ エントリを検索するには、 [Branch] ドロップダウン メニューをクリックして、ブランチを選択します。 キャッシュの一覧に、選択したブランチ用に使用されるすべてのキャッシュが表示されます。
    • 特定のキャッシュ キーを持つキャッシュ エントリを検索するには、 [Filter caches] フィールドで構文 key: key-name を使用します。 キャッシュの一覧に、そのキーが使用されたすべてのブランチのキャッシュが表示されます。

    キャッシュ エントリの一覧のスクリーンショット。

キャッシュ エントリの削除

リポジトリへの write アクセス権を持つユーザーは、GitHub Web インターフェイスを使ってキャッシュ エントリを削除できます。

  1. GitHub で、リポジトリのメイン ページに移動します。

  2. リポジトリ名の下にある [アクション] をクリックします。

    "github/docs" リポジトリのタブのスクリーンショット。 [アクション] タブがオレンジ色の枠線で強調表示されています。

  3. 左サイドバーの [管理] セクションで、 [キャッシュ] をクリックします。

  4. 削除するキャッシュ エントリの右側にある をクリックします。

    キャッシュ エントリの一覧のスクリーンショット。 キャッシュの削除に使用されるごみ箱アイコンあが、濃いオレンジ色の枠線で強調表示されています。

キャッシュ エントリの強制削除

キャッシュにはブランチ スコープの制限が設定されています。つまり、一部のキャッシュは使用オプションが制限されます。 キャッシュ スコープの制限について詳しくは、「依存関係をキャッシュしてワークフローのスピードを上げる」をご覧ください。 特定のブランチに限定されたキャッシュで大量のストレージ クォータが使用されている場合は、default ブランチからのキャッシュが頻繁に作成および削除される可能性があります。

たとえば、リポジトリでは新しい pull request が多数オープンされ、それぞれがそのブランチに制限された独自のキャッシュがある場合があります。 これらのキャッシュは、そのリポジトリのキャッシュ ストレージの大部分を占める可能性があります。 リポジトリがその最大キャッシュ ストレージに達すると、キャッシュの削除ポリシーによって、リポジトリ内の最も古いキャッシュが削除されてスペースが作成されます。 このような場合にキャッシュのスラッシングを防ぐため、キャッシュの削除ポリシーよりも速い周期でキャッシュを削除するようにワークフローを設定できます。 gh-actions-cache CLI 拡張機能を使用して、特定のブランチのキャッシュを削除できます。

次のワークフローの例では、gh-actions-cache を使用して、pull request が閉じられた後にブランチによって作成された最大 100 個のキャッシュを削除します。

リポジトリ間の pull request またはフォークからの pull request で次の例を実行するには、pull_request_target イベントを使用してワークフローをトリガーできます。 ワークフローのトリガーに pull_request_target を使用する場合は、セキュリティに関する考慮事項に留意する必要があります。 詳しくは、「ワークフローをトリガーするイベント」を参照してください。

name: cleanup caches by a branch
on:
  pull_request:
    types:
      - closed

jobs:
  cleanup:
    runs-on: ubuntu-latest
    steps:
      - name: Cleanup
        run: |
          gh extension install actions/gh-actions-cache

          echo "Fetching list of cache key"
          cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH -L 100 | cut -f 1 )

          ## Setting this to not fail the workflow while deleting cache keys.
          set +e
          echo "Deleting caches..."
          for cacheKey in $cacheKeysForPR
          do
              gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
          done
          echo "Done"
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          REPO: ${{ github.repository }}
          BRANCH: refs/pull/${{ github.event.pull_request.number }}/merge

または、API を使用して、独自の周期ですべてのキャッシュを自動で一覧表示または削除することもできます。 詳しくは、「GitHub Actions キャッシュの REST API エンドポイント」を参照してください。