From bc623bc1f944088c80b16f285e1e696ccb1789d0 Mon Sep 17 00:00:00 2001 From: jochen Date: Mon, 12 Oct 2026 17:44:18 +0200 Subject: [PATCH] Name the announced trunk commit on a verdict no build judges A change touching no module, in a repository with no merge-check.sh, was answered by the controller with no trunk commit, so the merge tool refused it, asked again and refused it for ever (novox/mesh-tools-go; novox/hq ADR 0323). --- cmd/mesh-controller/checks.go | 22 +++++++++++++++++++--- cmd/mesh-controller/checks_test.go | 18 ++++++++++++++++++ internal/link/events.go | 4 ++++ 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/cmd/mesh-controller/checks.go b/cmd/mesh-controller/checks.go index 9faa4915..1ff6a275 100644 --- a/cmd/mesh-controller/checks.go +++ b/cmd/mesh-controller/checks.go @@ -161,9 +161,7 @@ func (f following) PullUpdated(ctx context.Context, p link.PullUpdated) error { return u, err == nil }) fmt.Print(planText(plan)) - direct := link.Checked{Owner: p.Owner, Repo: p.Repo, Number: p.Number, Commit: p.Commit, - ID: link.NewBuildID(time.Now()), Verdict: "pass", Summary: noModuleTouched, - Gate: &link.CheckLayer{Verdict: "pass", Summary: noModuleTouched}, Plan: &plan} + direct := directVerdict(p, plan) switch { case !scope.gated() && !scope.Mesh: fmt.Printf("%s/%s#%d (%.8s): %s, and the repository is not the mesh's: said, nothing run\n", @@ -201,6 +199,24 @@ func (f following) PullUpdated(ctx context.Context, p link.PullUpdated) error { return nil } +// directVerdict is the verdict of a change no build judges — it touches no module, and either the repository is not +// the mesh's or the head holds no merge-check.sh. **It names the trunk commit it holds for** (novox/hq ADR 0323 §3): +// the base branch's head the forge announced with the head, so the merge tool can weigh it against the trunk's head +// and does not refuse it for ever (a verdict naming no trunk is never the trunk's head's). Nothing was built to +// judge: the trunk commit is the one the forge said the change was announced against. +func directVerdict(p link.PullUpdated, plan link.ChangePlan) link.Checked { + trunk := p.BaseSHA + if len(trunk) > 12 { + trunk = trunk[:12] + } + if trunk != "" { + plan.Trunk = trunk + } + return link.Checked{Owner: p.Owner, Repo: p.Repo, Number: p.Number, Commit: p.Commit, + ID: link.NewBuildID(time.Now()), Verdict: "pass", Summary: noModuleTouched, + Gate: &link.CheckLayer{Verdict: "pass", Summary: noModuleTouched}, Plan: &plan, Trunk: trunk} +} + // checkRequestFor is the ask for one pull request's head: the repository as the mesh clones it, the head, // and what is read beside it. func checkRequestFor(ctx context.Context, open *stores, p link.PullUpdated, scope checkScope, diff --git a/cmd/mesh-controller/checks_test.go b/cmd/mesh-controller/checks_test.go index 65a8314f..4d62e4dc 100644 --- a/cmd/mesh-controller/checks_test.go +++ b/cmd/mesh-controller/checks_test.go @@ -260,3 +260,21 @@ func TestABuildOfACheckMergeIsRefusedNamingTheTrunk(t *testing.T) { t.Fatalf("a build of a check's merge was answered %v", err) } } + +// **A verdict no build judges names its trunk commit too** (novox/hq ADR 0323 §3): a change touching no module of a +// repository with no merge-check.sh (novox/mesh-tools-go) is answered by the controller itself. Naming no trunk, the +// merge tool refused it, asked again, got the same verdict, and refused for ever. +func TestADirectVerdictNamesTheTrunkTheForgeAnnounced(t *testing.T) { + p := link.PullUpdated{Owner: "novox", Repo: "mesh-tools-go", Number: 3, Base: "main", Commit: "1a2b3c4d5e6f7a8b9c0d", + BaseSHA: "7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b"} + c := directVerdict(p, link.ChangePlan{Repository: "novox/mesh-tools-go", Base: "main", Head: p.Commit}) + if c.Trunk != "7a8b9c0d1e2f" || c.Plan == nil || c.Plan.Trunk != "7a8b9c0d1e2f" { + t.Fatalf("the direct verdict names trunk %q, its plan %+v", c.Trunk, c.Plan) + } + if c.Verdict != "pass" || c.Commit != p.Commit { + t.Fatalf("the direct verdict is %+v", c) + } + if c := directVerdict(link.PullUpdated{Owner: "novox", Repo: "x", Commit: "abc"}, link.ChangePlan{}); c.Trunk != "" { + t.Fatalf("a forge that said no base head gave the trunk %q", c.Trunk) + } +} diff --git a/internal/link/events.go b/internal/link/events.go index aeddd28d..cd5c1b1d 100644 --- a/internal/link/events.go +++ b/internal/link/events.go @@ -228,6 +228,10 @@ type PullUpdated struct { Base string `json:"base"` Head string `json:"head"` Commit string `json:"head_sha"` + // BaseSHA is the base branch's head when the forge announced the head (novox/hq ADR 0323): the trunk commit a + // verdict the controller gives without the build seat — a change that runs no build — is judged against. Empty + // from a forge module from before it. + BaseSHA string `json:"base_sha,omitempty"` CloneURL string `json:"clone_url"` HTMLURL string `json:"html_url,omitempty"` // Paths are the files the pull request changes; PathsTruncated says there were more.