先日, 「GitHub Actionsの知見ご紹介」でactions/cache
が意図通り動作しないケースがある, ということをご紹介しました. 今回は, actions/cache
の代わりにS3を使ってキャッシュを実現する方法をご紹介します. ...まあ, ご紹介しますというか, まあ普通にaws
コマンドを使って必要なファイルをS3に置いたり引っ張ってきたりするだけなのですが.
ここでは, 例としてcpanfile.snapshot
を元にして, Perlのモジュールがインストールされるディレクトリ(local
)をS3でキャッシュする例をご紹介します.
Node.jsであれば, cpanfile.snapshot
をpackage.json
, local
をnode_modules
と読み替えればOKです.
前提として, 適当なS3バケット(以下の例では, sample-cache-bucket
という名前としました)を用意しておいてください.
また, S3への読み書きが可能なIAMアカウントを用意して, そのAccess Key IDとSecret Access KeyをGitHubのSecrets(リポジトリのSettings
→Secrets
)で, それぞれAWS_ACCESS_KEY_ID
とAWS_SECRET_ACCESS_KEY
という名前で登録しておく必要があります.
env: cache-bucket: sample-cache-bucket cache-directory: perl jobs: prepare: runs-on: ubuntu-latest steps: - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ap-northeast-1 - name: Fetch cached perl modules run: | if [[ $(aws s3 ls s3://${{ env.cache-bucket }}/${{ env.cache-directory }}/${{ hashFiles('cpanfile.snapshot') }}.tar.gz | wc -l) > 0 ]]; then aws s3 cp --no-progress s3://${{ env.cache-bucket }}/${{ env.cache-directory }}/${{ hashFiles('cpanfile.snapshot') }}.tar.gz perl-modules.tar.gz tar -zxf perl-modules.tar.gz else echo "Cache not found" fi # ここで必要に応じてライブラリのインストール(carton install, npm installなど)を実行する - name: Cache perl modules run: | if [[ $(aws s3 ls s3://${{ env.cache-bucket }}/${{ env.cache-directory }}/${{ hashFiles('cpanfile.snapshot') }}.tar.gz | wc -l) > 0 ]]; then echo "Cache already exists" else tar -zcf perl-modules.tar.gz local aws s3 cp --no-progress perl-modules.tar.gz s3://${{ env.cache-bucket }}/${{ env.cache-directory }}/${{ hashFiles('cpanfile.snapshot') }}.tar.gz fi
...少なくとも, runs-on
がubuntu-latest
の場合, デフォルトでaws
コマンドが/usr/local/bin/aws
に用意されています.
2020年5月現在バージョンは1.18.37
となっているようで, 最新の2系ではないのですが, 例なので今回はこれをそのままを使うことにしましょう(より新しいバージョンのaws
コマンドが必要であれば, 別途インストールしてください).
後はaws-actions/configure-aws-credentials@v1
を利用して適切にAWSアカウントの認証(ここでSecretsで設定したAWS_ACCESS_KEY_ID
とAWS_SECRET_ACCESS_KEY
を利用します)をした上で, aws
コマンドを使って
S3からファイルを撮ってくる/ファイルを設置するだけです.
これで,
cpanfile.snapshot
に対応するキャッシュがあれば...- S3からこれをダウンロードして利用する
- 必要なライブラリは全てキャッシュから復元されているはずなので, ライブラリのインストールをしても差分なしですぐに完了する
cpanfile.snapshot
が書き換えられるなどしており, 対応するキャッシュがないなら...- ライブラリのインストールを実行して, その結果を最後にS3にアップロードする
- 2回目以降はキャッシュが利用されるようになる
...という挙動が実現できます.
S3を使えば, 前のエントリで紹介したactions/cache
のハマりポイントを意識する必要はありませんし(2〜3週間運用していますが, キャッシュの取得にミスした事例はほぼほぼなくなった), 必要があればAWSのWebコンソールなどを使って, キャッシュを削除したりできるので, 適切なS3バケットが用意できるのであればむしろこちらの方が便利なのでは...? という気がしています.
一方で, 当然ながら別途S3の料金が必要になるのはデメリットですね. なるべく料金を節約できるよう, ライフサイクルルールを設定するなどしつつ利用すると良さそうです.