A group's composed verdict names each member's siblings at the heads it composed, so a sibling's own merge is no move (issue 1049)

This commit is contained in:
2026-10-18 01:08:26 +02:00
parent 0c56f60305
commit da094008ea
6 changed files with 184 additions and 1 deletions
@@ -428,6 +428,8 @@ type fakeForge struct {
merges, comments []string
approvedHeads [][]string
refuse error
// refuseRepo refuses the merges of one repository only ("owner/name"), beside refuse (issue 1049).
refuseRepo map[string]error
// calls are the comments in the order asked.
calls []string
}
@@ -711,6 +713,9 @@ func (f *fakeForge) Merge(owner, repo string, number int, head string, approved
defer f.mu.Unlock()
f.merges = append(f.merges, fmt.Sprintf("%s/%s#%d@%s", owner, repo, number, head))
f.approvedHeads = append(f.approvedHeads, approved)
if err := f.refuseRepo[owner+"/"+repo]; err != nil {
return err
}
return f.refuse
}
@@ -188,3 +188,34 @@ func TestAMemberWhoseGateIsTheComposedChecksCountsAsPassed(t *testing.T) {
t.Fatalf("a member whose repository check failed is ready")
}
}
// Issue 1049 (survey question 1, confirmed here): a composed check asked after one member has already merged is asked
// with ALL the members, the merged one at the head it merged, never with the unmerged one alone. The controller needs two
// or more members to compose (mesh-controller delivery.go askGroupCheck), and a merge of a contained head is a no-op
// there.
func TestAComposedCheckAskedAfterOneMemberMergedIsAskedWithAllMembers(t *testing.T) {
w := approvedGroup(t)
w.forge.refuseRepo = map[string]error{gCtl: errAskedAgain}
w.op.answer(w.op.open()[0], OptionApprove)
w.settleAll()
w.h.PullMerged(merged(gCat, 2, gHk, gT1))
w.settleAll()
if g := w.h.groups["feat/g"]; g == nil || !g.Closed {
t.Fatalf("the group did not close when a member merged: %+v", g)
}
// The unmerged member gets a new head and its own verdict: the group's composed check is due again.
const gHc2 = "e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3"
asked := len(w.ctl.checks)
w.h.PullUpdated(pr(gCtl, 1, gHc2, "feat/g", "internal/a.go"))
w.h.Checked(judged(gCtl, 1, gHc2, "pass", gT1))
w.settleAll()
var composed []string
for _, c := range w.ctl.checks[asked:] {
if len(c) > 7 && c[:7] == "feat/g:" {
composed = append(composed, c)
}
}
if len(composed) != 1 || composed[0] != "feat/g:"+IDOf(gCat, gHk)+","+IDOf(gCtl, gHc2) {
t.Fatalf("the composed check was asked with %v; wanted once, with both members (the merged one at its head)", composed)
}
}