Answer gitea_commit_statuses in the bus test's runtime, and say a held, refused member once (issue 1275, review round 1)
mesh/merge-gate head 301cd2287f5f merged into trunk eda55ceb9e1b — pass: builds mesh-delivery → novox; no bus step; every machine composes with the change …
mesh/repo-check head 301cd2287f5f merged into trunk eda55ceb9e1b — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-…
mesh/delivery delivered

This commit is contained in:
2026-10-19 20:38:48 +02:00
parent 524e3405e5
commit 301cd2287f
3 changed files with 48 additions and 1 deletions
@@ -306,6 +306,17 @@ func (r *runtime) answer(m rpcMessage) {
return toolAnswer(map[string]any{"asked": "check-1"}), nil return toolAnswer(map[string]any{"asked": "check-1"}), nil
case "gitea.gitea_open_pulls": case "gitea.gitea_open_pulls":
return toolAnswer(map[string]any{"pulls": pulls}), nil return toolAnswer(map[string]any{"pulls": pulls}), nil
case "gitea.gitea_commit_statuses":
// Green: both merge checks a success at the head asked, as the gitea module answers.
sha, _ := a.Body["sha"].(string)
if sha == "" {
sha = "0000000"
}
return toolAnswer(map[string]any{"commit": sha, "statuses": []any{
map[string]any{"context": "mesh/merge-gate", "state": "success"},
map[string]any{"context": "mesh/repo-check", "state": "success"}},
"merge": map[string]any{"branch": "main", "protected": true, "required": []string{"mesh/merge-gate", "mesh/repo-check"},
"blocking": []any{}, "mergeable": true, "says": "main requires mesh/merge-gate, mesh/repo-check"}}), nil
case "gitea.gitea_note_append", "gitea.gitea_delivery_view", "gitea.gitea_commit_status", "gitea.gitea_merge_pull_request", case "gitea.gitea_note_append", "gitea.gitea_delivery_view", "gitea.gitea_commit_status", "gitea.gitea_merge_pull_request",
"gitea.gitea_add_comment": "gitea.gitea_add_comment":
return toolAnswer(map[string]any{}), nil return toolAnswer(map[string]any{}), nil
@@ -193,8 +193,10 @@ func (h *Holder) groupLines(now time.Time) []StalledLine {
merged++ merged++
} }
} }
heldOn := h.deliveries[holdMember(g)]
switch { switch {
case g.Hold != nil && g.Hold.Kind == "blocked" && !running: // A held member the merge tool refused is said by readyLines already: one line for an id, not two.
case g.Hold != nil && g.Hold.Kind == "blocked" && !running && !(heldOn != nil && heldOn.Ready != nil && heldOn.Ready.RefusedSince != nil):
out = append(out, StalledLine{ID: g.Hold.Member, Number: numberOf(h.deliveries[g.Hold.Member]), State: first.State, out = append(out, StalledLine{ID: g.Hold.Member, Number: numberOf(h.deliveries[g.Hold.Member]), State: first.State,
For: now.Sub(g.Hold.Since).Round(time.Second).String(), Bound: "0s", Severity: "urgent", For: now.Sub(g.Hold.Since).Round(time.Second).String(), Bound: "0s", Severity: "urgent",
H2: "none: the required status turns success, which asks the merge again — or the operator's decision", H2: "none: the required status turns success, which asks the merge again — or the operator's decision",
@@ -218,3 +220,10 @@ func numberOf(d *Delivery) int {
} }
return d.Number return d.Number
} }
func holdMember(g *Group) string {
if g.Hold == nil {
return ""
}
return g.Hold.Member
}
@@ -221,3 +221,30 @@ func TestAClosedGroupsMemberRefusedForItsOwnMissingStatusAsksItsOwnCheck(t *test
t.Fatalf("own checks %v, composed checks %v; wanted the member's own check once and no composed check", own, composed) t.Fatalf("own checks %v, composed checks %v; wanted the member's own check once and no composed check", own, composed)
} }
} }
// 1275/AC3 (review round 1): a member that is both refused and held for a required status is said by one stalled line,
// not two with the same id.
func TestAMemberBothRefusedAndHeldForAStatusIsOneStalledLine(t *testing.T) {
w := approvedGroup(t)
allGreen(w)
w.forge.refuseRepo = map[string]error{gCat: refusedWords("novox/mesh-catalog#2")}
w.op.answer(w.op.open()[0], OptionApprove)
w.settleAll()
setChecks(w, gCat, gHk, "success", "") // now its status is missing too; the next pass is held
w.h.CommitStatus(ForgeStatusEvent{Owner: "novox", Repo: "mesh-catalog", SHA: gHk, Context: repoCheck, State: "success"})
w.h.mergeAgainNow(w.delivery(IDOf(gCat, gHk)))
w.later(time30s)
w.settleAll()
if g := w.h.groups["feat/g"]; g.Hold == nil {
t.Fatalf("the group was not held for the missing status")
}
n := 0
for _, l := range w.h.Stalled() {
if l.ID == IDOf(gCat, gHk) {
n++
}
}
if n != 1 {
t.Fatalf("%d stalled lines for one member: %+v", n, w.h.Stalled())
}
}