Bazel Remote Cacheはpackage binary cacheと同じ問題をaction粒度で扱う
binary package cacheの考え方はpackage managerだけに存在するわけではない。Bazel Remote Cacheは、buildをactionという細粒度へ分解し、action identityからbuild resultを再利用する。この構造はNix等のbuild-result substitutionを理解する比較対象になる。
Nixのsubstituteは「バイナリパッケージ」よりbuild resultに近い のNixではderivation output/store objectをsubstituteするが、Bazelではbuild graph中の個々のaction outputをcacheする。
Bazelのactionにはinputs、expected output names、command line、environment variablesが宣言される。Remote Cacheには大きく二種類のdataが置かれる。
- Action Cache (AC): action hashからActionResult metadataへのmapping
- Content-Addressable Store (CAS): input/output file等のcontentをdigestで保存するstore
build時にはBazelが必要なactionを計算し、local output、remote Action Cacheの順に既存resultを探す。hitすればCASからoutputを取得し、missすればactionを実行してresultをcacheへuploadする。
この構造は「artifact identity」と「build identity」を分離している点が興味深い。CAS keyはcontent digestであり、content addressingはprovenanceではない のwhat-bytes identityを持つ。一方AC keyは「このaction inputs/command等に対応するresultはどのCAS objectか」というbuild-result mappingを表す。
概念的には、
action identity -> result metadata -> content-addressed outputs
という二段階になる。
これはNixのstore pathは通常content-addressedではないで見たNixの問題とも似ている。build inputからoutputをlookupしたいが、actual output bytesのidentityはcontent digestでも表せる。package managerとbuild systemでは粒度やsemanticsが違うものの、input-keyed computation cache + CASという一般構造が共通している。
ただしcache reuseが安全に成立するにはactionがhermetic/reproducibleである必要がある。Bazel公式documentationもremote cacheについて、buildがreproducibleなら別machineのoutputを安全にreuseできるとしている。undeclared input、host-specific environment、time/randomness等がaction resultへ影響すると、同じaction keyに対して期待しないoutputが作られる危険がある。
これはlockfileで依存を固定してもreproducible buildにはならないのpackage単位の問題を、action単位へ縮小したものと考えられる。
またremote cache poisoningはbinary cacheの公開鍵を追加することはbuilderを信頼することに近いと似たsecurity issueになる。write accessを持つ主体が誤ったresultをaction keyへ対応付ければ、他のdeveloper/CIがそのresultをreuseし得る。content hashがoutput bytesの改変を検出できても、「そのcontentがそのactionの正当なresultか」というmappingのtrustは別に残る。
この比較から、Nix/Spack/Bazel等を単なるpackage manager/build toolという製品分類だけで分けず、次の共通primitiveで見ることができる。
- computation/build identity
- result lookup
- content-addressed blob storage
- dependency/output graph
- cache trust policy
- miss時のexecution
binary package cacheは、remote build cacheより大きなartifact粒度とdistribution semanticsを加えたものとして連続的に捉えられる。