Keep the shared caches unchanged by a candidate's step, under a throwaway writable layer (issue 1309, S18, ADR 0448)

A trunk build alone writes them; any other step writes into an overlay that dies with it.
This commit is contained in:
2026-10-22 17:45:35 +02:00
parent 39a2144cd6
commit 1f4ff20488
2 changed files with 38 additions and 3 deletions
+8 -3
View File
@@ -132,13 +132,18 @@ func (iso Isolation) command(env []string, name string, args ...string) ([]strin
return append(argv, args...), nil
}
// cacheArgs binds the shared caches: read-write for a trunk build, otherwise read-only (S18).
// cacheArgs binds the shared warm caches (S18): for a trunk build read-write, so the next build is warm; for any other
// read-only beneath an overlay whose writes go to a tmpfs of the step's own, so the step writes as a build does and
// nothing it wrote outlives it (bubblewrap's --tmp-overlay, an overlay mount in the step's user namespace).
func cacheArgs(caches []string, write bool) []string {
var argv []string
for _, c := range caches {
argv = append(argv, "--ro-bind", c, c)
if write {
argv = append(argv, "--bind", c, c)
continue
}
argv = append(argv, "--overlay-src", c, "--tmp-overlay", c)
}
_ = write
return argv
}
+30
View File
@@ -0,0 +1,30 @@
package buildstep
import "testing"
// The shared warm caches are read under a throwaway writable layer (novox/hq ADR 0448; issue 1309): a candidate's step
// writes into them as a build does, and nothing it writes outlives it or reaches a later build; only a trunk build
// writes them.
func TestACandidatesStepWritesTheCachesOnlyIntoAThrowawayLayer(t *testing.T) {
fixedSystem(t)
iso := Isolation{Workspace: "/w", Caches: []string{"/var/cache/go-build", "/var/cache/npm"}}
argv, err := iso.Command("go", "test")
if err != nil {
t.Fatal(err)
}
for _, c := range iso.Caches {
if !holds(argv, "--overlay-src", c, "--tmp-overlay", c) {
t.Errorf("the cache %s is not under a throwaway layer: %v", c, argv)
}
if holds(argv, "--bind", c, c) {
t.Errorf("a candidate's step writes the cache %s: %v", c, argv)
}
}
iso.WriteCaches = true
argv, _ = iso.Command("go", "build")
for _, c := range iso.Caches {
if !holds(argv, "--bind", c, c) || holds(argv, "--tmp-overlay", c) {
t.Errorf("a trunk build does not write the cache %s: %v", c, argv)
}
}
}