summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Duncalfe <lduncalfe@gitlab.com>2019-04-05 13:22:58 +0000
committerLuke Duncalfe <lduncalfe@eml.cc>2019-04-09 10:03:26 +1200
commit68f189ad23d7a384f40caa152d263fdf1465b30a (patch)
tree36f9b0f177b6238c0a730f23134d80c02e79f982
parent1883e320eafa02b332a16eec658f65c4a28def83 (diff)
downloadgitlab-ce-68f189ad23d7a384f40caa152d263fdf1465b30a.tar.gz
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
-rw-r--r--app/services/merge_requests/push_options_handler_service.rb41
-rw-r--r--changelogs/unreleased/53198-git-push-option-merge-when-pipeline-succeeds.yml6
-rw-r--r--doc/user/project/merge_requests/index.md31
-rw-r--r--lib/gitlab/push_options.rb2
-rw-r--r--spec/services/merge_requests/push_options_handler_service_spec.rb82
5 files changed, 149 insertions, 13 deletions
diff --git a/app/services/merge_requests/push_options_handler_service.rb b/app/services/merge_requests/push_options_handler_service.rb
index c810340c636..73b4869cc5d 100644
--- a/app/services/merge_requests/push_options_handler_service.rb
+++ b/app/services/merge_requests/push_options_handler_service.rb
@@ -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)
diff --git a/changelogs/unreleased/53198-git-push-option-merge-when-pipeline-succeeds.yml b/changelogs/unreleased/53198-git-push-option-merge-when-pipeline-succeeds.yml
new file mode 100644
index 00000000000..6fefd05049c
--- /dev/null
+++ b/changelogs/unreleased/53198-git-push-option-merge-when-pipeline-succeeds.yml
@@ -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
diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md
index 678fc3dd196..ba7d05a7ad7 100644
--- a/doc/user/project/merge_requests/index.md
+++ b/doc/user/project/merge_requests/index.md
@@ -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.
diff --git a/lib/gitlab/push_options.rb b/lib/gitlab/push_options.rb
index 7c655c12995..810aba436cc 100644
--- a/lib/gitlab/push_options.rb
+++ b/lib/gitlab/push_options.rb
@@ -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]
diff --git a/spec/services/merge_requests/push_options_handler_service_spec.rb b/spec/services/merge_requests/push_options_handler_service_spec.rb
index 96becfcae26..eafe7a34617 100644
--- a/spec/services/merge_requests/push_options_handler_service_spec.rb
+++ b/spec/services/merge_requests/push_options_handler_service_spec.rb
@@ -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 } }