diff --git a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder-tools/build_test.go b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder-tools/build_test.go index f18c8ad0..071a5ea4 100644 --- a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder-tools/build_test.go +++ b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder-tools/build_test.go @@ -2,9 +2,12 @@ package main import ( "encoding/json" + "errors" "strings" "testing" + "mesh-delivery-builder/internal/build" + "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient" "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog" ) @@ -30,3 +33,24 @@ func TestNewestIsReadFromTheCatalogHalfOfEachWatchedBranch(t *testing.T) { t.Fatalf("newest = %v, %v, want each branch's entry fingerprint whole", got, err) } } + +// A build seat's steps are read in its holder's state, the holder found where it is read (design 47 G A-128); a seat with no +// holder found reads as an error. +func TestABuildSeatsStepsAreReadInItsHoldersState(t *testing.T) { + var named []string + steps := stepsOfHolder(func(seat string) (string, error) { + if seat == "node-build-go" { + return "mesh-build-go", nil + } + return "", errors.New("no holder") + }, func(name string) build.StateRead { + named = append(named, name) + return build.StateRead{Keys: func() ([]string, error) { return []string{"k"}, nil }} + }) + if ks, err := steps("node-build-go").Keys(); err != nil || len(ks) != 1 || len(named) != 1 || named[0] != "mesh-build-go.steps" { + t.Errorf("read %v (keys %v, %v); want the holder's mesh-build-go.steps", named, ks, err) + } + if _, err := steps("node-build-node").Keys(); err == nil || !strings.Contains(err.Error(), "node-build-node") { + t.Errorf("a seat with no holder reads %v; want an error naming it", err) + } +} diff --git a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder-tools/main.go b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder-tools/main.go index 2ba23cde..4f5603ab 100644 --- a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder-tools/main.go +++ b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder-tools/main.go @@ -293,6 +293,22 @@ func askKept(s stdio.KeptState, state, bucket, what string, bound time.Duration, } } +// stepsOfHolder reads a build seat's steps in the state of the seat's holder (`.steps`), the holder found where it is +// read by mesh-sdk's seatlist helper (design 47 G A-128, A-126), as the manifest's `seat:.steps` reads name it; a seat +// whose holder cannot be found reads as an error naming it. +func stepsOfHolder(holder func(seat string) (string, error), read func(name string) build.StateRead) func(seat string) build.StateRead { + return func(seat string) build.StateRead { + module, err := holder(seat) + if err != nil { + fail := fmt.Errorf("the holder of %s is not found: %w", seat, err) + return build.StateRead{Keys: func() ([]string, error) { return nil, fail }, + Get: func(string) (json.RawMessage, time.Time, error) { return nil, time.Time{}, fail }, + Written: func(string) time.Time { return time.Time{} }} + } + return read(module + ".steps") + } +} + func read(s stdio.KeptState) build.StateRead { return build.StateRead{Keys: s.Keys, Get: func(key string) (json.RawMessage, time.Time, error) { e, err := s.Get(key) @@ -331,7 +347,7 @@ const ( func main() { reasks := stdio.State(build.ReAsksState) - r := build.StuckReader{Logf: func(f string, a ...any) { fmt.Fprintf(os.Stderr, "[mesh-delivery-builder-tools] "+f+"\n", a...) }, Builds: read(stdio.State("builds")), ReAsks: read(reasks), StepsOf: func(seat string) build.StateRead { return read(stdio.State(seat + ".steps")) }, + r := build.StuckReader{Logf: func(f string, a ...any) { fmt.Fprintf(os.Stderr, "[mesh-delivery-builder-tools] "+f+"\n", a...) }, Builds: read(stdio.State("builds")), ReAsks: read(reasks), StepsOf: stepsOfHolder(func(seat string) (string, error) { return seatlist.HolderOf(stdio.Ask, seat) }, func(name string) build.StateRead { return read(stdio.State(name)) }), Hearing: read(stdio.State(buildrun.HearingState))} put := func(key string, value []byte) error { _, err := reasks.Put(key, json.RawMessage(value)) diff --git a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/names_test.go b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/names_test.go index 5447f9bc..7e51d0a6 100644 --- a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/names_test.go +++ b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/names_test.go @@ -26,7 +26,7 @@ func TestTheNamesAreTheManifests(t *testing.T) { t.Fatal(err) } for _, read := range []string{ - "node-build-go.steps", "node-build-image.steps", "node-build-node.steps", + "seat:node-build-go.steps", "seat:node-build-image.steps", "seat:node-build-node.steps", } { if !slices.Contains(m.Reads, read) { t.Errorf("the builder reads %s, its manifest's reads are %v", read, m.Reads) diff --git a/modules/mesh-delivery-builder/manifest_test.go b/modules/mesh-delivery-builder/manifest_test.go index 1311e4e5..f7498cb2 100644 --- a/modules/mesh-delivery-builder/manifest_test.go +++ b/modules/mesh-delivery-builder/manifest_test.go @@ -119,8 +119,9 @@ func TestManifestDeclarations(t *testing.T) { // 1607/AC1 // 1887/A4c: the builder chooses no node, so it reads neither presence nor have, invokes no build module's tool and // holds no capacity; it puts asks on the three build seats and reads their steps (ADR 0525 §1, §4, §5). Whether a // node's machine is heard it asks the watchdogs seat's presence (issue 1966, ADR 0596 §2, ADR 0668 §3). - if want := []string{"node-build-go.steps", "node-build-image.steps", "node-build-node.steps", - "seat:mesh-module-assigner.assignments"}; !reflect.DeepEqual(sorted(m.Reads), want) { + // Each build seat's steps are read in seat form, its holder found where it is read (A-116, A-128). + if want := []string{"seat:mesh-module-assigner.assignments", "seat:node-build-go.steps", "seat:node-build-image.steps", + "seat:node-build-node.steps"}; !reflect.DeepEqual(sorted(m.Reads), want) { t.Errorf("reads = %v, want %v", m.Reads, want) } if want := []string{"node-build-go", "node-build-image", "node-build-node", "operator-channel"}; !reflect.DeepEqual(sorted(m.Uses), want) { diff --git a/modules/mesh-delivery-builder/module.json b/modules/mesh-delivery-builder/module.json index 74a51154..a60b5e69 100644 --- a/modules/mesh-delivery-builder/module.json +++ b/modules/mesh-delivery-builder/module.json @@ -155,10 +155,10 @@ { "name": "build-log", "max-age-days": 30, "max-mib": 3072 } ], "reads": [ - "node-build-go.steps", - "node-build-image.steps", - "node-build-node.steps", - "seat:mesh-module-assigner.assignments" + "seat:mesh-module-assigner.assignments", + "seat:node-build-go.steps", + "seat:node-build-image.steps", + "seat:node-build-node.steps" ], "uses": [ "node-build-go",