Support merge on pipeline success w/ push options
MergeRequests::PushOptionsHandlerService has been updated to allow creating and updating merge requests with the `merge_when_pipeline_succeeds` set using git push options. To create a new merge request and set it to merge when the pipeline succeeds: git push -u origin -o merge_request.create \ -o merge_request.merge_when_pipeline_succeeds To update an existing merge request and set it to merge when the pipeline succeeds: git push -u origin -o merge_request.merge_when_pipeline_succeeds Issue https://gitlab.com/gitlab-org/gitlab-ce/issues/53198
This commit is contained in:
parent
1883e320ea
commit
68f189ad23
5 changed files with 149 additions and 13 deletions
|
@ -7,7 +7,7 @@ module MergeRequests
|
|||
LIMIT = 10
|
||||
|
||||
attr_reader :branches, :changes_by_branch, :current_user, :errors,
|
||||
:project, :push_options, :target
|
||||
:project, :push_options
|
||||
|
||||
def initialize(project, current_user, changes, push_options)
|
||||
@project = project
|
||||
|
@ -16,7 +16,6 @@ module MergeRequests
|
|||
@push_options = push_options
|
||||
@errors = []
|
||||
@branches = @changes_by_branch.keys
|
||||
@target = @push_options[:target] || @project.default_branch
|
||||
|
||||
raise Error, 'User is required' if @current_user.nil?
|
||||
|
||||
|
@ -28,8 +27,8 @@ module MergeRequests
|
|||
raise Error, "Too many branches pushed (#{@branches.size} were pushed, limit is #{LIMIT})"
|
||||
end
|
||||
|
||||
if @push_options[:target] && !@project.repository.branch_exists?(@target)
|
||||
raise Error, "Branch #{@target} does not exist"
|
||||
if @push_options[:target] && !@project.repository.branch_exists?(@push_options[:target])
|
||||
raise Error, "Branch #{@push_options[:target]} does not exist"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -93,12 +92,10 @@ module MergeRequests
|
|||
end
|
||||
|
||||
def update!(merge_request)
|
||||
return if target == merge_request.target_branch
|
||||
|
||||
merge_request = ::MergeRequests::UpdateService.new(
|
||||
project,
|
||||
current_user,
|
||||
{ target_branch: target }
|
||||
update_params
|
||||
).execute(merge_request)
|
||||
|
||||
collect_errors_from_merge_request(merge_request) unless merge_request.valid?
|
||||
|
@ -111,13 +108,39 @@ module MergeRequests
|
|||
commits = CommitCollection.new(project, commits)
|
||||
commit = commits.without_merge_commits.first
|
||||
|
||||
{
|
||||
params = {
|
||||
assignee: current_user,
|
||||
source_branch: branch,
|
||||
target_branch: target,
|
||||
target_branch: push_options[:target] || project.default_branch,
|
||||
title: commit&.title&.strip || 'New Merge Request',
|
||||
description: commit&.description&.strip
|
||||
}
|
||||
|
||||
if push_options.key?(:merge_when_pipeline_succeeds)
|
||||
params.merge!(
|
||||
merge_when_pipeline_succeeds: push_options[:merge_when_pipeline_succeeds],
|
||||
merge_user: current_user
|
||||
)
|
||||
end
|
||||
|
||||
params
|
||||
end
|
||||
|
||||
def update_params
|
||||
params = {}
|
||||
|
||||
if push_options.key?(:merge_when_pipeline_succeeds)
|
||||
params.merge!(
|
||||
merge_when_pipeline_succeeds: push_options[:merge_when_pipeline_succeeds],
|
||||
merge_user: current_user
|
||||
)
|
||||
end
|
||||
|
||||
if push_options.key?(:target)
|
||||
params[:target_branch] = push_options[:target]
|
||||
end
|
||||
|
||||
params
|
||||
end
|
||||
|
||||
def collect_errors_from_merge_request(merge_request)
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: Allow merge requests to be set to merge when pipeline succeeds via git push
|
||||
options
|
||||
merge_request: 26842
|
||||
author:
|
||||
type: added
|
|
@ -223,9 +223,17 @@ branch already exists, the patches will be applied on top of it.
|
|||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/26752) in GitLab 11.10.
|
||||
|
||||
GitLab supports using [Git push options](https://git-scm.com/docs/git-push#Documentation/git-push.txt--oltoptiongt) to create merge requests and set the target
|
||||
branch during a push. Note that git push options are only available with
|
||||
Git 2.10 or newer.
|
||||
NOTE: **Note:**
|
||||
Git push options are only available with Git 2.10 or newer.
|
||||
|
||||
GitLab supports using
|
||||
[Git push options](https://git-scm.com/docs/git-push#Documentation/git-push.txt--oltoptiongt)
|
||||
to perform the following actions against merge requests at the same time
|
||||
as pushing changes:
|
||||
|
||||
- Create a new merge request for the pushed branch.
|
||||
- Set the target of the merge request to a particular branch.
|
||||
- Set the merge request to merge when its pipeline succeeds.
|
||||
|
||||
### Create a new merge request using git push options
|
||||
|
||||
|
@ -252,6 +260,23 @@ same time using a `-o` flag per push option:
|
|||
git push -o merge_request.create -o merge_request.target=branch_name
|
||||
```
|
||||
|
||||
### Set merge when pipeline succeeds using git push options
|
||||
|
||||
To set an existing merge request to
|
||||
[merge when its pipeline succeeds](merge_when_pipeline_succeeds.md), use
|
||||
the `merge_request.merge_when_pipeline_succeeds` push option:
|
||||
|
||||
```sh
|
||||
git push -o merge_request.merge_when_pipeline_succeeds
|
||||
```
|
||||
|
||||
You can also create a merge request and set it to merge when its
|
||||
pipeline succeeds at the same time using a `-o` flag per push option:
|
||||
|
||||
```sh
|
||||
git push -o merge_request.create -o merge_request.merge_when_pipeline_succeeds
|
||||
```
|
||||
|
||||
## Find the merge request that introduced a change
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/2383) in GitLab 10.5.
|
||||
|
|
|
@ -4,7 +4,7 @@ module Gitlab
|
|||
class PushOptions
|
||||
VALID_OPTIONS = HashWithIndifferentAccess.new({
|
||||
merge_request: {
|
||||
keys: [:create, :target]
|
||||
keys: [:create, :merge_when_pipeline_succeeds, :target]
|
||||
},
|
||||
ci: {
|
||||
keys: [:skip]
|
||||
|
|
|
@ -66,6 +66,22 @@ describe MergeRequests::PushOptionsHandlerService do
|
|||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'a service that can set the merge request to merge when pipeline succeeds' do
|
||||
subject(:last_mr) { MergeRequest.last }
|
||||
|
||||
it 'sets merge_when_pipeline_succeeds' do
|
||||
service.execute
|
||||
|
||||
expect(last_mr.merge_when_pipeline_succeeds).to eq(true)
|
||||
end
|
||||
|
||||
it 'sets merge_user to the user' do
|
||||
service.execute
|
||||
|
||||
expect(last_mr.merge_user).to eq(user)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'a service that does not create a merge request' do
|
||||
it do
|
||||
expect { service.execute }.not_to change { MergeRequest.count }
|
||||
|
@ -118,6 +134,72 @@ describe MergeRequests::PushOptionsHandlerService do
|
|||
end
|
||||
end
|
||||
|
||||
describe '`merge_when_pipeline_succeeds` push option' do
|
||||
let(:push_options) { { merge_when_pipeline_succeeds: true } }
|
||||
|
||||
context 'with a new branch' do
|
||||
let(:changes) { new_branch_changes }
|
||||
|
||||
it_behaves_like 'a service that does not create a merge request'
|
||||
|
||||
it 'adds an error to the service' do
|
||||
error = "A merge_request.create push option is required to create a merge request for branch #{source_branch}"
|
||||
|
||||
service.execute
|
||||
|
||||
expect(service.errors).to include(error)
|
||||
end
|
||||
|
||||
context 'when coupled with the `create` push option' do
|
||||
let(:push_options) { { create: true, merge_when_pipeline_succeeds: true } }
|
||||
|
||||
it_behaves_like 'a service that can create a merge request'
|
||||
it_behaves_like 'a service that can set the merge request to merge when pipeline succeeds'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with an existing branch but no open MR' do
|
||||
let(:changes) { existing_branch_changes }
|
||||
|
||||
it_behaves_like 'a service that does not create a merge request'
|
||||
|
||||
it 'adds an error to the service' do
|
||||
error = "A merge_request.create push option is required to create a merge request for branch #{source_branch}"
|
||||
|
||||
service.execute
|
||||
|
||||
expect(service.errors).to include(error)
|
||||
end
|
||||
|
||||
context 'when coupled with the `create` push option' do
|
||||
let(:push_options) { { create: true, merge_when_pipeline_succeeds: true } }
|
||||
|
||||
it_behaves_like 'a service that can create a merge request'
|
||||
it_behaves_like 'a service that can set the merge request to merge when pipeline succeeds'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with an existing branch that has a merge request open' do
|
||||
let(:changes) { existing_branch_changes }
|
||||
let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch)}
|
||||
|
||||
it_behaves_like 'a service that does not create a merge request'
|
||||
it_behaves_like 'a service that can set the merge request to merge when pipeline succeeds'
|
||||
end
|
||||
|
||||
context 'with a deleted branch' do
|
||||
let(:changes) { deleted_branch_changes }
|
||||
|
||||
it_behaves_like 'a service that does nothing'
|
||||
end
|
||||
|
||||
context 'with the project default branch' do
|
||||
let(:changes) { default_branch_changes }
|
||||
|
||||
it_behaves_like 'a service that does nothing'
|
||||
end
|
||||
end
|
||||
|
||||
describe '`target` push option' do
|
||||
let(:push_options) { { target: target_branch } }
|
||||
|
||||
|
|
Loading…
Reference in a new issue