Skip to content

feat(pull-requests): say why a merge was refused, and let an administrator merge anyway - #38

Merged
yordis merged 5 commits into
mainfrom
yordis/feat-merge-refusal-reason-and-bypass
Aug 22, 2026
Merged

feat(pull-requests): say why a merge was refused, and let an administrator merge anyway#38
yordis merged 5 commits into
mainfrom
yordis/feat-merge-refusal-reason-and-bypass

Conversation

@yordis

@yordis yordis commented Aug 22, 2026

Copy link
Copy Markdown
Member
  • A pull request the base branch's rules hold back, a branch that conflicts, and a pull request somebody already merged all arrived as the same generic hint about write access. The host's own explanation was reaching the server and being dropped before the toast, so the one refusal a reader can act on told them nothing, and the suggested remedy was usually the wrong one.
  • Someone who administers a repository already has the authority to merge past its rules, and had to leave the app for a terminal to do it. Offering it in the app, behind its own confirmation and only where the host and the account both allow it, keeps that work where the rest of it happens.
  • Explaining the refusal without offering the way out is still a dead end: the reader is told no, and the one thing that gets them past it sits in a menu they have no reason to open at that point. Carrying the refusal as a kind rather than only as prose is what lets the page tell the refusal an administrator can stand down from the ones nobody can, and ask right there.
  • The parts are one change on purpose: the override is hard to justify to a reader who was never told what stopped the merge in the first place, and its own failure needs the same wording to be worth showing.

yordis added 3 commits August 22, 2026 15:45
…rator merge anyway

A pull request held back by its base branch's rules is a normal end to a day's
work, and the host's own explanation was being dropped one layer below the
toast. Every refusal read as the same guess about write access, which leaves
the reader pressing the same button again.

Someone who administers the repository already has the authority to merge past
those rules, and had to leave the app for a terminal to use it.

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
@cursor

cursor Bot commented Aug 22, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches merge execution and admin-only rule bypass, which is permission-sensitive, but the override is gated on host capability plus ADMIN (not MAINTAIN) and is refused for auto-merge and other actions.

Overview
Failed GitHub merges no longer collapse into a generic “check write access” toast. gh stderr is classified into merge-blocked, merge-conflict, and already-merged, and that kind travels with the error so the client can act on it instead of matching prose.

Repository admins can merge past branch rules. GitHub reports mergeBypass only for ADMIN (not MAINTAIN or write). The service accepts bypassRules only for a live merge when both the host and the viewer allow it, and the CLI then passes --admin. Auto-merge cannot bypass, because it waits on those same rules.

On the detail panel, admins get a destructive “merge past branch rules” menu item behind its own confirmation. A merge-blocked failure for someone who may bypass opens that dialog instead of a toast; conflicts, already-merged PRs, and a refused bypass stay toasts. Other hosts keep saying nothing and offering nothing.

Reviewed by Cursor Bugbot for commit 831ea8b. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L labels Aug 22, 2026
@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@yordis, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 46 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 92581995-9707-41a4-bb57-00160762b9dd

📥 Commits

Reviewing files that changed from the base of the PR and between 70a5a60 and 831ea8b.

📒 Files selected for processing (21)
  • apps/server/src/pullRequest/GitHubPullRequestCli.test.ts
  • apps/server/src/pullRequest/GitHubPullRequestCli.ts
  • apps/server/src/pullRequest/GitHubPullRequestProvider.test.ts
  • apps/server/src/pullRequest/GitHubPullRequestProvider.ts
  • apps/server/src/pullRequest/PullRequestProvider.ts
  • apps/server/src/pullRequest/PullRequestService.test.ts
  • apps/server/src/pullRequest/PullRequestService.ts
  • apps/server/src/pullRequest/gitHubPullRequestJson.test.ts
  • apps/server/src/pullRequest/gitHubPullRequestJson.ts
  • apps/server/src/sourceControl/GitHubCli.test.ts
  • apps/server/src/sourceControl/GitHubCli.ts
  • apps/server/src/sourceControl/GitLabCli.ts
  • apps/server/src/vcs/VcsProcess.test.ts
  • apps/server/src/vcs/VcsProcess.ts
  • apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx
  • apps/web/src/components/pullRequest/pullRequestDetail.logic.test.ts
  • apps/web/src/components/pullRequest/pullRequestDetail.logic.ts
  • docs/fork/0024-a-refused-merge-says-why.md
  • docs/fork/README.md
  • packages/contracts/src/pullRequest.ts
  • packages/contracts/src/vcs.ts
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch yordis/feat-merge-refusal-reason-and-bypass

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

yordis added 2 commits August 22, 2026 15:59
A sentence explaining that the branch's rules forbid the merge is a dead end: the reader is told no and left to find the way out on their own, in a menu they have no reason to open. The refusal now travels as a kind rather than only as prose, so the page can tell the one refusal an administrator can override from the ones nobody can, and ask.

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
@yordis
yordis merged commit 656ac24 into main Aug 22, 2026
11 of 20 checks passed
@yordis
yordis deleted the yordis/feat-merge-refusal-reason-and-bypass branch August 22, 2026 20:02

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 831ea8b. Configure here.

})
) {
setConfirmation({ open: true, action: "merge-bypass", refusalDetail: description });
return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bypass retry dialog race

High Severity

After a merge is refused, the new bypass path sets confirmation to open the merge-bypass dialog and returns without a toast. The dialog's onOpenChangeComplete still resets confirmation to { open: false, action: "merge" } when the prior close finishes, which can wipe that reopen. When the host answers quickly, the reader gets neither the override dialog nor an error toast.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 831ea8b. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant