feat(automerge): handle require-up-to-date -- update behind branches instead of failing #265
No reviewers
Labels
No labels
Agent
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No assignees
2 participants
Notifications
Total time spent: 2 minutes 2 seconds
Due date
igor
2 minutes 2 seconds
No due date set.
Dependencies
No dependencies set
Reference
joshtronic/igor!265
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/automerge-update-behind"
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?
Fixes the
merge API failedwarnings — and the underlying starve.What was happening (verified live this morning): a ready PR that's behind its base passes every existing gate (approved, CI green, mergeable), but the merge API rejects it because require-up-to-date is on. So
do_automerge_tickPOSTed a doomed merge and loggedmerge API failedevery single tick. And these do not self-heal — porksicle#82 sat 5-behind and failing for 14+ minutes (including 22 minutes with master perfectly stable); #81 only merged after I manually ran a branchupdateon it.The fix — the gate now checks up-to-date-ness itself, and handles "behind" instead of fighting it:
automerge_behind_count(PR head vs base via the compare API):0= current,>0= behind,-1= can't tell.automerge_update_branch(Forgejo's base-merge) so it satisfies the requirement; CI re-runs and it merges next cycle. The human approval survives the base-merge (verified on #81), and the shadow review's patch-id dedup skips the same-net-diff head.-1) → skip the tick, never a blind update.Anti-thrash for your fast-moving master: it prefers to merge a current PR each tick (master advances once), and updates only one behind PR when none is current. The deploy barrier already freezes master between deploys, which gives the update its window to land.
Net effect: no spurious warnings, and behind PRs self-unblock — your "perfect world."
Tests cover
behind_count(count / up-to-date / API-error),update_branch, and the tick's merge-vs-update-vs-skip decision.bash -n+ check-sync green. No reviewer.Note: once this deploys, the stuck #82 (and any siblings) get picked up automatically — no manual bump.
5341e7c53b9644019c53🤖 Review —
APPROVE(automated)CI for
9644019c: successSummary: Adds a
require-up-to-datehandler todo_automerge_tick: instead of POSTing a merge that the API will reject for a behind-base PR (the oldmerge API failedwarning loop), the gate now measures behind-ness itself and updates the branch instead. Focused, tested, CI green. Approving.What I verified:
automerge_behind_countcallscompare/${head}...${base}, i.e. base-side = PR head SHA, head-side = base ref, sototal_commits= commits the base has that the PR head lacks = behind count. This matches the stated intent ("base-branch commits the PR head is missing"). Had it beenbase...headthe feature would be inverted; it isn't.(.total_commits // (.commits | length) // 0)returns 0 fortotal_commits: 0(jq//only falls through on null/false, not 0), andelse -1/|| echo -1cover non-object and parse-failure cases. Relies on_fjreturning non-zero on API failure, which matches the existing convention inautomerge_do_merge.behind=0→ merge + return 0 (unchanged path);>0→ remember the first behind PR but keep scanning so a later CURRENT PR still wins (return 0 on merge);-1/other → log + continue. Only-one-update-per-tick anti-thrash is implemented as described.[ "$behind" -gt 0 ] 2>/dev/nullsafely treats non-numeric/-1as the else branch.behind_countcount/up-to-date/API-error,update_branchPOST path, and the tick's merge-vs-update-vs-skip (echo 3→ update-not-merge, no deploy;echo -1→ rc1, no update) are all present and meaningful. No CI-workflow files touched; docs/test/lib only; ~70 lines.Non-blocking notes (for the human, no rework needed):
-1and skips a merge that previously would have gone through; it self-heals next tick, but it's a real new dependency worth being aware of.-1) log says "skipping this tick," but the code only skips that PR — a later current PR in the same stream still merges. The behavior is arguably better than the message implies; just a cosmetic mismatch.automerge_behind_countwholesale, so the real compare logic and the tick are never exercised together. Each is unit-tested in isolation (standard), but there's no integration coverage of the URL the real function builds.None of these rise to a blocker. Logic, scope, honesty, and CI all check out.
Independent review by the harness on
claude-opus-4-8. The human reviewer is requested once Igor has reviewed; a human still merges.