Skip to content

ci(staging): rebase-rescue conflicting open PRs onto upstream main - #22

Open
btli wants to merge 1 commit into
mainfrom
ci/staging-rebase-rescue
Open

ci(staging): rebase-rescue conflicting open PRs onto upstream main#22
btli wants to merge 1 commit into
mainfrom
ci/staging-rebase-rescue

Conversation

@btli

@btli btli commented Aug 21, 2026

Copy link
Copy Markdown
Owner

Summary

  • Every night several open PRs skip composition because a merge of their head conflicts with upstream main even when the branch content is fine — typically PRs partially landed upstream (merged in evolved form, cherry-picked), where the total-diff merge conflicts but a commit-by-commit replay succeeds.
  • The composer now gives each conflicting open PR one rescue: rebase its head onto upstream main in a throwaway worktree, retry the merge with the rescued head, and push the rescue back to the PR's fork branch so the PR stays current and the next run composes it on the normal path.

Safety properties

  • Reproducible: fixed ring identity + --committer-date-is-author-date make rescued oids byte-identical across reruns, so same-day no-op detection keeps working even when a push-back fails (covered by test).
  • Leased push-back: --force-with-lease on the pre-rescue head — a branch a human moved meanwhile keeps its newer work; this run still ships the rescue, the next run rescues from the newer head (covered by test).
  • Never blanks a PR: a rescue landing exactly on upstream main (PR fully landed) is not pushed and not composed.
  • Scope: open PRs only — extras are frozen pins, and the production ring never rescues (covered by test).
  • DCO sign-off trailers survive rebase (message-preserving).

Test Plan

  • 5 new offline tests in test_stage.py (rescue success incl. fork-branch refresh, reproducibility/no-op rerun, moved-branch lease, production-ring exclusion, and the existing pure-conflict skip still byte-identical).
  • Full composer suite: test_stage.py + test_ring_golden.py + test_push_classify.py82 passed (goldens untouched).

Note for local checkouts

When the ring rescues one of your PRs, its branch history is rewritten — git pull --rebase (or git reset --hard origin/<branch>) before continuing local work on that branch.

A merge applies a PR's total diff, so a PR partially landed upstream
(merged in evolved form, cherry-picked) conflicts every night even
though replaying its commits succeeds. Give each conflicting open PR
one rescue: rebase its head onto upstream main in a throwaway worktree
(reproducible identity and committer dates, already-landed patches
dropped), retry the merge with the rescued head, and push the rescue
back to the PR's fork branch under a lease on the pre-rescue head so a
branch that moved keeps its newer work.

Extras stay verbatim (frozen pins) and the production ring never
rescues. A rescue that lands exactly on upstream main is not pushed —
the PR fully landed and blanking its branch helps nobody. Rescues are
byte-reproducible, so a rerun with a stale listing rebuilds the same
head and no-op detection keeps working.
@github-actions github-actions Bot added the size/L Pull request size: L label Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/L Pull request size: L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant