diff --git a/cmd/mesh-controller/checks_stop_integration_test.go b/cmd/mesh-controller/checks_stop_integration_test.go index d6f32d1d..0ed5b21a 100644 --- a/cmd/mesh-controller/checks_stop_integration_test.go +++ b/cmd/mesh-controller/checks_stop_integration_test.go @@ -33,6 +33,12 @@ func TestThePullRequestChecksAreAskedOnlyForARepositoryTheCheckerDoesNotJudge(t inventory.Source{Repository: "novox/mesh-controller", Ref: "main", BuiltFrom: "c0", Head: "c0"}); err != nil { t.Fatal(err) } + // hq is cloned as a module built from it is, from its URL: no forge is held in this test. + if err := open.inventory.RegisterModule(ctx, catalogue.Manifest{Module: "hq-docs", Version: "1"}, + inventory.Source{Repository: "http://forge.invalid/novox/hq.git", Ref: "main", Path: "docs", BuiltFrom: "c0", + Head: "c0"}); err != nil { + t.Fatal(err) + } required := map[string][]string{"novox/mesh-controller": {"mesh/check"}, "novox/hq": {"mesh/repo-check"}} was := requiredStatusesOf requiredStatusesOf = func(_ context.Context, owner, repo, _ string) ([]string, error) { diff --git a/cmd/mesh-controller/main.go b/cmd/mesh-controller/main.go index 0b506f2a..1bc06227 100644 --- a/cmd/mesh-controller/main.go +++ b/cmd/mesh-controller/main.go @@ -495,5 +495,11 @@ func removedByName(command string) error { "forget-checks": "build-agent makes no check build from R4e (ADR 0503 §3), so there is nothing to let go of", "delivery-plan": "a delivery's plan is read with `delivery-order` and the checker's verdict (ADR 0503 §3)", }[command] - return fmt.Errorf("`%s` is removed: %s", command, replacement) + return &removedCommand{msg: fmt.Sprintf("`%s` is removed: %s", command, replacement)} } + +// removedCommand is a command or verb the controller no longer has: a refusal that is the verb's whole answer, not a +// verb of a newer build this one cannot run. +type removedCommand struct{ msg string } + +func (r *removedCommand) Error() string { return r.msg } diff --git a/cmd/mesh-controller/pending.go b/cmd/mesh-controller/pending.go index 724a6b1a..0a48d957 100644 --- a/cmd/mesh-controller/pending.go +++ b/cmd/mesh-controller/pending.go @@ -241,7 +241,7 @@ func notRegistered(ctx context.Context, open *stores, node, module string, opts "at the controller's terminal, and the indexer holds no %s", inventory.ErrNoSuchModule, where.said, module) } answer := strings.TrimPrefix(where.said, inventory.ErrNoSuchModule.Error()) + - "\n a module in a repository is registered from the builder's done key once a merge adds it, then assigned" + "\n a module in a repository is registered from the builder's done key of it, then assigned" if opts.Build { answer += "\n build \"true\" asks for nothing: the controller asks no build (ADR 0501 §5), and the indexer " + "holds no module of that name" diff --git a/cmd/mesh-controller/replay867_test.go b/cmd/mesh-controller/replay867_test.go index a8316cee..1918e261 100644 --- a/cmd/mesh-controller/replay867_test.go +++ b/cmd/mesh-controller/replay867_test.go @@ -323,44 +323,3 @@ exit 1 t.Setenv("PATH", dir+string(os.PathListSeparator)+os.Getenv("PATH")) t.Setenv("GOTOOLCHAIN", "local") } - -// A recheck runs as a command of its own (`delivery check` with one member), where the controller is not the serving -// one and holds no connection: it dials the bus for the moment and asks mesh-delivery's `groups` as the daemon does. -// This drives the verb on a test bus with a fake mesh-delivery answering `groups`, with no stub of the seam between. -func TestTheRecheckVerbAsksMeshDeliveryOnABusOfItsOwn(t *testing.T) { - realAsk := askDeliveryOwner - r := theGroupOfIssue867(t) - askDeliveryOwner = realAsk - js, _ := aBuildQueue(t) - if servingBus.Load() != nil { - t.Fatal("this test is of a process that is not the serving controller") - } - asked := 0 - wrapped, _ := json.Marshal(map[string]any{"content": []map[string]any{{"type": "text", "text": r.groups}}}) - sub, err := js.Conn().Subscribe(link.SeatToolSubject(catalogue.DeliverySeat, "groups"), func(m *nats.Msg) { - asked++ - body, _ := json.Marshal(link.Answer{Result: wrapped}) - _ = m.Respond(body) - }) - if err != nil { - t.Fatal(err) - } - t.Cleanup(func() { _ = sub.Unsubscribe() }) - member := `[{"id":"novox/mesh-host@` + r.hostHead[:12] + `","repository":"novox/mesh-host","base":"main","head":"` + - r.hostHead + `","number":114,"paths":["notes.txt"],"module_dirs_said":true}]` - if err := deliveryCommand(t.Context(), []string{"check", "--members", member}); err != nil { - t.Fatal(err) - } - q, err := link.ReadQueue(t.Context(), js, link.TheBuildMachine) - if err != nil || len(q.Asks) == 0 { - t.Fatalf("nothing was asked of the build seat: %v", err) - } - c := q.Asks[len(q.Asks)-1].Request.Check - if c.SiblingsUnknown != "" || len(c.Siblings) != 1 || c.Siblings[0].Repository != "novox/mesh-controller" || - c.Siblings[0].Number != 346 || c.Siblings[0].Head != r.controllerHead { - t.Fatalf("the recheck learned siblings %+v, unknown %q", c.Siblings, c.SiblingsUnknown) - } - if asked != 1 { - t.Fatalf("mesh-delivery was asked %d times", asked) - } -} diff --git a/cmd/mesh-controller/seatverbs.go b/cmd/mesh-controller/seatverbs.go index b27187f3..737c89ec 100644 --- a/cmd/mesh-controller/seatverbs.go +++ b/cmd/mesh-controller/seatverbs.go @@ -1325,7 +1325,8 @@ func seatToolHandlers() (map[string]link.ToolHandler, []string, error) { continue } var policy *heldAtTheTerminal - if _, err := argvFor(verb, sampleArguments(v)); err != nil && !errors.As(err, &policy) { + var removed *removedCommand + if _, err := argvFor(verb, sampleArguments(v)); err != nil && !errors.As(err, &policy) && !errors.As(err, &removed) { // **A row ahead of this binary is not a reason to go silent.** // // The row is the store's and a control plane follows it (novox/hq ADR 0154), so a verb diff --git a/cmd/mesh-controller/seatverbs_schema_integration_test.go b/cmd/mesh-controller/seatverbs_schema_integration_test.go index c955119d..10ac2c9f 100644 --- a/cmd/mesh-controller/seatverbs_schema_integration_test.go +++ b/cmd/mesh-controller/seatverbs_schema_integration_test.go @@ -38,7 +38,7 @@ func servedSchemas(t *testing.T) map[string]catalogue.Verb { func TestNoArgumentAVerbIsGivenIsPassedOver(t *testing.T) { for name, v := range servedSchemas(t) { - if inProcess[name] { + if inProcess[name] || removedVerbs[name] { continue } names, switches := declaredArguments(v) @@ -78,7 +78,7 @@ func TestAnArgumentAVerbDoesNotDeclareIsRefused(t *testing.T) { args := sampleArguments(v) args[stranger] = "x" _, err := argvFor(name, args) - if inProcess[name] { + if inProcess[name] || removedVerbs[name] { _, err = readArguments(name, args) } if err == nil || !strings.Contains(err.Error(), strconv.Quote(stranger)) { @@ -105,7 +105,7 @@ func TestEveryFlagOfAVerbsCommandIsAnArgumentOrAccountedFor(t *testing.T) { reached := map[string]map[string]bool{} // verb → flag sets its command lines reach served := servedSchemas(t) for name, v := range served { - if inProcess[name] || name == "command" { + if inProcess[name] || removedVerbs[name] || name == "command" { continue } names, switches := declaredArguments(v) diff --git a/cmd/mesh-controller/seatverbs_schema_test.go b/cmd/mesh-controller/seatverbs_schema_test.go index a14f1041..0aed1a96 100644 --- a/cmd/mesh-controller/seatverbs_schema_test.go +++ b/cmd/mesh-controller/seatverbs_schema_test.go @@ -177,11 +177,8 @@ var accountedFlags = map[string]map[string]string{ "all": "withheld: the verb naming no machine is --behind, and a push of every machine is said at a " + "shell (novox/hq ADR 0217); `command` reaches it", }, - "build": { - "wait": "set by the verb to 0: the id follows the build (issue 176)", - "self": "set by the verb from the repository's form: a path on the forge, or a URL", - "dry-run": "withheld: a dry run answers only when the build ends, which a call cannot wait for; `command` reaches it", - }, + // Kept only to be refused by name, naming what replaced it (novox/hq ADR 0501 §5, ADR 0429 §18). + "replay": {"register": "withheld: refused by name, a registered replay being removed (ADR 0501 §5)"}, "builds": {"n": "=limit"}, "plans": {"n": "=limit", "what-if": "=repository"}, // The machine's tunnel key, named as the verb's other arguments are (novox/hq ADR 0169). diff --git a/internal/inventory/seats_test.go b/internal/inventory/seats_test.go index c300e97c..fb6cb9c7 100644 --- a/internal/inventory/seats_test.go +++ b/internal/inventory/seats_test.go @@ -230,48 +230,3 @@ func TestASeatsVerbGainsTheArgumentsTheBinaryNames(t *testing.T) { } } } - -// **A stored row's build verb takes on and behind** (novox/hq ADR 0246: arguments added to a verb are -// additive): a row seeded before them described build with a repository it required, so the console -// would refuse both and a call naming neither would be refused for want of a repository. Re-seeding -// gives the row this binary's build. -func TestAStoredRowsBuildVerbTakesOnAndBehind(t *testing.T) { - inv := ForTest(t) - ctx := t.Context() - if _, err := inv.SeedSeats(ctx, catalogue.DefaultSeats()); err != nil { - t.Fatal(err) - } - old := `[{"name":"build","description":"Have the build machine build a repository.","input":{"type":"object", - "properties":{"repository":{"type":"string"},"path":{"type":"string"},"ref":{"type":"string"}}, - "required":["repository"]}}]` - if _, err := inv.store.Pool().Exec(ctx, `update seat set serves = $1 where name = $2`, - []byte(old), catalogue.ControllerSeatName); err != nil { - t.Fatal(err) - } - if _, err := inv.SeedSeats(ctx, catalogue.DefaultSeats()); err != nil { - t.Fatal(err) - } - seats, err := inv.Seats(ctx) - if err != nil { - t.Fatal(err) - } - var build catalogue.Verb - for _, s := range seats { - if s.Name == catalogue.ControllerSeatName { - for _, v := range s.Serves { - if v.Name == "build" { - build = v - } - } - } - } - props, _ := build.Input["properties"].(map[string]any) - for _, arg := range []string{"repository", "path", "ref", "on", "behind"} { - if _, has := props[arg]; !has { - t.Errorf("build in the row does not take %s: %v", arg, props) - } - } - if req, _ := build.Input["required"].([]any); len(req) != 0 { - t.Errorf("build in the row still requires %v, so on and behind alone are refused", req) - } -}