Fail loudly when preserve-branch-name collides with existing remote branch#27458
Fail loudly when preserve-branch-name collides with existing remote branch#27458
Conversation
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/e96fa9ed-55e3-405c-9607-653a6964420d Co-authored-by: mrjf <180956+mrjf@users.noreply.github.com>
🧪 Test Quality Sentinel ReportTest Quality Score: 90/100✅ Excellent
Test Classification Details
Flagged Tests — Requires ReviewNo tests require mandatory review. One minor note below. i️
|
There was a problem hiding this comment.
Pull request overview
This PR ensures safe-outputs.create-pull-request.preserve-branch-name: true is no longer silently bypassed when the agent-supplied branch already exists on the remote, by failing loudly with an actionable error instead of auto-renaming the branch.
Changes:
- Update all three remote-branch collision handlers to throw an explicit error when
preserve-branch-nameis enabled. - Document the new fail-loud collision behavior for
preserve-branch-name. - Add regression tests covering fail-loud (flag on) and suffix-append (flag off) behavior.
Show a summary per file
| File | Description |
|---|---|
| actions/setup/js/create_pull_request.cjs | Throws an explicit error on remote-branch collisions when preserve-branch-name is enabled; otherwise retains suffix-append behavior. |
| actions/setup/js/create_pull_request.test.cjs | Adds tests validating the new fail-loud path and the existing default collision-avoidance behavior. |
| docs/src/content/docs/reference/safe-outputs-pull-requests.md | Documents that collisions now fail explicitly when preserve-branch-name: true. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 3/3 changed files
- Comments generated: 2
| throw new Error( | ||
| `Remote branch "${branchName}" already exists and preserve-branch-name is enabled. ` + | ||
| `Refusing to silently rename the branch. Either delete the remote branch, choose a different ` + | ||
| `branch name, or disable preserve-branch-name to allow a random suffix to be appended.` | ||
| ); |
There was a problem hiding this comment.
The actionable collision error message is duplicated verbatim in three separate remote-branch collision blocks (bundle push, patch push, and allow-empty push). To reduce drift risk and make future edits safer, consider extracting this message into a small helper (e.g., makePreserveBranchNameCollisionError(branchName)) or a shared constant.
| if (preserveBranchName) { | ||
| throw new Error( | ||
| `Remote branch "${branchName}" already exists and preserve-branch-name is enabled. ` + | ||
| `Refusing to silently rename the branch. Either delete the remote branch, choose a different ` + | ||
| `branch name, or disable preserve-branch-name to allow a random suffix to be appended.` |
There was a problem hiding this comment.
In the allow-empty (empty patch) push path, this new throw ends up in the catch (pushError) that returns { success: false, error } without error_type: "push_failed" and without honoring fallback-as-issue (unlike the bundle and patch paths). If callers rely on error_type/fallback consistency (and per the PR description), consider mapping this failure to the same push_failed structure and/or using the same fallback-as-issue behavior here.
|
@copilot review all comments |
…y push failure Agent-Logs-Url: https://github.com/github/gh-aw/sessions/fab5372a-c934-4afd-bef1-c41d44e169ff Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Addressed both reviewer comments in 65bfa28:
All 63 tests in |
safe-outputs.create-pull-request.preserve-branch-name: truewas silently bypassed whenever the agent-supplied branch already existed on the remote: the collision handler unconditionally appended an 8-char hex salt, defeating the flag's purpose and producing a growing pile of disconnected PRs for long-running branches.Root cause: three identical
remoteBranchExistsblocks inactions/setup/js/create_pull_request.cjs(signed-commits, patch-apply, empty-commit paths) did not consultpreserveBranchName.Changes
actions/setup/js/create_pull_request.cjs: extract remote-branch-collision handling into a sharedhandleRemoteBranchCollision(branchName, preserveBranchName)helper used by all three push paths (signed-commits, patch-apply, allow-empty). WhenpreserveBranchNameis true and the remote branch already exists, the helper throws an actionable error naming the branch and pointing at the three remediation paths (delete the remote branch, rename, or disable the flag). Otherwise it preserves the existing behavior of renaming the local branch with a random hex suffix. The surroundingtry/catchpropagates this as apush_failedresult, optionally honoringfallback-as-issue.Allow-empty push-failure consistency: the
catch (pushError)in the allow-empty empty-branch push path now returnserror_type: "push_failed", matching the signed-commits and patch-apply paths so callers see a consistent error shape across all three push paths.docs/src/content/docs/reference/safe-outputs-pull-requests.md: document the fail-loud collision behavior alongside the existingpreserve-branch-namedescription.actions/setup/js/create_pull_request.test.cjs: two regression tests — one asserting the new fail-loud path emits the expected error and does not warn about appending a suffix; one confirming the default (flag off) path still appends a random suffix.Notes for reviewers
basewould require either a force-push (history loss) or a fetch-and-rebase flow — both materially larger than the surgical fix and arguably their own feature (closer topush-to-pull-request-branch).