🦀

Rustのworkspace内をGitHub Actionsでキャッシュする(checksum-freshnessがくるまで)

に公開

Rustのプロジェクトでworkspace内に多数のcrates(補助ライブラリやCLI群など)を配置する場合、それらのビルド結果も GitHub Actions のキャッシュの対象にしたくなります。毎回workspace内のすべてのcratesを変更することはないからです。しかしこれをするときのハマり所があります。

Rustプロジェクトでよく使われるGitHub Actions用アクションの Swatinem/rust-cache にも cache-workspace-crates オプションがありますが、これを有効にするだけでは、キャッシュは保存されるものの、実際には使われません。sccache などでも同じことが起きるでしょう。

原因

依存関係の再ビルドが必要かを判断するための "fingerprint" が、今のところファイルの変更時刻 (mtime) をもとに計算されているからです。GitHub Actions などのCI上ではソースコードのチェックアウト時に mtime が変更されてしまうため、workspace内のcrateに関しては内容が変化したと判定されキャッシュが使われなくなります。

なお、この fingerprint を、mtimeではなく、ファイルの内容から計算するように変えようとする checksum-freshness という unstable feature が存在します。

https://doc.rust-lang.org/cargo/reference/unstable.html#checksum-freshness

現時点での対処

上述の unstable feature を使わずにやるには、mtime を復元してあげるとよさそうです。mtime を各ファイルのコミット時刻に書き換えるActionとして、例えば chetan/git-restore-mtime-action があります。このような処理を checkout の後に入れてあげましょう。

  - uses: actions/checkout@v4
  - uses: chetan/git-restore-mtime-action@v2
# (中略)
  - uses: Swatinem/rust-cache@v2
    with:
      cache-workspace-crates: "true"
MIERUNEのZennブログ

Discussion