Edited at

CircleCI 2.0 キャッシュ指定で詰まったこと

CircleCIの1.0が8月でサポート終了ということで、先月くらいに、重い腰をあげて作業していました。

いくつかキャッシュの指定関連で詰まって、試行錯誤したのでメモしておきます。


ディレクトリをjob単位で設定できない

以前書いたこの記事の内容です。

CircleCI 2.0でbuild_dirを指定する

1.0ではbuild_dirという設定があり、checkoutしたリポジトリルートからたどる場所をjob単位で簡単に固定できましたが、

2.0ではtask単位で指定する必要があります。

(2.0でjob単位で指定できるのはリポジトリルートの場所だけ)

名前はworking_directoryという名前に変更されています。

- Equivalent of CircleCI 1.0 build_dir

ただし、working_directoryrundeploy等のタスクにしか適用されず、

キャッシュ関連のタスクである、save_cache,restore_cacheには適用されません :scream:


対策

なのでkey等でファイルのchecksumを参照する場合はrootパスから指定する必要があります。

上記記事の再掲ですが、以下のようにします。


ダメな例

      - restore_cache:

working_directory: api # ここのブロックには有効にならない
key: venv-{{ checksum "requirements.txt" }}
# ....
- save_cache:
working_directory: api # ここのブロックには有効にならない
key: venv-{{ checksum "requirements.txt" }}
paths: venv


いい例

      - restore_cache:

key: venv-{{ checksum "api/requirements.txt" }} # checksum関数に渡すときに示す。
# ....
- save_cache:
key: venv-{{ checksum "api/requirements.txt" }}
paths: api/venv # 保存するパスもきちんと示す


キャッシュキーに環境変数を指定できない

キャッシュのキーは特殊なリテラルでchecksum等を指定できます。

使える関数はこちら: using-keys-and-templates

いかに少し転記します。

Template
Description

{{ .Branch }}
The VCS branch currently being built.

{{ .BuildNum }}
The CircleCI build number for this build.

{{ .Revision }}
The VCS revision currently being built.

{{ .Environment.variableName }}
The environment variable variableName (supports any environment variable exported by CircleCI or added to a specific Context—not any arbitrary environment variable).

{{ checksum "filename" }}

ここに書いてあるんですが、.Environment.variableNameを使えば環境変数もkeyに含めそうだな、と思っていました。

でも自分で設定した変数は使えないと書いてますね、、


ダメな方法

- save_cache:

key: v1-{{ epoch }}
paths:
- $(my cache dir) # 展開されない
- save_cache:
key: v1-{{ epoch }}
paths:
- $MY_CACHE_DIR # 環境変数も展開されない
- save_cache:
key: v1-{{ epoch }}
paths:
- {{ .Environment.MY_CACHE_DIR }} # これはCircleCIが設定した値しか入らない
- save_cache:
key: v1-{{ .Environment.MY_CACHE_DIR }} # keyでも同じ。
paths:
- /my/cache/dir

悲しいですね。


対策

pathの対策はhardcodeです :cry:


動く例

- save_cache:

key: v1-{{ epoch }}
paths:
- /my/cache/dir # hardcodeしよう

keyも基本的にはhardcodeですが、checksumとかで環境変数の値に応じてkeyを変えたいケースもありそうです。

その場合は環境変数を一回ファイルに書き出してchecksumします。


動く例1

- save_cache:

key: v1-{{ 1.0.0 }} # 環境変数もハードコードしちゃう
paths:
- /my/cache/dir

環境変数が展開できる場所でファイルに書き出し、そのファイルのchecksumをkeyに入れます。


動く例2

version: 2

jobs:
build:
# ...
environment:
MY_VERSION: 1.0.0
steps:
- checkout
- run: echo ${MY_VERSION} > _my_version # 展開される場所で書き出す。
- restore_cache:
key: v1-{{ checksum "_my_version" }} # ファイルのchecksumをkeyに入れる
# ...
- save_cache:
key: v1-{{ checksum "_my_version" }}
paths:
- /my/cache/dir

そもそもキャッシュすべきファイルが何か、っていうのも難しいですし、

基本的にバージョン依存はファイルとしてリポジトリに含まれるケースが多いので、

あまり遭遇しないかもしれませんね。


削除できない

一度キャッシュされた内容は削除できないようです。

上のように色々試行錯誤して、ちゃんとキャッシュされてるかを確認して行ったらゴミというか以前試した空のキャッシュができてしまって上書きもできなくなり困りました。


対策

特にないです。

試行錯誤中はkeyにtestとかprefixを入れるとか、名前や順番を変えて試すしかないです。

そのうち削除機能やフラグが実装されるかもしれませんね。。


まとめ

大体の問題は既にdiscuss.circleci.comで議論・回答されている内容かなと思うので、

困った時は見て見るといいな、と思います。

でも結構CircleCI担当者の回答が素っ気ないというか、「これで十分」「できないのでハードコードして」という感じでなんか冷たく感じました。

「忙しくて無理 :sweat: 」「いつか検討するからissueに入れておくね」「頑張るから待っててね〜」みたいな姿勢が欲しくなってしまいました。

贅沢ですね。