You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Push the base-branch merge before asking for conflict resolution (#33)
Alternative to #32 for the same stuck-PR bug. Pick one.
Background: when a parent PR is squash-merged, the action brings each
child branch up to date with three merges: the parent branch (the
base-branch merge), the trunk as it stood just before the squash landed
(`SQUASH_COMMIT~`), and the squash itself recorded with `-s ours` so the
child's diff against its new base stays clean. When the pre-squash trunk
merge conflicts, the action asks the user to resolve, and a follow-up
run triggered by the user's push finishes the job.
Two separate bugs left a conflicting child PR broken:
1. **The follow-up run never finished the job.** It removed the conflict
label, retargeted the PR, and deleted the old base branch, but it never
recorded the squash. The synthetic merge commit that keeps the child's
diff against its new base clean was never created, and because the label
was gone the action would never revisit the PR.
2. **Even with that fixed, the recipe could push the user into an
unrecoverable state.** The conflict comment asked the user to merge only
the conflicting ref, starting from a head that did not contain the
base-branch merge. When that merge is clean the head is clean against
its base going in, so the only thing that can make it conflict with the
base is the user's own resolution. If resolving the `SQUASH_COMMIT~`
conflict produced content that conflicts with the parent branch, the
user's push left the head conflicting with its base. GitHub does not run
`pull_request` workflows on a PR that conflicts with its base, so the
follow-up run never fired and the PR was stuck for good.
This PR fixes both:
- Push the base-branch merge before commenting, when it is clean. The
head then always contains it, so the parent branch is an ancestor and no
resolution can make the head conflict with its base. The PR stays
mergeable and the synchronize trigger keeps working. If the base merge
itself conflicts there is nothing safe to pre-push, so the existing
comment-and-label fallback runs.
- `continue_after_resolution` now records the squash with `-s ours` and
pushes before retargeting. The synchronize payload is the child PR, so
the squash commit and new target are reconstructed from the merged
parent PR (its merge commit and base).
Pushing the base merge leaves the user's local branch behind origin, so
the conflict comment now starts the recipe with `git pull --ff-only
origin <branch>`. Without it the user resolves on a stale head and the
final push is rejected as non-fast-forward. The comment still lists only
the genuine conflict to merge.
The e2e conflict scenario already triggers this case (clean base merge,
conflicting `SQUASH_COMMIT~` merge), so coverage lives there: it checks
the action pushed the base merge on top of the pre-conflict head and
that the comment asks only for the genuine conflict, then resolves by
following the comment verbatim (re-sync included) and checks
`continue_after_resolution` records the squash so the branch ends up
mergeable into the new target.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
echo>&2"✅ Verification Passed: action pushed the clean base merge on top of feature3 (still a descendant of its pre-conflict head)."
875
924
else
876
-
echo>&2"❌ Verification Failed: Remote feature3 branch SHA ($REMOTE_FEATURE3_SHA_BEFORE_RESOLVE) differs from expected SHA before conflict resolution ($EXPECTED_FEATURE3_SHA_BEFORE_RESOLVE)."
877
-
exit 1
925
+
echo>&2"❌ Verification Failed: expected origin/feature3 to advance from $FEATURE3_CONFLICT_COMMIT_SHA with the pushed base merge, got $REMOTE_FEATURE3_SHA_BEFORE_RESOLVE."
0 commit comments