Merge a group whole or not at all, and say loudly when it cannot (issues 1275, 1276) #375
@@ -306,6 +306,17 @@ func (r *runtime) answer(m rpcMessage) {
|
||||
return toolAnswer(map[string]any{"asked": "check-1"}), nil
|
||||
case "gitea.gitea_open_pulls":
|
||||
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",
|
||||
"gitea.gitea_add_comment":
|
||||
return toolAnswer(map[string]any{}), nil
|
||||
|
||||
@@ -193,8 +193,10 @@ func (h *Holder) groupLines(now time.Time) []StalledLine {
|
||||
merged++
|
||||
}
|
||||
}
|
||||
heldOn := h.deliveries[holdMember(g)]
|
||||
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,
|
||||
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",
|
||||
@@ -218,3 +220,10 @@ func numberOf(d *Delivery) int {
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// 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())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user