fix(forgejo): auto-merge rebases head branch on 'behind base' before retry #44

Merged
navigator merged 1 commit from fix/auto-merge-rebase-behind-base into main 2026-05-25 14:29:44 -03:00
Owner

Summary

When POST /pulls/{n}/merge returned HTTP 405 "head branch is behind the base branch" (the common case after a PR earlier in a cascade lands), auto-merge.sh exited 5 and the pr-approver re-kicked it every 60s — flooding Telegram with hundreds of notifications and never making progress until a human rebased manually.

This adds an inline one-shot rebase retry:

  • Detect 405 with behind the base branch in the response body.
  • Clone repo in a temp dir, fetch base, rebase head on origin/<base>, force-push with --force-with-lease.
  • Real rebase conflicts → abort + exit 5 (human triage, no auto-resolve).
  • After a clean rebase the head SHA changes, so re-run poll-CI → approve → merge on the new SHA.
  • Retries capped at MAX_REBASE_RETRIES (default 1) — prevents an infinite cascade if base keeps moving.

Refactor splits the existing body into wait_for_ci, attempt_merge, and rebase_and_push helpers so the retry path is a single while : loop.

Test plan

  • bash -n infra/forgejo/auto-merge.sh (passes locally)
  • Manually merge a follow-up PR onto main, then run bash infra/forgejo/auto-merge.sh <pr> on a "behind base" PR and confirm: clone → rebase → push → re-poll CI → approve → merge cycle completes cleanly
  • Inject a real conflict on a test branch and verify the script aborts with exit 5 (no destructive auto-resolution)

Notes

  • infra/forgejo/** is off-limits per ADR-017 — this PR must be reviewed/merged by Marcos, not by the swarm.
  • Once landed, fluidpop-pr-approver.service can be re-enabled.
## Summary When `POST /pulls/{n}/merge` returned HTTP 405 "head branch is behind the base branch" (the common case after a PR earlier in a cascade lands), `auto-merge.sh` exited 5 and the `pr-approver` re-kicked it every 60s — flooding Telegram with hundreds of notifications and never making progress until a human rebased manually. This adds an inline one-shot rebase retry: - Detect 405 with `behind the base branch` in the response body. - Clone repo in a temp dir, fetch base, rebase head on `origin/<base>`, force-push with `--force-with-lease`. - Real rebase conflicts → abort + exit 5 (human triage, no auto-resolve). - After a clean rebase the head SHA changes, so re-run poll-CI → approve → merge on the new SHA. - Retries capped at `MAX_REBASE_RETRIES` (default 1) — prevents an infinite cascade if base keeps moving. Refactor splits the existing body into `wait_for_ci`, `attempt_merge`, and `rebase_and_push` helpers so the retry path is a single `while :` loop. ## Test plan - [ ] `bash -n infra/forgejo/auto-merge.sh` (passes locally) - [ ] Manually merge a follow-up PR onto main, then run `bash infra/forgejo/auto-merge.sh <pr>` on a "behind base" PR and confirm: clone → rebase → push → re-poll CI → approve → merge cycle completes cleanly - [ ] Inject a real conflict on a test branch and verify the script aborts with exit 5 (no destructive auto-resolution) ## Notes - `infra/forgejo/**` is off-limits per ADR-017 — this PR must be reviewed/merged by Marcos, not by the swarm. - Once landed, `fluidpop-pr-approver.service` can be re-enabled.
fix(forgejo): auto-merge rebases head branch on 'behind base' before retry
All checks were successful
build / scalafmt-check (pull_request) Successful in 4s
build / sbt-compile (pull_request) Successful in 4s
build / shell-lint (pull_request) Successful in 20s
a74364851e
When `POST /pulls/{n}/merge` returns HTTP 405 "head branch is behind the
base branch" (e.g., after a previous PR in the cascade lands), the old
script exited 5 and the pr-approver kept calling it in a 60s loop,
flooding Telegram with notifications. The merge would never succeed
without a manual rebase + force-push.

This adds a one-shot rebase retry inline:

- Detect 405 with "behind the base branch" in the response body.
- Clone the repo into a temp dir, fetch the latest base, rebase the
  head branch on `origin/<base>`, force-push with `--force-with-lease`.
- If rebase produces conflicts, abort, exit 5 — a real human-triage
  blocker. We do not auto-resolve content conflicts.
- After a clean force-push the head SHA changes, so re-run the
  poll-CI → approve → merge cycle on the new SHA. Retries are capped
  at MAX_REBASE_RETRIES (default 1) to prevent infinite loops if
  base keeps moving.

Refactors the body into three helpers (rebase_and_push, wait_for_ci,
attempt_merge) so the retry loop is a clean `while :`.

The git identity used for the rebase commits is the swarm identity
(FluidPop Swarm <swarm@pop.coop>); rebases of clean fast-forwardable
work preserve the original commit metadata.
fluidpop-bot left a comment
Collaborator

CI green (head a74364851e), auto-approving

CI green (head a74364851e1f27f45aeed8e6ece0df57290c2262), auto-approving
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Fluid/fluidpop-v1!44
No description provided.