fix(ci): use GraphQL REBASE for auto-update PR branches (kill merge bubbles)#411
Merged
Merged
Conversation
The REST endpoint PUT /repos/{}/pulls/{}/update-branch is merge-only —
it merges main HEAD INTO the PR branch as a merge commit, polluting
the PR's history with a merge bubble per main movement. Observed live
in PRs #403/#406: every time main moved, auto-update added a merge
commit (e.g. b972586), breaking force-pushed linear rebase history.
Other Claude session's proposed fix (`-f "update_method=rebase"` on
the REST call) doesn't work — the parameter is silently ignored. Per
GitHub REST docs the only body param is `expected_head_sha`.
The correct path is GraphQL: the `updatePullRequestBranch` mutation
accepts `updateMethod: REBASE` (enum PullRequestBranchUpdateMethod
verified empirically). Switch the API call:
# before
gh api -X PUT 'repos/$REPO/pulls/$pr/update-branch'
# after
gh api graphql -f query='
mutation($id: ID!) {
updatePullRequestBranch(input: { pullRequestId: $id, updateMethod: REBASE }) {
pullRequest { number headRefOid }
}
}
' -f id="$nodeid"
Requires fetching .id (GraphQL node ID) alongside .number from
`gh pr list` — added.
Response-pattern matching updated to match GraphQL output (success
detected via *headRefOid* present in response, conflict via
*could not be rebased* / *conflict*).
Risk: if GitHub's rebase decides the branch can't be cleanly rebased
(e.g. merge commits in PR history), it falls back to merge or errors
out. Currently no PR mixes in merge commits, so this is theoretical.
The marker-comment safety net catches unexpected error states.
$id inside the single-quoted query string is a GraphQL variable name, not a shell expansion. Bash single-quoting is correct here; the shellcheck-disable comment + explanatory note makes the intent explicit for future readers.
Contributor
ecp impact cache (0 symbols) — internal, used by
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Symptom
PRs #403 / #406 had auto-merge enabled. As main moved (PRs #401/#402/#404 etc. landed), the `Auto-update PR branches` workflow merged main HEAD INTO each PR branch as a merge commit (e.g. b972586), breaking linear rebase history maintained by force-pushes. Another session diagnosed live by force-pushing clean rebases to overwrite the polluted state.
Root cause
The REST endpoint `PUT /repos/{owner}/{repo}/pulls/{pull_number}/update-branch` is merge-only. Per GitHub REST docs, the only body parameter is `expected_head_sha` — no rebase option.
A previously-suggested fix of `-f "update_method=rebase"` doesn't actually work: empirical test on this repo's PRs shows the parameter is silently ignored. The endpoint always produces a merge commit.
Fix
GitHub's GraphQL `updatePullRequestBranch` mutation accepts `updateMethod: REBASE` (enum `PullRequestBranchUpdateMethod` with values MERGE | REBASE, verified empirically against the live schema).
Swap the API call from REST to GraphQL:
```bash
Before
gh api -X PUT "repos/$REPO/pulls/$pr/update-branch"
After
gh api graphql -f query='
mutation($id: ID!) {
updatePullRequestBranch(input: { pullRequestId: $id, updateMethod: REBASE }) {
pullRequest { number headRefOid }
}
}
' -f id="$nodeid"
```
Other changes:
Test plan
Notes