From 3d42988afa7db00ece5c4070fd4a911e004db88c Mon Sep 17 00:00:00 2001 From: jochen Date: Tue, 27 Oct 2026 01:22:13 +0100 Subject: [PATCH] Hold every build module to ending what a previous process left running (issue 1890) A replaced mesh-build-go left a check ask's step running and its start sweep spared it (issue 1890, note 21). mesh-build-go, mesh-build-node and mesh-build-image pin mesh-sdk 981a35b5, whose steps name their owner and whose sweep ends another owner's at once; each runs the sweep through one method that main calls and that its test runs through the conformance kit's left-running case. The failurekit check now refuses a build module whose tests do not run that case, test step or not. --- checks/failurekit/failurekit.go | 29 ++++++++++++++----- checks/failurekit/failurekit_test.go | 17 +++++++---- .../mesh-build-go/cmd/mesh-build-go/asks.go | 8 +++++ .../cmd/mesh-build-go/kit_test.go | 11 +++++++ .../mesh-build-go/cmd/mesh-build-go/main.go | 6 ++-- modules/mesh-build-go/go.mod | 2 +- modules/mesh-build-go/go.sum | 4 +-- .../cmd/mesh-build-image/asks.go | 8 +++++ .../cmd/mesh-build-image/capture_test.go | 3 ++ .../cmd/mesh-build-image/kit_test.go | 19 ++++++++++++ .../cmd/mesh-build-image/main.go | 6 ++-- .../testdata/captured/build-candidate.json | 1 + .../testdata/captured/build-trunk.json | 1 + .../testdata/captured/fetch.json | 1 + modules/mesh-build-image/go.mod | 2 +- modules/mesh-build-image/go.sum | 4 +-- .../cmd/mesh-build-node/asks.go | 8 +++++ .../cmd/mesh-build-node/kit_test.go | 11 +++++++ .../cmd/mesh-build-node/main.go | 6 ++-- modules/mesh-build-node/go.mod | 2 +- modules/mesh-build-node/go.sum | 4 +-- 21 files changed, 122 insertions(+), 31 deletions(-) create mode 100644 modules/mesh-build-image/cmd/mesh-build-image/kit_test.go diff --git a/checks/failurekit/failurekit.go b/checks/failurekit/failurekit.go index 72e1ed25..d95afa6a 100644 --- a/checks/failurekit/failurekit.go +++ b/checks/failurekit/failurekit.go @@ -2,7 +2,9 @@ // fix): a module that claims a node-build-* seat and serves a test step must hold a test that calls conformance.Run, so // its parse of the test runner's output is held to the failure contract (a failing test named with its cause, never a // passing line in its place). A build module with no test step (mesh-build-image builds images and runs no tests) is -// exempt, and said so. +// exempt from that, and said so. Every build module, test step or not, must also hold a test that calls +// conformance.LeftRunning with its own start sweep, so a step a previous process left running is ended at its start +// (issue 1890). package failurekit import ( @@ -57,20 +59,31 @@ func Judge(root string) ([]Judged, error) { } dir := filepath.Dir(p) j := Judged{Module: filepath.Base(dir)} + var refused []string test := testTool(m.Tools) switch { case test == "": - j.Exempt = fmt.Sprintf("it claims %s and serves no test step", seat) + j.Exempt = fmt.Sprintf("it claims %s and serves no test step, so the failure contract's cases do not apply", seat) default: - runs, err := runsTheKit(dir) + runs, err := runsTheKit(dir, "conformance.Run(") if err != nil { return nil, err } if !runs { - j.Refused = fmt.Sprintf("it claims %s and serves the test step %s, and no test of it calls conformance.Run "+ - "(mesh-sdk go/buildstep/conformance): run the kit with the module's own parse path (issue 1901)", seat, test) + refused = append(refused, fmt.Sprintf("it claims %s and serves the test step %s, and no test of it calls conformance.Run "+ + "(mesh-sdk go/buildstep/conformance): run the kit with the module's own parse path (issue 1901)", seat, test)) } } + // Every build module keeps steps, so every one runs the left-running case, test step or not (issue 1890). + sweeps, err := runsTheKit(dir, "conformance.LeftRunning(") + if err != nil { + return nil, err + } + if !sweeps { + refused = append(refused, fmt.Sprintf("it claims %s, and no test of it calls conformance.LeftRunning "+ + "(mesh-sdk go/buildstep/conformance): run the kit's left-running case with the module's own start sweep (issue 1890)", seat)) + } + j.Refused = strings.Join(refused, "; ") out = append(out, j) } return out, nil @@ -96,8 +109,8 @@ func testTool(tools []json.RawMessage) string { return "" } -// runsTheKit says a _test.go file under dir calls conformance.Run. -func runsTheKit(dir string) (bool, error) { +// runsTheKit says a _test.go file under dir calls the kit's function call (such as "conformance.Run("). +func runsTheKit(dir, call string) (bool, error) { found := false err := filepath.WalkDir(dir, func(p string, d fs.DirEntry, err error) error { if err != nil || found || d.IsDir() || !strings.HasSuffix(p, "_test.go") { @@ -107,7 +120,7 @@ func runsTheKit(dir string) (bool, error) { if err != nil { return err } - found = strings.Contains(string(raw), "conformance.Run(") && + found = strings.Contains(string(raw), call) && strings.Contains(string(raw), `"git.novox.be/novox/mesh-sdk/go/buildstep/conformance"`) return nil }) diff --git a/checks/failurekit/failurekit_test.go b/checks/failurekit/failurekit_test.go index 2b2e9d92..f08ecf7b 100644 --- a/checks/failurekit/failurekit_test.go +++ b/checks/failurekit/failurekit_test.go @@ -6,17 +6,24 @@ import ( "testing" ) -// 1901/AC7: a build module with a test step and no kit is refused, one that runs the kit passes, one with no test step is -// exempt, and a module that claims no node-build-* seat is not judged. +// 1901/AC7 and 1890/AC8: a build module with a test step and no kit is refused, one that runs the kit passes, one with no +// test step is exempt from the failure cases but not from the left-running case, a module that runs only the failure +// cases is refused, and a module that claims no node-build-* seat is not judged. func TestABuildModuleWithATestStepMustRunTheKit(t *testing.T) { root := t.TempDir() - kit := "package main\n\nimport \"git.novox.be/novox/mesh-sdk/go/buildstep/conformance\"\n\nfunc TestKit(t *testing.T) { conformance.Run(t, conformance.GoTest, nil) }\n" + const imp = "package main\n\nimport \"git.novox.be/novox/mesh-sdk/go/buildstep/conformance\"\n\n" + const sweep = "func TestSweep(t *testing.T) { conformance.LeftRunning(t, nil) }\n" + kit := imp + "func TestKit(t *testing.T) { conformance.Run(t, conformance.GoTest, nil) }\n" + sweep for path, body := range map[string]string{ "modules/a/module.json": `{"claims":[{"name":"node-build-a"}],"tools":["build_a_fetch","build_a_test"]}`, "modules/a/cmd/a/check_test.go": "package main\n", "modules/b/module.json": `{"claims":[{"name":"node-build-b"}],"tools":[{"name":"build_b_test"}]}`, "modules/b/cmd/b/kit_test.go": kit, "modules/c/module.json": `{"claims":[{"name":"node-build-c"}],"tools":["build_c_build"]}`, + "modules/c/cmd/c/kit_test.go": imp + sweep, + "modules/f/module.json": `{"claims":[{"name":"node-build-f"}],"tools":["build_f_build"]}`, + "modules/g/module.json": `{"claims":[{"name":"node-build-g"}],"tools":["build_g_test"]}`, + "modules/g/cmd/g/kit_test.go": imp + "func TestKit(t *testing.T) { conformance.Run(t, conformance.GoTest, nil) }\n", "modules/d/module.json": `{"claims":[{"name":"other"}],"tools":["d_test"]}`, "modules/e/module.json": `{"claims":[{"name":"node-build-e"}],"tools":["build_e_test"]}`, "modules/e/cmd/e/kit.go": kit, // not a test file @@ -33,9 +40,9 @@ func TestABuildModuleWithATestStepMustRunTheKit(t *testing.T) { if err != nil { t.Fatal(err) } - want := map[string]string{"a": "refused", "b": "passes", "c": "exempt", "e": "refused"} + want := map[string]string{"a": "refused", "b": "passes", "c": "exempt", "e": "refused", "f": "refused", "g": "refused"} if len(got) != len(want) { - t.Fatalf("judged %+v, want a, b, c and e", got) + t.Fatalf("judged %+v, want a, b, c, e, f and g", got) } for _, j := range got { is := "passes" diff --git a/modules/mesh-build-go/cmd/mesh-build-go/asks.go b/modules/mesh-build-go/cmd/mesh-build-go/asks.go index 816793b2..eb95b65f 100644 --- a/modules/mesh-build-go/cmd/mesh-build-go/asks.go +++ b/modules/mesh-build-go/cmd/mesh-build-go/asks.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "time" stdio "git.novox.be/novox/mesh-sdk/go" "git.novox.be/novox/mesh-sdk/go/buildstep" @@ -128,6 +129,13 @@ func (m *Module) SeatTools(p *buildstep.Puller) []stdio.Tool { // StepEndTool ends one step left running (issue 1890); the module's steps state is the one it reads and writes. const StepEndTool = "build_go_step_end" +// endLeftRunning is the module's start sweep (issue 1890): it ends the steps of its node that a previous process left +// running (buildstep.EndStaleAtStart; every step names its owner). main runs it once at the start, and the module's test +// runs it through the conformance kit's left-running case. +func (m *Module) endLeftRunning(ctx context.Context, scan buildstep.Scan, booted time.Time, logf func(string, ...any)) { + buildstep.EndStaleAtStart(ctx, scan, m.Node, booted, logf) +} + // stepScan is the module's steps state as buildstep reads it. func (m *Module) stepScan() buildstep.Scan { return buildstep.ScanOf(stdio.State(delivery.StepsState)) diff --git a/modules/mesh-build-go/cmd/mesh-build-go/kit_test.go b/modules/mesh-build-go/cmd/mesh-build-go/kit_test.go index 5aff31a8..357fd8b2 100644 --- a/modules/mesh-build-go/cmd/mesh-build-go/kit_test.go +++ b/modules/mesh-build-go/cmd/mesh-build-go/kit_test.go @@ -1,7 +1,9 @@ package main import ( + "context" "testing" + "time" "git.novox.be/novox/mesh-sdk/go/buildstep" "git.novox.be/novox/mesh-sdk/go/buildstep/conformance" @@ -20,3 +22,12 @@ func TestTheTestStepKeepsTheFailureContract(t *testing.T) { return res.Failed }) } + +// 1890/AC7: the module's own start sweep (endLeftRunning, as main runs it) keeps the conformance kit's left-running +// case: a step a previous process left running is ended at once and said, whatever its age, and a step of this process +// is kept. +func TestTheStartSweepEndsWhatAPreviousProcessLeft(t *testing.T) { + conformance.LeftRunning(t, func(ctx context.Context, scan buildstep.Scan, node string, before time.Time, logf func(string, ...any)) { + (&Module{Node: node}).endLeftRunning(ctx, scan, before, logf) + }) +} diff --git a/modules/mesh-build-go/cmd/mesh-build-go/main.go b/modules/mesh-build-go/cmd/mesh-build-go/main.go index 0fe82227..4e96528b 100644 --- a/modules/mesh-build-go/cmd/mesh-build-go/main.go +++ b/modules/mesh-build-go/cmd/mesh-build-go/main.go @@ -8,7 +8,6 @@ package main import ( "context" "fmt" - "git.novox.be/novox/mesh-sdk/go/buildstep" "os" "os/user" "strings" @@ -76,8 +75,9 @@ func main() { puller := m.Puller(steps, nil) m.Held = puller if m.Node != "" { - // A step a previous process left running is ended (issue 1890); this process's own steps start after booted. - go buildstep.EndStaleAtStart(ctx, m.stepScan(), m.Node, booted, logf) + // A step a previous process left running is ended (issue 1890): one that names another owner, or none and + // started before booted. + go m.endLeftRunning(ctx, m.stepScan(), booted, logf) } if m.Node != "" { // The seat's asks, pulled once Serve has the runtime's channel; a pull before it is said and tried again. diff --git a/modules/mesh-build-go/go.mod b/modules/mesh-build-go/go.mod index fa959a83..2daa28ef 100644 --- a/modules/mesh-build-go/go.mod +++ b/modules/mesh-build-go/go.mod @@ -3,7 +3,7 @@ module meshbuildgo go 1.26.0 require ( - git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026233910-a2759ec92ec9 + git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261027001929-981a35b598fd github.com/distribution/distribution/v3 v3.1.2 github.com/nats-io/nats-server/v2 v2.11.17 github.com/nats-io/nats.go v1.54.0 diff --git a/modules/mesh-build-go/go.sum b/modules/mesh-build-go/go.sum index ffedfa40..b66caaf1 100644 --- a/modules/mesh-build-go/go.sum +++ b/modules/mesh-build-go/go.sum @@ -1,5 +1,5 @@ -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026233910-a2759ec92ec9 h1:MS7i4NVNQHMAMqRRFMdzbto31BHZY+BuEZY1ql3p4Rs= -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026233910-a2759ec92ec9/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261027001929-981a35b598fd h1:B78Hm1SWIcaA089lEgVX00QRez5BntLEhs2d4Xsb1yU= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261027001929-981a35b598fd/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= github.com/alicebob/miniredis/v2 v2.35.0 h1:QwLphYqCEAo1eu1TqPRN2jgVMPBweeQcR21jeqDCONI= github.com/alicebob/miniredis/v2 v2.35.0/go.mod h1:TcL7YfarKPGDAthEtl5NBeHZfeUQj6OXMm/+iu5cLMM= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0= diff --git a/modules/mesh-build-image/cmd/mesh-build-image/asks.go b/modules/mesh-build-image/cmd/mesh-build-image/asks.go index ad9899bf..71d8644a 100644 --- a/modules/mesh-build-image/cmd/mesh-build-image/asks.go +++ b/modules/mesh-build-image/cmd/mesh-build-image/asks.go @@ -2,6 +2,7 @@ package main import ( "context" + "time" stdio "git.novox.be/novox/mesh-sdk/go" "git.novox.be/novox/mesh-sdk/go/buildstep" @@ -78,6 +79,13 @@ func (m *Module) SeatTools(p *buildstep.Puller) []stdio.Tool { // StepEndTool ends one step left running (issue 1890); the module's steps state is the one it reads and writes. const StepEndTool = "build_image_step_end" +// endLeftRunning is the module's start sweep (issue 1890): it ends the steps of its node that a previous process left +// running (buildstep.EndStaleAtStart; every step names its owner). main runs it once at the start, and the module's test +// runs it through the conformance kit's left-running case. +func (m *Module) endLeftRunning(ctx context.Context, scan buildstep.Scan, booted time.Time, logf func(string, ...any)) { + buildstep.EndStaleAtStart(ctx, scan, m.Node, booted, logf) +} + // stepScan is the module's steps state as buildstep reads it. func (m *Module) stepScan() buildstep.Scan { return buildstep.ScanOf(stdio.State(delivery.StepsState)) diff --git a/modules/mesh-build-image/cmd/mesh-build-image/capture_test.go b/modules/mesh-build-image/cmd/mesh-build-image/capture_test.go index b6f372a7..f251ca7e 100644 --- a/modules/mesh-build-image/cmd/mesh-build-image/capture_test.go +++ b/modules/mesh-build-image/cmd/mesh-build-image/capture_test.go @@ -36,6 +36,9 @@ func normalized(t *testing.T, st delivery.Step, workspace, commit, registry stri t.Fatal(err) } v["id"] = "STEPID" + if _, ok := v["owner"]; ok { + v["owner"] = "OWNER" // the process that ran it (issue 1890), differs per run + } v["started"], v["ended"] = "2026-10-22T08:00:00Z", "2026-10-22T08:00:01Z" out, _ := json.MarshalIndent(v, "", " ") s := string(out) diff --git a/modules/mesh-build-image/cmd/mesh-build-image/kit_test.go b/modules/mesh-build-image/cmd/mesh-build-image/kit_test.go new file mode 100644 index 00000000..512e45c9 --- /dev/null +++ b/modules/mesh-build-image/cmd/mesh-build-image/kit_test.go @@ -0,0 +1,19 @@ +package main + +import ( + "context" + "testing" + "time" + + "git.novox.be/novox/mesh-sdk/go/buildstep" + "git.novox.be/novox/mesh-sdk/go/buildstep/conformance" +) + +// 1890/AC7: the module's own start sweep (endLeftRunning, as main runs it) keeps the conformance kit's left-running +// case: a step a previous process left running is ended at once and said, whatever its age, and a step of this process +// is kept. +func TestTheStartSweepEndsWhatAPreviousProcessLeft(t *testing.T) { + conformance.LeftRunning(t, func(ctx context.Context, scan buildstep.Scan, node string, before time.Time, logf func(string, ...any)) { + (&Module{Node: node}).endLeftRunning(ctx, scan, before, logf) + }) +} diff --git a/modules/mesh-build-image/cmd/mesh-build-image/main.go b/modules/mesh-build-image/cmd/mesh-build-image/main.go index 525143a4..32f75e72 100644 --- a/modules/mesh-build-image/cmd/mesh-build-image/main.go +++ b/modules/mesh-build-image/cmd/mesh-build-image/main.go @@ -9,7 +9,6 @@ package main import ( "context" "fmt" - "git.novox.be/novox/mesh-sdk/go/buildstep" "os" "os/user" "strings" @@ -63,8 +62,9 @@ func main() { puller := m.Puller(steps, nil) m.Held = puller if m.Node != "" { - // A step a previous process left running is ended (issue 1890); this process's own steps start after booted. - go buildstep.EndStaleAtStart(ctx, m.stepScan(), m.Node, booted, logf) + // A step a previous process left running is ended (issue 1890): one that names another owner, or none and + // started before booted. + go m.endLeftRunning(ctx, m.stepScan(), booted, logf) } if m.Node != "" { // The seat's asks, pulled once Serve has the runtime's channel; a pull before it is said and tried again. diff --git a/modules/mesh-build-image/cmd/mesh-build-image/testdata/captured/build-candidate.json b/modules/mesh-build-image/cmd/mesh-build-image/testdata/captured/build-candidate.json index ee226619..2ebaf428 100644 --- a/modules/mesh-build-image/cmd/mesh-build-image/testdata/captured/build-candidate.json +++ b/modules/mesh-build-image/cmd/mesh-build-image/testdata/captured/build-candidate.json @@ -2,6 +2,7 @@ "ended": "2026-10-22T08:00:01Z", "id": "STEPID", "node": "ace", + "owner": "OWNER", "result": { "artifact": "server", "digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", diff --git a/modules/mesh-build-image/cmd/mesh-build-image/testdata/captured/build-trunk.json b/modules/mesh-build-image/cmd/mesh-build-image/testdata/captured/build-trunk.json index db897d3d..cc8f9592 100644 --- a/modules/mesh-build-image/cmd/mesh-build-image/testdata/captured/build-trunk.json +++ b/modules/mesh-build-image/cmd/mesh-build-image/testdata/captured/build-trunk.json @@ -2,6 +2,7 @@ "ended": "2026-10-22T08:00:01Z", "id": "STEPID", "node": "ace", + "owner": "OWNER", "result": { "artifact": "server", "digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", diff --git a/modules/mesh-build-image/cmd/mesh-build-image/testdata/captured/fetch.json b/modules/mesh-build-image/cmd/mesh-build-image/testdata/captured/fetch.json index 6f893f4e..d34737e7 100644 --- a/modules/mesh-build-image/cmd/mesh-build-image/testdata/captured/fetch.json +++ b/modules/mesh-build-image/cmd/mesh-build-image/testdata/captured/fetch.json @@ -2,6 +2,7 @@ "ended": "2026-10-22T08:00:01Z", "id": "STEPID", "node": "ace", + "owner": "OWNER", "result": { "commit": "COMMIT", "workspace": "WORKSPACE" diff --git a/modules/mesh-build-image/go.mod b/modules/mesh-build-image/go.mod index aa7efa34..e2a4de32 100644 --- a/modules/mesh-build-image/go.mod +++ b/modules/mesh-build-image/go.mod @@ -3,7 +3,7 @@ module meshbuildimage go 1.26.0 require ( - git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026202658-805b4d9a3536 + git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261027001929-981a35b598fd github.com/nats-io/nats-server/v2 v2.11.17 github.com/nats-io/nats.go v1.54.0 ) diff --git a/modules/mesh-build-image/go.sum b/modules/mesh-build-image/go.sum index c6d0c7bf..1d802bae 100644 --- a/modules/mesh-build-image/go.sum +++ b/modules/mesh-build-image/go.sum @@ -1,5 +1,5 @@ -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026202658-805b4d9a3536 h1:+SoDdDXF7Tgj38WP4kRpUSps6DJVl6P+w5u/KfdtwnQ= -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026202658-805b4d9a3536/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261027001929-981a35b598fd h1:B78Hm1SWIcaA089lEgVX00QRez5BntLEhs2d4Xsb1yU= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261027001929-981a35b598fd/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI= github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo= diff --git a/modules/mesh-build-node/cmd/mesh-build-node/asks.go b/modules/mesh-build-node/cmd/mesh-build-node/asks.go index f2353133..607755e7 100644 --- a/modules/mesh-build-node/cmd/mesh-build-node/asks.go +++ b/modules/mesh-build-node/cmd/mesh-build-node/asks.go @@ -2,6 +2,7 @@ package main import ( "context" + "time" stdio "git.novox.be/novox/mesh-sdk/go" "git.novox.be/novox/mesh-sdk/go/buildstep" @@ -86,6 +87,13 @@ func (m *Module) SeatTools(p *buildstep.Puller) []stdio.Tool { // StepEndTool ends one step left running (issue 1890); the module's steps state is the one it reads and writes. const StepEndTool = "build_node_step_end" +// endLeftRunning is the module's start sweep (issue 1890): it ends the steps of its node that a previous process left +// running (buildstep.EndStaleAtStart; every step names its owner). main runs it once at the start, and the module's test +// runs it through the conformance kit's left-running case. +func (m *Module) endLeftRunning(ctx context.Context, scan buildstep.Scan, booted time.Time, logf func(string, ...any)) { + buildstep.EndStaleAtStart(ctx, scan, m.Node, booted, logf) +} + // stepScan is the module's steps state as buildstep reads it. func (m *Module) stepScan() buildstep.Scan { return buildstep.ScanOf(stdio.State(delivery.StepsState)) diff --git a/modules/mesh-build-node/cmd/mesh-build-node/kit_test.go b/modules/mesh-build-node/cmd/mesh-build-node/kit_test.go index 1883f689..a1997ef6 100644 --- a/modules/mesh-build-node/cmd/mesh-build-node/kit_test.go +++ b/modules/mesh-build-node/cmd/mesh-build-node/kit_test.go @@ -1,7 +1,9 @@ package main import ( + "context" "testing" + "time" "git.novox.be/novox/mesh-sdk/go/buildstep" "git.novox.be/novox/mesh-sdk/go/buildstep/conformance" @@ -18,3 +20,12 @@ func TestTheTestStepKeepsTheFailureContract(t *testing.T) { return testFailures(".", "type-check", o.Dir, forgekey.Ran{Status: 2, Stdout: o.Stdout, Stderr: o.Stderr}, "") }) } + +// 1890/AC7: the module's own start sweep (endLeftRunning, as main runs it) keeps the conformance kit's left-running +// case: a step a previous process left running is ended at once and said, whatever its age, and a step of this process +// is kept. +func TestTheStartSweepEndsWhatAPreviousProcessLeft(t *testing.T) { + conformance.LeftRunning(t, func(ctx context.Context, scan buildstep.Scan, node string, before time.Time, logf func(string, ...any)) { + (&Module{Node: node}).endLeftRunning(ctx, scan, before, logf) + }) +} diff --git a/modules/mesh-build-node/cmd/mesh-build-node/main.go b/modules/mesh-build-node/cmd/mesh-build-node/main.go index aac0d513..8f2e338d 100644 --- a/modules/mesh-build-node/cmd/mesh-build-node/main.go +++ b/modules/mesh-build-node/cmd/mesh-build-node/main.go @@ -9,7 +9,6 @@ package main import ( "context" "fmt" - "git.novox.be/novox/mesh-sdk/go/buildstep" "os" "os/user" "path/filepath" @@ -75,8 +74,9 @@ func main() { puller := m.Puller(steps, nil) m.Held = puller if m.Node != "" { - // A step a previous process left running is ended (issue 1890); this process's own steps start after booted. - go buildstep.EndStaleAtStart(ctx, m.stepScan(), m.Node, booted, logf) + // A step a previous process left running is ended (issue 1890): one that names another owner, or none and + // started before booted. + go m.endLeftRunning(ctx, m.stepScan(), booted, logf) } if m.Node != "" { // The seat's asks, pulled once Serve has the runtime's channel; a pull before it is said and tried again. diff --git a/modules/mesh-build-node/go.mod b/modules/mesh-build-node/go.mod index 3575f370..5a603ceb 100644 --- a/modules/mesh-build-node/go.mod +++ b/modules/mesh-build-node/go.mod @@ -3,7 +3,7 @@ module meshbuildnode go 1.26.0 require ( - git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026233910-a2759ec92ec9 + git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261027001929-981a35b598fd github.com/distribution/distribution/v3 v3.1.2 github.com/nats-io/nats.go v1.54.0 ) diff --git a/modules/mesh-build-node/go.sum b/modules/mesh-build-node/go.sum index 32f3a421..f577899b 100644 --- a/modules/mesh-build-node/go.sum +++ b/modules/mesh-build-node/go.sum @@ -1,5 +1,5 @@ -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026233910-a2759ec92ec9 h1:MS7i4NVNQHMAMqRRFMdzbto31BHZY+BuEZY1ql3p4Rs= -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026233910-a2759ec92ec9/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261027001929-981a35b598fd h1:B78Hm1SWIcaA089lEgVX00QRez5BntLEhs2d4Xsb1yU= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261027001929-981a35b598fd/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= github.com/alicebob/miniredis/v2 v2.35.0 h1:QwLphYqCEAo1eu1TqPRN2jgVMPBweeQcR21jeqDCONI= github.com/alicebob/miniredis/v2 v2.35.0/go.mod h1:TcL7YfarKPGDAthEtl5NBeHZfeUQj6OXMm/+iu5cLMM= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0=