From 004bbc2ce27b4253a3e88eb7fe90bc64e11a809d Mon Sep 17 00:00:00 2001 From: jochen Date: Wed, 28 Oct 2026 18:13:57 +0100 Subject: [PATCH] =?UTF-8?q?Carry=20every=20node's=20name=20on=20a=20check?= =?UTF-8?q?=20ask=20to=20the=20names=20check,=20so=20no=20repository=20lis?= =?UTF-8?q?ts=20them=20(ADR=200567=20=C2=A712,=20issue=201126)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go/buildstep/askrun.go | 3 +++ go/buildstep/askrun_test.go | 7 +++++++ go/delivery/stepasks.go | 19 +++++++++++++++++++ go/delivery/stepasks_test.go | 11 ++++++++++- 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/go/buildstep/askrun.go b/go/buildstep/askrun.go index 0410f3a..f1ef95b 100644 --- a/go/buildstep/askrun.go +++ b/go/buildstep/askrun.go @@ -200,6 +200,9 @@ func (s AskSteps) level(ctx context.Context, job delivery.CheckJob, level string if runner != "" { args["runner"] = runner } + if len(job.NodeNames) > 0 { + args[delivery.NodeNamesArg] = job.NodeNames // the names check's (ADR 0567 §12) + } return args } test := func(args map[string]any) (bool, error) { diff --git a/go/buildstep/askrun_test.go b/go/buildstep/askrun_test.go index 19bed04..047ef1d 100644 --- a/go/buildstep/askrun_test.go +++ b/go/buildstep/askrun_test.go @@ -143,6 +143,13 @@ test {"level":"unit","packages":["x/pkg/a"],"workspace":"/w"}` t.Fatalf("the unit level %+v", u) } + // ADR 0567 §12: a check's node names reach the test tool, for the names check. + r.calls = nil + if _, err := RunAsk(context.Background(), r.steps(), ask(delivery.CheckJob{Levels: []string{delivery.LevelUnit}, NodeNames: []string{"anchor"}, + Fetch: map[string]any{"repository": "novox/x", "commit": runCommit}})); err != nil || !strings.Contains(strings.Join(r.calls, "\n"), `"node-names":["anchor"]`) { + t.Fatalf("the node names are not handed to the test tool: %v, %v", r.calls, err) + } + // Issue 890/AC2: a package declaring node-build-node is not tested on a node that lacks it but named unmet, and is // tested on a node that has it. for _, has := range []bool{false, true} { diff --git a/go/delivery/stepasks.go b/go/delivery/stepasks.go index f940dbf..fba438c 100644 --- a/go/delivery/stepasks.go +++ b/go/delivery/stepasks.go @@ -340,8 +340,20 @@ type CheckJob struct { // Packages, when set, are the only packages each level tests (issue 890, ADR 0552 §4): a placed ask names the // packages the first ask left unmet, and the others are neither tested nor taken kept, so nothing is judged twice. Packages []string `json:"packages,omitempty"` + // NodeNames are the names of every node with a record (novox/hq ADR 0567 §12), read by the checker from each + // `.node` of node-engine's have: the names check of ADR 0507 §9 looks for them in the tree, so no repository + // has to list them. The build step hands them to its test tool as the argument NodeNamesArg, and the build module + // gives them to the tests in NodeNamesEnv. + NodeNames []string `json:"node-names,omitempty"` } +// NodeNamesArg is the test tool's argument that carries a check's node names, and NodeNamesEnv the environment +// variable a build module sets for the tests it runs from it, the names separated by commas. +const ( + NodeNamesArg = "node-names" + NodeNamesEnv = "MESH_NODE_NAMES" +) + func (a StepAsk) check() error { if err := checkAskID(a.ID); err != nil { return err @@ -447,6 +459,13 @@ func (c CheckJob) check(id string) error { return fmt.Errorf("delivery: the check ask %s names a package %q that is no import path", id, p) } } + seen := map[string]bool{} + for _, n := range c.NodeNames { + if err := checkName("node", n); err != nil || strings.Contains(n, ",") || seen[n] { + return fmt.Errorf("delivery: the check ask %s names the node %q, which is no node name or named twice", id, n) + } + seen[n] = true + } return checkFetchArgs(id, c.Fetch) } diff --git a/go/delivery/stepasks_test.go b/go/delivery/stepasks_test.go index 2f10122..99269cf 100644 --- a/go/delivery/stepasks_test.go +++ b/go/delivery/stepasks_test.go @@ -24,7 +24,8 @@ func checkAsk() StepAsk { return StepAsk{ID: "mh3k2x9qa1b2c4", Kind: AskCheck, Language: AskNode, Asker: "mesh-delivery-checker", At: time.Date(2026, 10, 23, 13, 0, 0, 0, time.UTC), Check: &CheckJob{Fetch: map[string]any{"repository": "novox/mesh-catalog", "commit": askCommit, "ref": "refs/pull/3/head", "base": askCommit}, - Levels: []string{LevelUnit, LevelIntegration}, Kept: true, Runner: "workspace", RunnerWhen: "modules/mesh-build-go/", Run: ""}} + Levels: []string{LevelUnit, LevelIntegration}, Kept: true, Runner: "workspace", RunnerWhen: "modules/mesh-build-go/", Run: "", + NodeNames: []string{"anchor", "laptop"}}} } // 1887/A1a: an ask encodes and decodes with every field. @@ -65,6 +66,14 @@ func TestAskRefusesUnknownKindAndLanguage(t *testing.T) { t.Errorf("%s: encoded", name) } } + // ADR 0567 §12: a check's node names are each a node name, once. + for _, names := range [][]string{{"anchor", "anchor"}, {"a.b"}, {""}, {"a,b"}} { + c := checkAsk() + c.Check.NodeNames = names + if _, err := EncodeStepAsk(c); err == nil { + t.Errorf("the node names %q: encoded", names) + } + } // A copy alone fetches nothing and needs no path. a := buildAsk() a.Build.Fetch, a.Build.Path, a.Build.Artifacts = nil, "", []AskArtifact{{Artifact: "base", From: "registry/x@sha256:00"}}