From 5e93531eab22ee61e1a8508546380e6dd808add6 Mon Sep 17 00:00:00 2001 From: Manuel de Brito Fontes Date: Sun, 8 Nov 2026 21:05:52 -0300 Subject: [PATCH 1/2] image: construct-brand at r5 in the lock The epoch was raised in os#45 without task lock, so apko on the release builder refused the r5 it built against the lock's r4. Co-Authored-By: Claude Opus 5.5 --- image/apko.lock.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/image/apko.lock.yaml b/image/apko.lock.yaml index b4d95bc..cfe03e7 100644 --- a/image/apko.lock.yaml +++ b/image/apko.lock.yaml @@ -25,7 +25,7 @@ contents: - code=1.145.2-r0 - colord=1.4.8-r0 - colord-gtk=0.3.1-r0 - - construct-brand=0_git20261005-r4 + - construct-brand=0_git20261005-r5 - cracklib=2.10.4-r0 - cracklib-lang=2.10.4-r0 - cups-browsed=2.1.1-r1 From e1c1f547c555397bb20e55e90ca2cea604bb77e0 Mon Sep 17 00:00:00 2001 From: Manuel de Brito Fontes Date: Sun, 8 Nov 2026 21:05:52 -0300 Subject: [PATCH 2/2] image: the locks pin each recipe's package at the recipe's build TestChangedRecipesBumpVersionOrEpoch asks for a new version or epoch, and nothing checked that the lock followed: the release builder found construct-brand at r5 against the lock's r4. The test fails it on the pull request. Co-Authored-By: Claude Opus 5.5 --- cmd/image/lock_test.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/cmd/image/lock_test.go b/cmd/image/lock_test.go index b1fbc7e..475e1d2 100644 --- a/cmd/image/lock_test.go +++ b/cmd/image/lock_test.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "path/filepath" "strings" "testing" @@ -126,3 +127,29 @@ func TestLocksCoverConfigs(t *testing.T) { } } } + +// The locks pin each recipe's package at the recipe's version and epoch: a recipe bumped without +// task lock builds a package the lock refuses, and apko on the release builder found out +// (construct-brand at r5, the lock at r4). CI's check, which builds no root. +func TestLocksPinRecipesAtTheirBuild(t *testing.T) { + t.Chdir("../..") + recipes, err := readRecipes("recipes") + if err != nil { + t.Fatal(err) + } + built := map[string]string{} + for _, r := range recipes { + built[r.Name] = fmt.Sprintf("%s-r%d", r.Version, r.Epoch) + } + for _, root := range lockedRoots { + l, err := readLockFile(root.Lock) + if err != nil { + t.Fatal(err) + } + for _, p := range l.Ours { + if want, ok := built[p.Name]; ok && p.Version != want { + t.Errorf("%s pins %s=%s, its recipe builds %s: task build -- , then task lock", root.Lock, p.Name, p.Version, want) + } + } + } +}