fix(finish): detect a CI-gated merge and wait (backgroundable) instead of failing #438
Labels
No labels
breaking
bug
documentation
enhancement
epic
good first issue
help wanted
refactoring
resolution/duplicate
resolution/invalid
resolution/wontfix
security
severity/critical
severity/high
severity/low
severity/medium
status/abandoned
status/blocked
status/needs-decision
status/needs-info
status/needs-verification
testing
upstream
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
sixfold-space/madtea#438
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
madtea finishdoes commit + push + PR + merge + return-to-mainline in one call. On a repo with branch protection that requires a status check, the merge step fails: the forge rejects it with405 "not all required status checks successful", because the required CI check has only just started when finish tries to merge.By then finish has already committed, pushed, and opened the PR, so no work is lost. But the merge and the return-to-mainline do not happen. The caller is dropped back into the exact manual flow finish exists to remove: watch the run, merge the PR by hand once it is green, then pull and delete the branch. On every protected-branch repo, finish is a partial operation.
The consolidated finish flow simplified the common case, but the common case for anyone shipping real work is a protected default branch with required CI. That is precisely where finish stops short.
What it should do
Acceptance
finishon a branch-protected repo with required CI completes the full commit -> merge -> mainline flow, or cleanly schedules an auto-merge and returns - no manualprs merge+pull+ branch-delete needed.Repro
madtea finishfrom a feature branch. The push and PR succeed; the merge is rejected with405 "not all required status checks successful"while the check is still running.Landed in PR #464. A new gitea.IsMergeRequiredChecksPending predicate catches the CI-gated 405, and MergeWithRetry re-issues the merge with merge_when_checks_succeed so the forge merges on green, returning an ErrAutoMergeScheduled sentinel. Every merge caller honors it - finish (local and remote), pr merge, the MCP prs merge action, and orchestrate batch-merge and revert - each reporting the scheduled merge and skipping return-to-mainline (no pull, no branch delete). Design: forge-side auto-merge-on-green, not a blocking poll (the issue offered either).
Two assumptions ride the live forge and cannot be tested hermetically, so they want confirming on the first real CI-gated finish:
Also worth flagging: batch-merge and revert now schedule-and-disclose on a CI-gated 405 too, replacing the old behavior that mislabeled it as a moved base and failed with the wrong message. That is the correct, consistent handling, but it is a behavior change on those paths.
Keeping this open on the two live-forge checks.
Verified live on the forge, 2026-09-09, both assumptions the fix in PR #464 rode on.
Setup: a temporary protected branch
verify-438-baseon this repo withenable_status_checkand required contextgate-438(nothing reports it), a one-file branchverify-438-head, and PR #477 between them. All three are removed again.The 405 wording. The forge returned
405 {"message":"not allowed to merge [reason: Not all required status checks successful]"}.gitea.IsMergeRequiredChecksPending(internal/gitea/client_errors.go) matches it case-insensitively, and a binary built from main did:madtea pr merge 477printed "Required status checks are still running; scheduled an auto-merge that completes when they pass" and "Enabled auto-merge for pull request #477", exit 0, no manual merge and no branch update attempted.A 2xx on the schedule request queues a real auto-merge. I then posted a
successstatus for contextgate-438on the head sha by hand. The forge merged PR #477 on its own at 22:20:21Z (merged: true,merged_by: hexajon, merge commit equals the head sha). No further madtea call was involved, so the 2xx did queue the merge.Also confirmed the negative case by accident: a stale 0.18.3 binary sent the same 405 down the old behind-base path ("branch update failed ... HeadBranch of PR 477 is up to date"), which is exactly the pre-fix behaviour this issue describes. Current binaries carry the fix; the release v0.18.5 includes it.