Compare commits

..
2 Commits
Author SHA1 Message Date
jschoubben 0fbc4ce6f8 Fold the composer key's versions test into the existing key test: mesh-sdk is over its test budget (issue 1921)
mesh/delivery ready: it is merged on the Approve
mesh/check pass 0fbc4ce6f816 on 5a38a1221659 | unit 6446 run, 187 kept, 14 skipped | integration 6580 run, 220 kept, 23 skipped | over bound: unit, in…
mesh/delivery-group group fix/1921-zero-version-builds ready: every member ready, and composed together they pass
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-06 01:59:46 +01:00
jschoubben db4eff3885 A composer's cache key covers the mesh package versions its ask names (issue 1921)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-06 01:51:16 +01:00
2 changed files with 32 additions and 9 deletions
+13 -3
View File
@@ -310,9 +310,19 @@ type ComposeAnswer struct {
// ComposerKey is the key a build module keeps a built composer under: the repository, commit, directory and package it // ComposerKey is the key a build module keeps a built composer under: the repository, commit, directory and package it
// was built from and the toolchain it was built with, hashed (`composer-` and 16 hex digits), so each head is built once // was built from and the toolchain it was built with, hashed (`composer-` and 16 hex digits), so each head is built once
// on a node (ADR 0482 clause 4). // on a node (ADR 0482 clause 4). The mesh package versions the ask names are an input of the build, so they are in the
func ComposerKey(repository, commit, dir, pkg string, toolchain ToolchainUsed) string { // key, sorted, when there are any; an ask that names none gets the key it always had (issue 1921).
sum := sha256.Sum256([]byte(strings.Join([]string{repository, commit, dir, pkg, toolchain.Version, toolchain.Recipe}, "\n"))) func ComposerKey(repository, commit, dir, pkg string, toolchain ToolchainUsed, versions PackageVersions) string {
parts := []string{repository, commit, dir, pkg, toolchain.Version, toolchain.Recipe}
pkgs := make([]string, 0, len(versions))
for p := range versions {
pkgs = append(pkgs, p)
}
sort.Strings(pkgs)
for _, p := range pkgs {
parts = append(parts, p+"="+versions[p])
}
sum := sha256.Sum256([]byte(strings.Join(parts, "\n")))
return "composer-" + hex.EncodeToString(sum[:8]) return "composer-" + hex.EncodeToString(sum[:8])
} }
+19 -6
View File
@@ -56,21 +56,34 @@ func TestAComposeAskIsRefusedWhereItDoesNotBelong(t *testing.T) {
} }
} }
// 1622/AC3: a composer is kept under one key per repository, commit, directory, package and toolchain, so two asks of // 1622/AC3, 1921: a composer is kept under one key per repository, commit, directory, package, toolchain and asked versions, so two asks of
// one head build it once on a node, and another head or toolchain builds its own. // one head build it once on a node, and another head or toolchain builds its own.
func TestAComposerIsKeptByWhatItWasBuiltFrom(t *testing.T) { func TestAComposerIsKeptByWhatItWasBuiltFrom(t *testing.T) {
tc := ToolchainUsed{Version: "go1.26.0", Recipe: "3"} tc := ToolchainUsed{Version: "go1.26.0", Recipe: "3"}
k := ComposerKey("novox/mesh-sdk", askCommit, "go", "p", tc) k := ComposerKey("novox/mesh-sdk", askCommit, "go", "p", tc, nil)
if k != ComposerKey("novox/mesh-sdk", askCommit, "go", "p", tc) || !strings.HasPrefix(k, "composer-") || len(k) != len("composer-")+16 { if k != ComposerKey("novox/mesh-sdk", askCommit, "go", "p", tc, nil) || !strings.HasPrefix(k, "composer-") || len(k) != len("composer-")+16 {
t.Fatalf("key = %q", k) t.Fatalf("key = %q", k)
} }
for _, other := range []string{ for _, other := range []string{
ComposerKey("novox/mesh-sdk", strings.Repeat("1", 40), "go", "p", tc), ComposerKey("novox/mesh-sdk", strings.Repeat("1", 40), "go", "p", tc, nil),
ComposerKey("novox/mesh-controller", askCommit, ".", "p", tc), ComposerKey("novox/mesh-controller", askCommit, ".", "p", tc, nil),
ComposerKey("novox/mesh-sdk", askCommit, "go", "p", ToolchainUsed{Version: "go1.26.1", Recipe: "3"}), ComposerKey("novox/mesh-sdk", askCommit, "go", "p", ToolchainUsed{Version: "go1.26.1", Recipe: "3"}, nil),
ComposerKey("novox/mesh-sdk", askCommit, "go", "p", tc, PackageVersions{"git.novox.be/novox/mesh-sdk/go": strings.Repeat("2", 40)}),
} { } {
if other == k { if other == k {
t.Errorf("two composers built from different inputs share the key %s", k) t.Errorf("two composers built from different inputs share the key %s", k)
} }
} }
// 1921: the asked versions are in the key, in any order of naming; none, or an empty ask, gives the key without them.
a, b := strings.Repeat("a", 40), strings.Repeat("b", 40)
k1 := ComposerKey("r", askCommit, "go", "p", tc, PackageVersions{"m/x": a, "m/y": b})
if k1 != ComposerKey("r", askCommit, "go", "p", tc, PackageVersions{"m/y": b, "m/x": a}) {
t.Error("the key depends on the order of the versions")
}
if k1 == ComposerKey("r", askCommit, "go", "p", tc, PackageVersions{"m/x": b, "m/y": a}) || k1 == ComposerKey("r", askCommit, "go", "p", tc, nil) {
t.Error("other versions, or none, share the key")
}
if ComposerKey("r", askCommit, "go", "p", tc, nil) != ComposerKey("r", askCommit, "go", "p", tc, PackageVersions{}) {
t.Error("an empty ask changed the key")
}
} }