The controller asks no build of anybody (ADR 0501 §5, ADR 0525 clause 6, ADR 0503 §3). Every module of a walk is taken from the builder's done key; a key not done yet waits, named in the plan, and never fails it. - C2b/C2c: internal/builder and cmd/mesh-controller's asks go (askABuild, onlyTheBuildersOwn, buildOneAsked, takeIn from an outcome, buildAgentsOwn, the builder's say and its fallback, the daemon hearing an outcome). The server follows the retired seats' built subjects only to let go of them, because the installer's carried user list names them. - C2d: replay, queue, cancel, clear, kill, pause, resume, delivery-check, check-here and merge-gate are refused by name. - C3: the check queues (CHECKS_READY, CHECKS_OTHER) and their workers, the checks-running and plans-building buckets and their grants, the build queue and its hold (plans_building.go, queue.go, link/holds.go, builds_nats.go, checks_nats.go). - C4: merge_gate*.go, the pull request's repo-check path, the Checked event and its layers; a pull request asks the controller nothing but to tell mesh-config what its head declares. - C5: the builds bucket is written only by key_takein. - C10 (help and refusals): the terminal's help lists only what is served. Integration tests of the plan's tiers, sends, stops and retries now run on a stand-in builder with a done key for every module (walk_keys_scaffold_integration_test.go); the tests of the asks, the queue, the merge gate and the replays are deleted.
69 lines
2.7 KiB
Go
69 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/novox/mesh-controller/internal/inventory"
|
|
"github.com/novox/mesh-controller/internal/link"
|
|
)
|
|
|
|
// A build's outcome is taken in the same way whoever hears it (novox/hq issue 176): recorded, and
|
|
// the module registered with its source as the seat and path when the request said so — never the
|
|
// URL. A definition naming an installation is recorded and not registered; a failure is recorded
|
|
// and said.
|
|
|
|
// novox/hq 04-ISSUES/215: a build asked at a commit is recorded as built from that commit, and the
|
|
// module keeps following the branch it followed — a new one, the default branch.
|
|
|
|
// novox/hq 04-ISSUES/219: an older request heard after a newer one is recorded and not registered,
|
|
// so a push sends what the newer request built.
|
|
|
|
func TestABuildIDSaysWhenItWasAsked(t *testing.T) {
|
|
at := time.Date(2026, 10, 3, 21, 51, 57, 392539762, time.UTC)
|
|
if got, ok := link.BuildAskedAt(link.NewBuildID(at)); !ok || !got.Equal(at) {
|
|
t.Errorf("read back %v %v; want %v", got, ok, at)
|
|
}
|
|
if got, ok := link.BuildAskedAt("build-1791064317392539762"); !ok || got.Format(time.TimeOnly) != "21:51:57" {
|
|
t.Errorf("the incident's id reads as %v %v", got, ok)
|
|
}
|
|
for _, id := range []string{"b-1", "build-2", "build-", "build-x", ""} {
|
|
if _, ok := link.BuildAskedAt(id); ok {
|
|
t.Errorf("%q read as a request time", id)
|
|
}
|
|
}
|
|
}
|
|
|
|
// novox/hq issue 1204: builds says the source fingerprint the builder recorded, the one tool that reads it.
|
|
func TestBuildsSaysTheSourceFingerprint(t *testing.T) {
|
|
at := time.Date(2026, 10, 19, 10, 40, 0, 0, time.UTC)
|
|
built := inventory.Build{ID: "build-1", Module: "mailu", Commit: "b4527d9091e972f28cb365623d9280045e7741a3", On: "ace",
|
|
Repository: "novox/mesh-catalog", At: at, ReuseKey: "r1:abc",
|
|
SourceFingerprint: "src1:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}
|
|
|
|
// 1204/AC1
|
|
var out bytes.Buffer
|
|
printBuild(&out, built)
|
|
lines := strings.Split(strings.TrimRight(out.String(), "\n"), "\n")
|
|
if last := lines[len(lines)-1]; last != " source "+built.SourceFingerprint {
|
|
t.Errorf("last line %q; want the source line after the reuse key:\n%s", last, out.String())
|
|
}
|
|
if !strings.Contains(lines[len(lines)-2], "reuse key r1:abc") {
|
|
t.Errorf("the source line does not follow the reuse key:\n%s", out.String())
|
|
}
|
|
|
|
// 1204/AC2
|
|
without := built
|
|
without.SourceFingerprint = ""
|
|
var plain bytes.Buffer
|
|
printBuild(&plain, without)
|
|
if strings.Contains(plain.String(), "source") {
|
|
t.Errorf("a build with no fingerprint says a source line:\n%s", plain.String())
|
|
}
|
|
if want := strings.Join(lines[:len(lines)-1], "\n") + "\n"; plain.String() != want {
|
|
t.Errorf("the other lines changed:\n%s\nwant\n%s", plain.String(), want)
|
|
}
|
|
}
|