A composed check that lands judged against a trunk that has moved is out of date and asked again (issue 1047, review round 1)

This commit is contained in:
2026-10-18 01:18:13 +02:00
parent 6556e61485
commit e8a74765f8
2 changed files with 54 additions and 0 deletions
@@ -316,4 +316,45 @@ func TestATrunkMoveAsksTheCheckOfAGroupMemberWhoseApproveIsNotAskedYet(t *testin
if len(w.ctl.checks[asked:]) != 1 {
t.Fatalf("asked twice: %v", w.ctl.checks[asked:])
}
// The composed check that was on its way when the trunk moved answers, judged against the old trunk (ADR 0403 §6): it is
// out of date as it lands, so the group does not become ready on it and the operator is not asked.
g := w.h.groups["feat/g"]
w.later(time.Minute)
w.h.Checked(CheckedEvent{Group: "feat/g", ID: g.Check.Asked, Verdict: "pass", Summary: "composed on the old trunk",
Members: []struct {
Owner string `json:"owner"`
Repo string `json:"repo"`
Commit string `json:"commit"`
Trunk string `json:"trunk,omitempty"`
}{{Owner: "novox", Repo: "mesh-controller", Commit: gHc, Trunk: gTrunk0[:12]},
{Owner: "novox", Repo: "mesh-catalog", Commit: gHk, Trunk: gTrunk0[:12]}}})
w.settleAll()
if w.op.count() != 0 {
t.Fatalf("the operator was asked on a composed pass judged against the old trunk: %d", w.op.count())
}
// The moved member's fresh verdict arrives: the composed check is asked again, and only its pass asks the operator.
w.later(time.Minute)
composedBefore := len(w.ctl.checks)
w.h.Checked(judged(gCat, 2, gHk, "pass", gT1))
w.settleAll()
last := w.ctl.checks[len(w.ctl.checks)-1]
if len(w.ctl.checks) == composedBefore || !strings.HasPrefix(last, "feat/g:") {
t.Fatalf("the composed check was not asked again on the fresh verdict: %v", w.ctl.checks[composedBefore:])
}
if w.op.count() != 0 {
t.Fatalf("the operator was asked before the new composed check passed: %d", w.op.count())
}
g = w.h.groups["feat/g"]
w.h.Checked(CheckedEvent{Group: "feat/g", ID: g.Check.Asked, Verdict: "pass", Summary: "composed on the new trunk",
Members: []struct {
Owner string `json:"owner"`
Repo string `json:"repo"`
Commit string `json:"commit"`
Trunk string `json:"trunk,omitempty"`
}{{Owner: "novox", Repo: "mesh-controller", Commit: gHc, Trunk: gTrunk0[:12]},
{Owner: "novox", Repo: "mesh-catalog", Commit: gHk, Trunk: gT1[:12]}}})
w.settleAll()
if w.op.count() != 1 {
t.Fatalf("the operator is asked once, on the new pass: %d", w.op.count())
}
}
@@ -829,6 +829,19 @@ func (h *Holder) Checked(c CheckedEvent) {
}
}
}
// A composed check that was on its way when a trunk moved lands judged against the old trunk: out of date as it lands
// (novox/hq ADR 0403 §6, issue 1047), and asked again once a member is judged again.
if g.Check.OutOfDate == "" {
for id, judged := range g.Check.Trunks {
if d := h.deliveries[id]; d != nil && d.MergedAs == "" && !d.State.Final() && d.TrunkNow != "" && !sameCommit(judged, d.TrunkNow) {
g.Check.OutOfDate = fmt.Sprintf("composed check out of date: %s was judged against trunk %s, the trunk is now %s",
id, shortOf(judged, 12), shortOf(d.TrunkNow, 12))
g.Check.OutOfDateAt = now
h.Logf("[mesh-delivery] group %s: %s", g.ID, g.Check.OutOfDate)
break
}
}
}
g.Updated = now
h.keepGroup(g)
h.Logf("[mesh-delivery] group %s composed: %s — %s", g.ID, c.Verdict, c.Summary)