Commit 7880a300 authored by Jeroen Jacobs's avatar Jeroen Jacobs

Allows MR authors to have the source branch removed when merging the MR

parent f26389a0
...@@ -65,6 +65,7 @@ v 8.8.0 (unreleased) ...@@ -65,6 +65,7 @@ v 8.8.0 (unreleased)
- All Grape API helpers are now instrumented - All Grape API helpers are now instrumented
- Improve Issue formatting for the Slack Service (Jeroen van Baarsen) - Improve Issue formatting for the Slack Service (Jeroen van Baarsen)
- Fixed advice on invalid permissions on upload path !2948 (Ludovic Perrine) - Fixed advice on invalid permissions on upload path !2948 (Ludovic Perrine)
- Allows MR authors to have the source branch removed when merging the MR. !2801 (Jeroen Jacobs)
v 8.7.6 v 8.7.6
- Fix links on wiki pages for relative url setups. !4131 (Artem Sidorenko) - Fix links on wiki pages for relative url setups. !4131 (Artem Sidorenko)
......
...@@ -334,7 +334,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -334,7 +334,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
params.require(:merge_request).permit( params.require(:merge_request).permit(
:title, :assignee_id, :source_project_id, :source_branch, :title, :assignee_id, :source_project_id, :source_branch,
:target_project_id, :target_branch, :milestone_id, :target_project_id, :target_branch, :milestone_id,
:state_event, :description, :task_num, label_ids: [] :state_event, :description, :task_num, :force_remove_source_branch,
label_ids: []
) )
end end
......
...@@ -286,6 +286,18 @@ class MergeRequest < ActiveRecord::Base ...@@ -286,6 +286,18 @@ class MergeRequest < ActiveRecord::Base
last_commit == source_project.commit(source_branch) last_commit == source_project.commit(source_branch)
end end
def should_remove_source_branch?
merge_params['should_remove_source_branch'].present?
end
def force_remove_source_branch?
merge_params['force_remove_source_branch'].present?
end
def remove_source_branch?
should_remove_source_branch? || force_remove_source_branch?
end
def mr_and_commit_notes def mr_and_commit_notes
# Fetch comments only from last 100 commits # Fetch comments only from last 100 commits
commits_for_notes_limit = 100 commits_for_notes_limit = 100
...@@ -426,7 +438,10 @@ class MergeRequest < ActiveRecord::Base ...@@ -426,7 +438,10 @@ class MergeRequest < ActiveRecord::Base
self.merge_when_build_succeeds = false self.merge_when_build_succeeds = false
self.merge_user = nil self.merge_user = nil
self.merge_params = nil if merge_params
merge_params.delete('should_remove_source_branch')
merge_params.delete('commit_message')
end
self.save self.save
end end
......
...@@ -8,11 +8,14 @@ module MergeRequests ...@@ -8,11 +8,14 @@ module MergeRequests
@project = Project.find(params[:target_project_id]) if params[:target_project_id] @project = Project.find(params[:target_project_id]) if params[:target_project_id]
filter_params filter_params
label_params = params[:label_ids] label_params = params.delete(:label_ids)
merge_request = MergeRequest.new(params.except(:label_ids)) force_remove_source_branch = params.delete(:force_remove_source_branch)
merge_request = MergeRequest.new(params)
merge_request.source_project = source_project merge_request.source_project = source_project
merge_request.target_project ||= source_project merge_request.target_project ||= source_project
merge_request.author = current_user merge_request.author = current_user
merge_request.merge_params['force_remove_source_branch'] = force_remove_source_branch
if merge_request.save if merge_request.save
merge_request.update_attributes(label_ids: label_params) merge_request.update_attributes(label_ids: label_params)
......
...@@ -45,10 +45,14 @@ module MergeRequests ...@@ -45,10 +45,14 @@ module MergeRequests
def after_merge def after_merge
MergeRequests::PostMergeService.new(project, current_user).execute(merge_request) MergeRequests::PostMergeService.new(project, current_user).execute(merge_request)
if params[:should_remove_source_branch].present? if params[:should_remove_source_branch].present? || @merge_request.force_remove_source_branch?
DeleteBranchService.new(@merge_request.source_project, current_user). DeleteBranchService.new(@merge_request.source_project, branch_deletion_user).
execute(merge_request.source_branch) execute(merge_request.source_branch)
end end
end end
def branch_deletion_user
@merge_request.force_remove_source_branch? ? @merge_request.author : current_user
end
end end
end end
...@@ -11,6 +11,8 @@ module MergeRequests ...@@ -11,6 +11,8 @@ module MergeRequests
params.except!(:target_project_id) params.except!(:target_project_id)
params.except!(:source_branch) params.except!(:source_branch)
merge_request.merge_params['force_remove_source_branch'] = params.delete(:force_remove_source_branch)
update(merge_request) update(merge_request)
end end
......
...@@ -25,7 +25,10 @@ ...@@ -25,7 +25,10 @@
- else - else
= f.button class: "btn btn-create btn-grouped js-merge-button accept_merge_request #{status_class}" do = f.button class: "btn btn-create btn-grouped js-merge-button accept_merge_request #{status_class}" do
Accept Merge Request Accept Merge Request
- if @merge_request.can_remove_source_branch?(current_user) - if @merge_request.force_remove_source_branch?
.accept-control
The source branch will be removed.
- elsif @merge_request.can_remove_source_branch?(current_user)
.accept-control.checkbox .accept-control.checkbox
= label_tag :should_remove_source_branch, class: "remove_source_checkbox" do = label_tag :should_remove_source_branch, class: "remove_source_checkbox" do
= check_box_tag :should_remove_source_branch = check_box_tag :should_remove_source_branch
......
...@@ -2,17 +2,16 @@ ...@@ -2,17 +2,16 @@
Set by #{link_to_member(@project, @merge_request.merge_user, avatar: true)} Set by #{link_to_member(@project, @merge_request.merge_user, avatar: true)}
to be merged automatically when the build succeeds. to be merged automatically when the build succeeds.
%div %div
- should_remove_source_branch = @merge_request.merge_params["should_remove_source_branch"].present?
%p %p
= succeed '.' do = succeed '.' do
The changes will be merged into The changes will be merged into
%span.label-branch= @merge_request.target_branch %span.label-branch= @merge_request.target_branch
- if should_remove_source_branch - if @merge_request.remove_source_branch?
The source branch will be removed. The source branch will be removed.
- else - else
The source branch will not be removed. The source branch will not be removed.
- remove_source_branch_button = @merge_request.can_remove_source_branch?(current_user) && !should_remove_source_branch && @merge_request.merge_user == current_user - remove_source_branch_button = !@merge_request.remove_source_branch? && @merge_request.can_remove_source_branch?(current_user) && @merge_request.merge_user == current_user
- user_can_cancel_automatic_merge = @merge_request.can_cancel_merge_when_build_succeeds?(current_user) - user_can_cancel_automatic_merge = @merge_request.can_cancel_merge_when_build_succeeds?(current_user)
- if remove_source_branch_button || user_can_cancel_automatic_merge - if remove_source_branch_button || user_can_cancel_automatic_merge
.clearfix.prepend-top-10 .clearfix.prepend-top-10
......
%h4 %h4
Ready to be merged automatically Ready to be merged automatically
%p %p
Ask someone with write access to this repository to merge this request. Ask someone with write access to this repository to merge this request.
- if @merge_request.force_remove_source_branch?
The source branch will be removed.
...@@ -114,6 +114,13 @@ ...@@ -114,6 +114,13 @@
- if @merge_request.new_record? - if @merge_request.new_record?
&nbsp; &nbsp;
= link_to 'Change branches', mr_change_branches_path(@merge_request) = link_to 'Change branches', mr_change_branches_path(@merge_request)
- if @merge_request.can_remove_source_branch?(current_user)
.form-group
.col-sm-10.col-sm-offset-2
.checkbox
= label_tag 'merge_request[force_remove_source_branch]' do
= check_box_tag 'merge_request[force_remove_source_branch]', '1', @merge_request.force_remove_source_branch?
Remove source branch when merge request is accepted.
- is_footer = !(issuable.is_a?(MergeRequest) && issuable.new_record?) - is_footer = !(issuable.is_a?(MergeRequest) && issuable.new_record?)
.row-content-block{class: (is_footer ? "footer-block" : "middle-block")} .row-content-block{class: (is_footer ? "footer-block" : "middle-block")}
......
...@@ -260,13 +260,18 @@ describe MergeRequest, models: true do ...@@ -260,13 +260,18 @@ describe MergeRequest, models: true do
end end
describe "#reset_merge_when_build_succeeds" do describe "#reset_merge_when_build_succeeds" do
let(:merge_if_green) { create :merge_request, merge_when_build_succeeds: true, merge_user: create(:user) } let(:merge_if_green) do
create :merge_request, merge_when_build_succeeds: true, merge_user: create(:user),
merge_params: { "should_remove_source_branch" => "1", "commit_message" => "msg" }
end
it "sets the item to false" do it "sets the item to false" do
merge_if_green.reset_merge_when_build_succeeds merge_if_green.reset_merge_when_build_succeeds
merge_if_green.reload merge_if_green.reload
expect(merge_if_green.merge_when_build_succeeds).to be_falsey expect(merge_if_green.merge_when_build_succeeds).to be_falsey
expect(merge_if_green.merge_params["should_remove_source_branch"]).to be_nil
expect(merge_if_green.merge_params["commit_message"]).to be_nil
end end
end end
......
...@@ -12,7 +12,8 @@ describe MergeRequests::CreateService, services: true do ...@@ -12,7 +12,8 @@ describe MergeRequests::CreateService, services: true do
title: 'Awesome merge_request', title: 'Awesome merge_request',
description: 'please fix', description: 'please fix',
source_branch: 'feature', source_branch: 'feature',
target_branch: 'master' target_branch: 'master',
force_remove_source_branch: '1'
} }
end end
...@@ -29,6 +30,7 @@ describe MergeRequests::CreateService, services: true do ...@@ -29,6 +30,7 @@ describe MergeRequests::CreateService, services: true do
it { expect(@merge_request).to be_valid } it { expect(@merge_request).to be_valid }
it { expect(@merge_request.title).to eq('Awesome merge_request') } it { expect(@merge_request.title).to eq('Awesome merge_request') }
it { expect(@merge_request.assignee).to be_nil } it { expect(@merge_request.assignee).to be_nil }
it { expect(@merge_request.merge_params['force_remove_source_branch']).to eq('1') }
it 'should execute hooks with default action' do it 'should execute hooks with default action' do
expect(service).to have_received(:execute_hooks).with(@merge_request) expect(service).to have_received(:execute_hooks).with(@merge_request)
......
...@@ -38,6 +38,21 @@ describe MergeRequests::MergeService, services: true do ...@@ -38,6 +38,21 @@ describe MergeRequests::MergeService, services: true do
end end
end end
context 'remove source branch by author' do
let(:service) do
merge_request.merge_params['force_remove_source_branch'] = '1'
merge_request.save!
MergeRequests::MergeService.new(project, user, commit_message: 'Awesome message')
end
it 'removes the source branch' do
expect(DeleteBranchService).to receive(:new).
with(merge_request.source_project, merge_request.author).
and_call_original
service.execute(merge_request)
end
end
context "error handling" do context "error handling" do
let(:service) { MergeRequests::MergeService.new(project, user, commit_message: 'Awesome message') } let(:service) { MergeRequests::MergeService.new(project, user, commit_message: 'Awesome message') }
......
...@@ -39,7 +39,8 @@ describe MergeRequests::UpdateService, services: true do ...@@ -39,7 +39,8 @@ describe MergeRequests::UpdateService, services: true do
assignee_id: user2.id, assignee_id: user2.id,
state_event: 'close', state_event: 'close',
label_ids: [label.id], label_ids: [label.id],
target_branch: 'target' target_branch: 'target',
force_remove_source_branch: '1'
} }
end end
...@@ -61,6 +62,7 @@ describe MergeRequests::UpdateService, services: true do ...@@ -61,6 +62,7 @@ describe MergeRequests::UpdateService, services: true do
it { expect(@merge_request.labels.count).to eq(1) } it { expect(@merge_request.labels.count).to eq(1) }
it { expect(@merge_request.labels.first.title).to eq(label.name) } it { expect(@merge_request.labels.first.title).to eq(label.name) }
it { expect(@merge_request.target_branch).to eq('target') } it { expect(@merge_request.target_branch).to eq('target') }
it { expect(@merge_request.merge_params['force_remove_source_branch']).to eq('1') }
it 'should execute hooks with update action' do it 'should execute hooks with update action' do
expect(service).to have_received(:execute_hooks). expect(service).to have_received(:execute_hooks).
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment