diff --git a/modules/mesh-delivery/cmd/mesh-delivery/holder.go b/modules/mesh-delivery/cmd/mesh-delivery/holder.go index 585c9b64..04d6589c 100644 --- a/modules/mesh-delivery/cmd/mesh-delivery/holder.go +++ b/modules/mesh-delivery/cmd/mesh-delivery/holder.go @@ -279,6 +279,8 @@ type PullEvent struct { ModuleDirs []string `json:"module_dirs,omitempty"` ModuleDirsSaid bool `json:"module_dirs_said,omitempty"` HeadChecks map[string]string `json:"head_checks,omitempty"` + // BaseSHA is the base branch's head when the head was announced (novox/hq ADR 0323). + BaseSHA string `json:"base_sha,omitempty"` } func (p PullEvent) repository() string { return strings.ToLower(p.Owner + "/" + p.Repo) } @@ -300,7 +302,11 @@ func (h *Holder) PullUpdated(p PullEvent) { if d := h.deliveries[id]; d != nil { // Announced again: nothing new — but for a delivery whose verdict is out of date, the announcement is its // check asked again against the trunk's head (the merge tool's ask, novox/hq ADR 0323 §5), and its bound - // runs from now (§7). + // runs from now (§7). The base head it was announced with is kept, for a check this owner asks after it. + if p.BaseSHA != "" && d.BaseSHA != p.BaseSHA { + d.BaseSHA = p.BaseSHA + h.keep(d) + } if d.State == Proposed && d.outOfDate() != "" && d.AskedAgain == nil { d.AskedAgain = &now h.keep(d) @@ -322,7 +328,7 @@ func (h *Holder) PullUpdated(p PullEvent) { d := &Delivery{ID: id, Repository: p.repository(), Commit: p.HeadSHA, Number: p.Number, Title: p.Title, Base: p.Base, Branch: p.Head, HTMLURL: p.HTMLURL, CloneURL: p.CloneURL, Paths: p.Paths, PathsTruncated: p.PathsTruncated, Removed: p.Removed, ModuleDirs: p.ModuleDirs, ModuleDirsSaid: p.ModuleDirsSaid, - After: AfterIn(p.Body), Created: now} + After: AfterIn(p.Body), Created: now, BaseSHA: p.BaseSHA} t, err := Apply(d, EvAnnounced, false, Facts{Now: now, Why: fmt.Sprintf("%s#%d's head announced", d.Repository, d.Number)}) if err != nil { h.refuse(err) diff --git a/modules/mesh-delivery/cmd/mesh-delivery/issue341_test.go b/modules/mesh-delivery/cmd/mesh-delivery/issue341_test.go index 311dc194..1b6e5352 100644 --- a/modules/mesh-delivery/cmd/mesh-delivery/issue341_test.go +++ b/modules/mesh-delivery/cmd/mesh-delivery/issue341_test.go @@ -438,3 +438,26 @@ func TestARebasedMemberAfterAnotherWasDeliveredIsComposedAgain(t *testing.T) { t.Fatalf("the rebased member is held: %s", d.HeldWhy) } } + +// A check this owner asks — a recheck — sends the base head the forge last announced the head with, so the +// controller's verdict for a head no build judges names its trunk commit (ADR 0323 §3, review of mesh-controller#271). +func TestARecheckSendsTheAnnouncedBaseHead(t *testing.T) { + const repo = "novox/mesh-tools-go" + const head = "1a2b3c4d5e6f7a8b" + w := newWorld(t) + p := pr(repo, 3, head, "x") + p.BaseSHA = trunk0 + w.h.PullUpdated(p) + id := IDOf(repo, head) + if m := MemberOf(w.delivery(id)); m.BaseSHA != trunk0 { + t.Fatalf("the member sends base head %q", m.BaseSHA) + } + p.BaseSHA = merge1 // announced again, by the merge tool + w.h.PullUpdated(p) + if m := MemberOf(w.delivery(id)); m.BaseSHA != merge1 { + t.Fatalf("announced again, the member sends base head %q", m.BaseSHA) + } + if raw := string(mustJSON(MemberOf(w.delivery(id)))); !strings.Contains(raw, `"base_sha":"`+merge1+`"`) { + t.Fatalf("the member as the controller reads it: %s", raw) + } +} diff --git a/modules/mesh-delivery/cmd/mesh-delivery/model.go b/modules/mesh-delivery/cmd/mesh-delivery/model.go index 41a7affb..55980cb2 100644 --- a/modules/mesh-delivery/cmd/mesh-delivery/model.go +++ b/modules/mesh-delivery/cmd/mesh-delivery/model.go @@ -53,6 +53,9 @@ type Delivery struct { // into its trunk landed as (novox/hq ADR 0323 §7). A verdict that names another trunk commit is out of date. // Empty until a merge into its trunk is heard after it was made. TrunkNow string `json:"trunk_now,omitempty"` + // BaseSHA is the base branch's head the forge last announced its head with (ADR 0323): sent with a check this + // owner asks, for a verdict no build judges to name its trunk commit. + BaseSHA string `json:"base_sha,omitempty"` // AskedAgain is when its head was announced again while its verdict was out of date — the merge tool's ask of // its check against the trunk's head (ADR 0323 §5) — and no verdict has come since: its one-hour bound runs from // then. Nil while nothing is asked, and cleared by a verdict or another move of its trunk. diff --git a/modules/mesh-delivery/cmd/mesh-delivery/ports.go b/modules/mesh-delivery/cmd/mesh-delivery/ports.go index 8675075e..c0185b1d 100644 --- a/modules/mesh-delivery/cmd/mesh-delivery/ports.go +++ b/modules/mesh-delivery/cmd/mesh-delivery/ports.go @@ -31,13 +31,16 @@ type Member struct { ModuleDirsSaid bool `json:"module_dirs_said,omitempty"` CloneURL string `json:"clone_url,omitempty"` After []string `json:"after,omitempty"` + // BaseSHA is the base branch's head the forge last announced the head with (novox/hq ADR 0323): the trunk commit + // the controller's verdict names when no build judges the head. + BaseSHA string `json:"base_sha,omitempty"` } // MemberOf is a delivery as a member. func MemberOf(d *Delivery) Member { return Member{ID: d.ID, Repository: d.Repository, Base: d.Base, Head: d.Commit, Number: d.Number, Paths: d.Paths, PathsTruncated: d.PathsTruncated, Removed: d.Removed, ModuleDirs: d.ModuleDirs, ModuleDirsSaid: d.ModuleDirsSaid, - CloneURL: d.CloneURL, After: d.After} + CloneURL: d.CloneURL, After: d.After, BaseSHA: d.BaseSHA} } // Order is a group's order as the controller works it out: each pair with the rules it won over by