buildstep: keep what one command of an ask writes into the caches for its later commands

Every command of a check ran over the shared Go build cache beneath a throwaway
tmpfs layer of its own, so the digests, the vet, the unit tests and the integration
compile of one ask each compiled every package again. With Isolation.CacheLayer a
command writes into a layer on disk of its own and Isolated moves it into the ask's
kept layer when it ends; later commands read the kept layer above the shared cache,
which stays unchanged (ADR 0541 §2, ADR 0448 §3). Empty CacheLayer keeps today's
throwaway layer. Ported from feat/try-speed S2 (issue 1921).
This commit is contained in:
2026-10-29 00:51:26 +01:00
parent d4c61ee8ff
commit 2a86701891
4 changed files with 222 additions and 11 deletions
+19
View File
@@ -63,4 +63,23 @@ func TestARunStepReachesNothingAndLeavesTheCachesUnchanged(t *testing.T) {
if b, err := os.ReadFile(filepath.Join(workspace, "out")); r.Status != 0 || err != nil || string(b) != "built\n" {
t.Fatalf("the step's write to its workspace did not stay (status %d, %s%s): %q %v", r.Status, r.Stderr, r.Err, b, err)
}
// 1921/S2: with the ask's cache layer, what one command writes into the cache the next command of the ask reads,
// above what the shared cache holds, and the shared cache stays unchanged.
asked := Isolated(forgekey.ExecRunnerFor(0), Isolation{Workspace: workspace, Caches: []string{cacheDir},
CacheLayer: filepath.Join(workspace, "cachelayer")})
r = asked(context.Background(), []string{"PATH=/usr/bin:/bin"}, "/bin/sh", "-c", "cat "+filepath.Join(cacheDir, "warm")+" && mkdir -p "+filepath.Join(cacheDir, "ab")+" && echo compiled > "+filepath.Join(cacheDir, "ab", "one-d"))
if r.Status != 0 || r.Err != "" || strings.TrimSpace(r.Stdout) != "warm" {
t.Fatalf("the first command of the ask did not read the shared cache and write its own (status %d, %s): %s%s", r.Status, r.Err, r.Stdout, r.Stderr)
}
r = asked(context.Background(), []string{"PATH=/usr/bin:/bin"}, "/bin/cat", filepath.Join(cacheDir, "ab", "one-d"), filepath.Join(cacheDir, "warm"))
if r.Status != 0 || r.Err != "" || r.Stdout != "compiled\nwarm\n" {
t.Fatalf("the next command of the ask did not find what the first wrote (status %d, %s): %q %s", r.Status, r.Err, r.Stdout, r.Stderr)
}
if _, err := os.Stat(filepath.Join(cacheDir, "ab")); !os.IsNotExist(err) {
t.Fatalf("the ask's commands wrote the shared cache: %v", err)
}
if err := os.RemoveAll(filepath.Join(workspace, "cachelayer")); err != nil {
t.Fatalf("the ask's cache layer cannot be removed with its workspace: %v", err)
}
}