AWS CodeBuildで依存ライブラリのキャッシュを利用する

会社ブログに書きましたが、その続き、というかAWS CodeBuildのビルド時間を短縮するための小ネタです。

AWS CodeBuildはビルド時に新しく実行環境を起動するため、クリーンな環境でのビルドが行える一方、jarなりgemなりの依存ライブラリをビルドのたびにダウンロードしてしまうので、ビルド時間がかさんでしまいます。

今のところサービス標準の機能として、特定のディレクトリをキャッシュして再利用する、みたいなことはできないみたいなので、 buildspec.yml 側で対応する仕組みを考えてみました。

Gradle の場合、こんな感じです(ポイントだけ抜粋)

version: 0.2

phases:
  install:
    commands:
      - aws configure set s3.signature_version s3v4
      - aws s3 cp --region ap-northeast-1 $GRADLE_CACHE_S3_URL /tmp/gradle-caches.tar.gz
      - mkdir -p $GRADLE_USER_HOME/caches
      - tar -zxf /tmp/gradle-caches.tar.gz -C $GRADLE_USER_HOME/caches
  build:
    commands:
      - ./gradlew build
  post_build:
    commands:
      - tar -zcf gradle-caches.tar.gz -C $GRADLE_USER_HOME/caches .
artifacts:
  files:
    - gradle-caches.tar.gz
  discard-paths: no

ビルド後の post_build フェーズ時 *1$GRADLE_USER_HOME/caches の中身を tarball にし、成果物(アーティファクト)としてS3にアップロードします。毎回のビルド開始時にはそのファイルを展開する、という方法です。 tarball の中身が足りない場合は ./gradlew build 実行時に不足分のライブラリがダウンロードされるはずです。

ちなみに初回はS3にファイルがないので、その部分の対応は必要になります(今回は省略)。

*1: この時点ではすべての依存ライブラリのダウンロードが終わっているはずです。