CircleCIで実行バイナリをDLしてCI内でキャッシュしながら使う
CI内でどこかしらから実行バイナリをダウンロードして、それを使うことがあると思います。 最近では僕はOPAのテストをCircleCIで実行したかったので、OPAのバイナリをダウンロードしてテストを実行しました。
毎回バイナリをダウンロードしてCircleCIを回すのもコストが高いので、CircleCIのキャッシュを使う方法について共有します!
実行バイナリをDockerイメージに入れてそれをCIで使う方法もありますが、今回は実行バイナリをダウンロードして使う方法でやります!
キャッシュせずにやった場合
まずはキャッシュのことを考えずにCIしてみると、以下のような流れになります。(OPAの例です)
version: 2 jobs: build: docker: - image: circleci/buildpack-deps:jessie steps: - checkout - run: name: Download OPA command: | mkdir .bin wget -O .bin/opa https://github.com/open-policy-agent/opa/releases/download/v0.10.6/opa_linux_amd64 sudo chmod +x .bin/opa - run: name: Test Policies command: .bin/opa test .
- チェックアウト
- OPAのバイナリをGitHubからダウンロードして実行権限付与
- OPAのテスト実行
という感じです。特につまるところは無いと思います。
ただしこれにはパフォーマンスの問題があって、CIの度にOPAのバイナリをGitHubからダウンロードしてくるのが無駄です。 このバイナリもそんなにしょっちゅう変わるものでも無いので、ダウンロードが一度で済ませられたら良いですよね。
そこで使えるのがCircleCIのキャッシュです!
キャッシュして効率化
CircleCIには save_cache
と restore_cache
という便利な機能があります。
キーを基にCircleCI側にファイルやディレクトリなどをキャッシュしておくことができます。
よく見る場面としては、依存パッケージなどをキャッシュしておくときです。( node_modules
や vendors
ディレクトリなど)
ポイントとなるのがキャッシュの「キーの決め方」です。
まずはあまり工夫をせずにキャッシュの手順を加えて見ます。
version: 2 jobs: build: docker: - image: circleci/buildpack-deps:jessie steps: - checkout - restore_cache: key: opa-cache-0.10.6 - run: name: Download OPA command: | if [ ! -f .bin/opa ]; then mkdir .bin wget -O .bin/opa https://github.com/open-policy-agent/opa/releases/download/v0.10.6/opa_linux_amd64 sudo chmod +x .bin/opa fi - run: name: Test Policies command: .bin/opa test . - save_cache: key: opa-cache-0.10.6 paths: - .bin
- チェックアウト
- キャッシュがあれば復元
- OPAのバイナリが 無ければ GitHubからダウンロードして実行権限付与
- OPAのテスト実行
- OPAのバイナリをキャッシュしておく
restore_cache
と save_cache
のキーには opa-cache-0.10.6
を使っています。
これは、OPAのバイナリのバージョンが変わったらキャッシュもちゃんと変わるようにするためです。
ただし、これってバージョンが変わるたびに少なくとも3箇所( 0.10.6
となってる部分)は変えないといけないので微妙ですよね。
ということでどうにか1箇所に集約できないかと考えてしまいます。
ちょっとトリッキーなのが、環境変数が restore_cache
や save_cache
の key
に使えない点です(少なくとも僕の2019/04/19時点での認識では)。
- restore_cache: key: opa-cache-${OPA_VERSION}
上記のように書けるとすっきりしそうなんですけど、これができません。ではどうするかというと、以下のフォーラムでやり方を見つけることができました。
次のように書き換えることができます。
- run: name: Setup Environment Variables and Version file command: | echo 'export OPA_VERSION="0.10.6"' >> $BASH_ENV echo "${OPA_VERSION}" > _opa_version_ - restore_cache: key: opa-cache-{{ checksum "_opa_version_" }}
- 環境変数OPA_VERSIONにバージョン番号を入れて
- バージョン番号を
_opa_version_
というファイルにリダイレクト _opa_version_
のchecksum
をキャッシュのキーとして使う
言われてみれば「あ、その手があったか!」ってなります。
ということでこの方法で config.yml
を書き換えると下のようになります。
version: 2 jobs: build: docker: - image: circleci/buildpack-deps:jessie steps: - checkout - run: name: Setup Environment Variables and Version file command: | echo 'export OPA_VERSION="0.10.6"' >> $BASH_ENV echo "${OPA_VERSION}" > _opa_version_ - restore_cache: keys: - opa-cache-{{ checksum "_opa_version_" }} - run: name: Download OPA command: | if [ ! -f .bin/opa ]; then mkdir .bin wget -O .bin/opa https://github.com/open-policy-agent/opa/releases/download/v${OPA_VERSION}/opa_linux_amd64 sudo chmod +x .bin/opa fi - run: name: Test Policies command: .bin/opa test . - save_cache: key: opa-cache-{{ checksum "_opa_version_" }} paths: - .bin
こうすることで下の一行を変えるだけで、OPAの実行バイナリのバージョンを切り替えることができます!
echo 'export OPA_VERSION="0.10.6"' >> $BASH_ENV
今の所の僕の最適解はこのやり方になるのですが、他にも良い方法があればぜひとも知りたいところです!
おわりに
- 依存ライブラリ以外にもCircleCIの
save_cache
やresotre_cache
は使える - 一工夫すればキャッシュのキーに環境変数で設定したバージョン番号を指定できる
参考
ちょうど「CircleCI 福岡ミートアップ」が開催されて、その中でもキャッシュについて触れている発表があったようです!