Say an unanswered merge check in its own words, with no action it cannot take (issue 438)
mesh/delivery-group group fix/438-a-check-that-never-answered-is-said checking: 0 of 2 member(s) ready
mesh/delivery superseded: a newer head of the same pull request
mesh/merge-gate pass: builds mesh-controller → novox; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed

mesh-delivery now says a head whose merge check started and never answered as a
stalled line in state unanswered. Through the generic delivery words it would read
as a delivery and offer a Stop that mesh-delivery refuses, since no delivery of
the head exists; it now names the checks waited on and what the operator can do.
This commit is contained in:
2026-10-11 02:25:11 +02:00
parent f8d08b0637
commit 585caa4371
3 changed files with 98 additions and 4 deletions
+35
View File
@@ -828,6 +828,9 @@ func stalledWords(l stalledLine, o conditions.Observation) (headline, explanatio
"to check it: the forge never announced it. It cannot merge until it is checked.", pull, long),
fmt.Sprintf("%s has a merge check now, or is closed", pull), needs, nil
}
if l.State == "unanswered" {
return unansweredWords(l, o)
}
held := l.State
if held == "" {
held = "held"
@@ -857,6 +860,38 @@ func stalledWords(l stalledLine, o conditions.Observation) (headline, explanatio
fmt.Sprintf("Delivery of %s is no longer %s", name, held), needs, actions
}
// unansweredWords are the plain words of a pull request's head whose merge check was asked and has not answered
// within its bound (novox/hq issue 438): mesh-delivery holds no delivery of it, so there is nothing to stop, release
// or close, and no action is offered. The operator's acts are a new commit, which asks the check again, or a look
// at the build seat's queue, where a check that never ran may still wait.
func unansweredWords(l stalledLine, o conditions.Observation) (headline, explanation, resolved, needs string,
actions []conditions.Action) {
repository, _, _ := strings.Cut(l.ID, "@")
pull := "A pull request of " + repoName(repository)
if l.Number > 0 {
pull = fmt.Sprintf("Pull request %s #%d", repoName(repository), l.Number)
}
long, limit := "for too long", ""
if d, err := time.ParseDuration(l.For); err == nil {
long = "for " + humanDuration(d)
}
if d, err := time.ParseDuration(l.Bound); err == nil {
limit = ", past its limit of " + humanDuration(d)
}
which := "Its merge check"
if len(l.Waiting) > 0 {
which = "Its merge check (" + strings.Join(l.Waiting, ", ") + ")"
}
if o.Resolver == conditions.ResolverOperator {
needs = "push a new commit to its branch, which asks the check again, or see whether the check still waits " +
"in the build seat's queue: mesh-controller.queue."
}
return fmt.Sprintf("%s has a merge check that has not answered %s", pull, long),
fmt.Sprintf("%s is open on a branch that requires the merge check. %s was asked and has not answered %s%s. "+
"It cannot merge until its check answers.", pull, which, long, limit),
fmt.Sprintf("%s has an answer from its merge check, or is closed", pull), needs, nil
}
// causeWords is a hand-act's cause as a person says it.
func causeWords(cause string) string {
return strings.NewReplacer(".", " ", "_", " ").Replace(cause)