v0.351.0 (unreleased): old -rc controller images and old infra images are deleted (decision 56 amended, decision 285)
gates / gates (push) Successful in 31s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-11-09 10:23:06 +01:00
1 parent 64b99b74e3
commit 27360d6abe
10 files changed
+471 -31

No files matched your search

@@ -48,16 +48,17 @@ func TestControllerRetention_KeepsRunningAndPreviousDeletesOlder(t *testing.T) {
if strings.Contains(s, ":0.284.2,") {
t.Fatalf("the previous controller (0.284.2) was deleted: %v", f.rmi)
}
for _, want := range []string{ctlRepo + ":0.284.1", ctlRepo + ":0.283.1", "sha256:CNONE"} {
// 0.273.0-rc1: a test build below the previous goes like an old release (decision 56 amended 2026-11-09).
for _, want := range []string{ctlRepo + ":0.284.1", ctlRepo + ":0.283.1", "sha256:CNONE", ctlRepo + ":0.273.0-rc1"} {
if !strings.Contains(s, ","+want+",") {
t.Fatalf("%s (older than the previous / untagged) was not deleted: rmi=%v", want, f.rmi)
}
}
if strings.Contains(s, "0.273.0-rc1") || strings.Contains(s, "acme/web") || strings.Contains(s, "W3") {
t.Fatalf("a non-version tag or another repository's image was touched: %v", f.rmi)
if strings.Contains(s, "acme/web") || strings.Contains(s, "W3") {
t.Fatalf("another repository's image was touched: %v", f.rmi)
}
if len(got) != 3 {
t.Fatalf("deleted %d, want 3: %v", len(got), got)
if len(got) != 4 {
t.Fatalf("deleted %d, want 4: %v", len(got), got)
}
}
@@ -183,3 +184,67 @@ func TestRetainImagesAfterUpdate_AppGoneDoesNotPanic(t *testing.T) {
t.Fatalf("deleted images for an app that is gone: %v", f.rmi)
}
}
// Decision 56 amended 2026-11-09: demo-hp's guest held 25 old test builds (X.Y.Z-rc.N, 2.2 GB) because every -rc tag was
// "left alone". A test build is now a version (util.ParseVersionPre: below its release): an old one goes; a test build
// ABOVE the running one (a pulled target) and one BETWEEN the previous and the running one stay; `latest` stays.
// COMPANION RED-PROOF: parse tags with util.ParseVersion again → "an old test build (0.330.0-rc.2) was not deleted".
func TestControllerRetention_OldTestBuildsGo(t *testing.T) {
m := retentionManager(t)
f := &fakeImages{
imgs: []localImage{
{ID: "sha256:R350", Repo: ctlRepo, Tag: "0.350.0", Size: "348MB"},
{ID: "sha256:R349", Repo: ctlRepo, Tag: "0.349.0", Size: "348MB"},
{ID: "sha256:RC350", Repo: ctlRepo, Tag: "0.350.0-rc.3", Size: "348MB"},
{ID: "sha256:RC330", Repo: ctlRepo, Tag: "0.330.0-rc.2", Size: "347MB"},
{ID: "sha256:RC351", Repo: ctlRepo, Tag: "0.351.0-rc.1", Size: "348MB"},
{ID: "sha256:LATEST", Repo: ctlRepo, Tag: "latest", Size: "348MB"},
},
containers: map[string]string{"c-ctl": "sha256:R350"},
}
withFakeImages(t, f)
// No swap record: the previous by version order is the RELEASE 0.349.0, not the newer test build 0.350.0-rc.3.
if _, err := m.RetainControllerImages(ControllerImageRecord{Repo: ctlRepo, Running: "0.350.0"}); err != nil {
t.Fatal(err)
}
s := rmiSet(f)
if !strings.Contains(s, ","+ctlRepo+":0.330.0-rc.2,") {
t.Fatalf("an old test build (0.330.0-rc.2) was not deleted: %v", f.rmi)
}
if strings.Contains(s, ":0.349.0,") {
t.Fatalf("the previous RELEASE (0.349.0) was deleted — version order must prefer a release over a test build: %v", f.rmi)
}
if strings.Contains(s, ":0.351.0-rc.1,") || strings.Contains(s, ":latest,") || strings.Contains(s, ":0.350.0,") {
t.Fatalf("a newer test build, latest, or the running one was deleted: %v", f.rmi)
}
// 0.350.0-rc.3 sits between the previous (0.349.0) and the running one: kept, like a release there would be.
if strings.Contains(s, ":0.350.0-rc.3,") {
t.Fatalf("a test build between the previous and the running one was deleted: %v", f.rmi)
}
}
// A box that RUNS a test build (Tester 1 during an rc round) is judged too — it was skipped before.
// COMPANION RED-PROOF: parse rec.Running with util.ParseVersion again → "a box running a test build deleted nothing".
func TestControllerRetention_BoxOnATestBuildIsJudged(t *testing.T) {
m := retentionManager(t)
f := &fakeImages{
imgs: []localImage{
{ID: "sha256:RC2", Repo: ctlRepo, Tag: "0.351.0-rc.2", Size: "348MB"},
{ID: "sha256:RC1", Repo: ctlRepo, Tag: "0.351.0-rc.1", Size: "348MB"},
{ID: "sha256:R350", Repo: ctlRepo, Tag: "0.350.0", Size: "348MB"},
{ID: "sha256:R349", Repo: ctlRepo, Tag: "0.349.0", Size: "348MB"},
},
containers: map[string]string{"c-ctl": "sha256:RC2"},
}
withFakeImages(t, f)
if _, err := m.RetainControllerImages(ControllerImageRecord{Repo: ctlRepo, Running: "0.351.0-rc.2", Previous: ctlRepo + ":0.350.0"}); err != nil {
t.Fatal(err)
}
s := rmiSet(f)
if !strings.Contains(s, ","+ctlRepo+":0.349.0,") {
t.Fatalf("a box running a test build deleted nothing: %v", f.rmi)
}
if strings.Contains(s, ":0.350.0,") || strings.Contains(s, ":0.351.0-rc.2,") || strings.Contains(s, ":0.351.0-rc.1,") {
t.Fatalf("the recorded previous, the running test build or one between them was deleted: %v", f.rmi)
}
}