🛶

GitHub Actions Workflowのdependenciesのキャッシュ

2022/11/23に公開

概要

個人の備忘録としてGitHub Actionsでビルドを実行する際に必要となるdependenciesのキャッシュ方法についてまとめていきます。

参考
https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows

workflowのdependenciesのキャッシュについて

GitHub ActionsのworkflowではしばしばMavenやGradle,npmやyarnなどのパッケージ管理ツールを使って依存ライブラリをダウンロードすることがよくあると思います。

GitHubでホストされたランナー上で実行するJobはまっさらなイメージの状態で開始するため依存ライブラリを毎回ダウンロードする必要があり、これによりネットワークの利用やruntimeの利用時間増、そして料金コストの増加などが起きてしまいます。これを防ぐためGitHubはよく使うファイルをworkflow上でcacheすることができます。

Action上でcacheを利用するにはcache actionを利用します。このActionはユニークキーによってcacheの作成とリストアを行います。
他の方法として、下記の表に該当するパッケージマネージャーを利用している場合、その言語に該当するsetup- actionを利用することで最小のセットアップで依存ライブラリのキャッシュの作成とリストアが行えます。

パッケージマネージャ cache用のsetup action
npm, Yarn, pnpm setup-node
Gradle, Maven setup-java
RubyGems setup-ruby
Go go.sum setup-go

キャッシュアクセスのルールについて

workflowの実行でキャッシュのアクセスについて次のルールがありまあす

  • workflowの実行で現在のブランチとデフォルトブランチで保存されたキャッシュをリストアすることができます
    ex)デフォルトブランチmainで作成されたcacheをmainから派生して作成したブランチfeature/aがアクセスでき、さらにfeature/aはそのブランチ自身で作成したキャッシュにもアクセスできます
  • さらに対象ブランチの派生元ブランチで作成されたcacheにもアクセスできます
    ex)mainfeature/afeature/bの派生順で作成されている場合、feature/bはデフォルトブランチであるmainブランチのcacheと、さらにfeature/bブランチのの派生元ブランチであるfeature/aブランチで作成したcacheにもアクセスできます
  • 子ブランチまたは兄弟ブランチで作成したキャッシュはリストアすることはできません
    ex)mainブランチはその子ブランチのfeature/aで作成したcacheを復元できません。さらに、同じmainブランチから派生したfeature/bブランチは兄弟ブランチであるfeature/aブランチで作成されたcacheを復元することができません。
  • プルリクエスト作成をトリガーとして実行されたworkflowでキャッシュが作成された場合、そのキャッシュはmerge ref(refs/pull/.../merge)に対して作成されるため、プルリクエストが再実行される場合のみそのキャッシュを復元できます

cacheアクションの利用

cache actionは指定したkeyに基づいて保存したキャッシュをリストアします。指定したkeyに厳密に一致するキャッシュが存在する場合、設定したpathにキャッシュされたファイルを復元します。keyがマッチしなかった時のために、restore-keysで複数のキャッシュkeyのリストを指定することもできます。
指定してkeyに一致するキャッシュが存在する場合、GitHub Actionはキャッシュヒットとみなします。
指定keyに一致するキャッシュが存在しない場合、キャッシュミシュとみなして、job成功時に自動でキャッシュを新規作成します。

詳細
https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#cache-hits-and-misses

まずcacheを利用したGitHub Actionsのworkflowファイル全体を見ていきます。
例としてDockerコンテナをビルド・プッシュする例です。

name: ci

on:
  push:
    branches:
      - "main"

jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
      -
        name: Cache Docker layers
        uses: actions/cache@v3
        with:
          path: /tmp/.buildx-cache
          key: ${{ runner.os }}-buildx-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-buildx-
      -
        name: Login to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      -
        name: Build and push
        uses: docker/build-push-action@v3
        with:
          context: .
          push: true
          tags: user/app:latest
          cache-from: type=local,src=/tmp/.buildx-cache
          cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
      -
        # Temp fix
        # https://github.com/docker/build-push-action/issues/252
        # https://github.com/moby/buildkit/issues/1896
        name: Move cache
        run: |
          rm -rf /tmp/.buildx-cache
          mv /tmp/.buildx-cache-new /tmp/.buildx-cache

参考
https://docs.docker.com/build/ci/github-actions/examples/#local-cache

input

次の部分でactions/cacheを利用してキャッシュほ保存しています。

      -
        name: Cache Docker layers
        uses: actions/cache@v3
        with:
          path: /tmp/.buildx-cache
          key: ${{ runner.os }}-buildx-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-buildx-
  • key(required):部分でキャッシュを復元時に指定するkeyを指定します。
    指定値には変数やcontext値、static stringや関数などの組み合わせを利用できます。
    最大長が512文字です。
  • path(required):キャッシュを保存・復元するときのGitHub runner上のパスを指定します
  • restore-keys(optional):keyに指定した値でcacheがヒットしなかった際に代りに利用する代理keyのリストです。

output

cache-hit:指定したkeyでキャッシュヒットしたかどうかをboolean値で出力できます。

使用制限

  • 7日間アクセスがないキャッシュをGitHub Actionsは自動で削除します
  • ここのキャッシュのサイズ制限はなく、1リポジトリのトータルで10GBまでのキャッシュのみを保存できます。

キャッシュサイズの制限を超えるキャッシュを保存しようとすると、GitHubはサイズ制限内収まるまで古いキャッシュを削除します。キャッシュの作成と削除が頻繁に発生する場合に、削除プレセスがキャッシュスラッシュを起こす場合があります。これを回避するために、Managing Cacheなどを参考に、特定のworkflowの不要なキャッシュなどを削除するようにします。

Discussion