Reject auto_merge push option without merge permission
What does this MR do and why?
git push -o merge_request.auto_merge (and the merge_request.merge_when_pipeline_succeeds alias) was accepted from a user who lacks permission to merge the target branch. The auto-merge was recorded with that user as merge_user, and because they cannot merge, the merge request became unmergeable for everyone: a user who does hold merge permission saw "You are not allowed to merge this merge request" with no Merge button, and the MR stayed open until the auto-merge was cancelled.
The cause is in MergeRequests::PushOptionsHandlerService. It sets auto_merge_enabled (an alias for the merge_when_pipeline_succeeds column) directly through BuildService/CreateService. That writes the auto-merge straight onto the record and skips the permission check AutoMergeService applies when auto-merge is enabled through the normal path.
This MR guards the auto-merge push options behind the same check MergeRequest#can_be_merged_by? uses (Gitlab::UserAccess#can_update_branch?). When the pushing user cannot merge the target branch:
- the auto-merge is not recorded, so the merge request is never left in the unmergeable state, and
- an explanatory error is added, which surfaces on the git
remote:channel naming the project, branch, and missing permission.
This implements the first (and preferred) option from #623038 (closed) — reject the option at push time with a remote: message. The second half of the issue — that detailed_merge_status reports mergeable while merge_error holds a permission refusal — lives in the mergeability-status code and is better addressed as a separate follow-up.
Related to #623038 (closed).
Behavior
Before: git push -o merge_request.auto_merge from a Developer against a target branch that only Maintainers may merge → the auto-merge is recorded silently and the MR is stuck unmergeable.
After: the same push does not enable auto-merge and prints a line such as:
remote: merge_request.auto_merge was not applied: you do not have permission to merge into group/project:mainThe branch push itself still succeeds, and when combined with merge_request.create the merge request is still created — only the auto-merge is withheld.
How to set up and validate locally
- Protect a project's default branch with "Allowed to merge" set to Maintainers (so the Developer role is excluded).
- As a Developer, run
git push -o merge_request.create -o merge_request.auto_merge. - Confirm the merge request is created, auto-merge is not enabled, and the
remote:output names the branch and the missing permission.
Specs:
bin/rspec spec/services/merge_requests/push_options_handler_service_spec.rb