Merge branch '40085-add-a-create_merge_request-quick-action' into 'master'
Resolve "Add a `/create_merge_request` quick action" Closes #40085 See merge request gitlab-org/gitlab-ce!22485
This commit is contained in:
commit
5cd0e7d29f
11 changed files with 182 additions and 6 deletions
|
@ -11,6 +11,12 @@ module Issues
|
|||
move_issue_to_new_project(issue) || update(issue)
|
||||
end
|
||||
|
||||
def update(issue)
|
||||
create_merge_request_from_quick_action
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def before_update(issue)
|
||||
spam_check(issue, current_user)
|
||||
end
|
||||
|
@ -93,6 +99,13 @@ module Issues
|
|||
|
||||
private
|
||||
|
||||
def create_merge_request_from_quick_action
|
||||
create_merge_request_params = params.delete(:create_merge_request)
|
||||
return unless create_merge_request_params
|
||||
|
||||
MergeRequests::CreateFromIssueService.new(project, current_user, create_merge_request_params).execute
|
||||
end
|
||||
|
||||
def handle_milestone_change(issue)
|
||||
return if skip_milestone_email
|
||||
|
||||
|
|
|
@ -19,13 +19,15 @@ module MergeRequests
|
|||
result = CreateBranchService.new(project, current_user).execute(branch_name, ref)
|
||||
return result if result[:status] == :error
|
||||
|
||||
SystemNoteService.new_issue_branch(issue, project, current_user, branch_name)
|
||||
|
||||
new_merge_request = create(merge_request)
|
||||
|
||||
if new_merge_request.valid?
|
||||
SystemNoteService.new_merge_request(issue, project, current_user, new_merge_request)
|
||||
|
||||
success(new_merge_request)
|
||||
else
|
||||
SystemNoteService.new_issue_branch(issue, project, current_user, branch_name)
|
||||
|
||||
error(new_merge_request.errors)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -635,6 +635,22 @@ module QuickActions
|
|||
@updates[:tag_message] = message
|
||||
end
|
||||
|
||||
desc 'Create a merge request.'
|
||||
explanation do |branch_name = nil|
|
||||
branch_text = branch_name ? "branch '#{branch_name}'" : 'a branch'
|
||||
"Creates #{branch_text} and a merge request to resolve this issue"
|
||||
end
|
||||
params "<branch name>"
|
||||
condition do
|
||||
issuable.is_a?(Issue) && current_user.can?(:create_merge_request_in, project) && current_user.can?(:push_code, project)
|
||||
end
|
||||
command :create_merge_request do |branch_name = nil|
|
||||
@updates[:create_merge_request] = {
|
||||
branch_name: branch_name,
|
||||
issue_iid: issuable.iid
|
||||
}
|
||||
end
|
||||
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
def extract_users(params)
|
||||
return [] if params.nil?
|
||||
|
|
|
@ -407,11 +407,17 @@ module SystemNoteService
|
|||
def new_issue_branch(issue, project, author, branch)
|
||||
link = url_helpers.project_compare_url(project, from: project.default_branch, to: branch)
|
||||
|
||||
body = "created branch [`#{branch}`](#{link})"
|
||||
body = "created branch [`#{branch}`](#{link}) to address this issue"
|
||||
|
||||
create_note(NoteSummary.new(issue, project, author, body, action: 'branch'))
|
||||
end
|
||||
|
||||
def new_merge_request(issue, project, author, merge_request)
|
||||
body = "created merge request #{merge_request.to_reference} to address this issue"
|
||||
|
||||
create_note(NoteSummary.new(issue, project, author, body, action: 'merge'))
|
||||
end
|
||||
|
||||
# Called when a Mentionable references a Noteable
|
||||
#
|
||||
# noteable - Noteable object being referenced
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Creates /create_merge_request quickaction
|
||||
merge_request: 22485
|
||||
author: Jacopo Beschi @jacopo-beschi
|
||||
type: added
|
|
@ -53,6 +53,7 @@ discussions, and descriptions:
|
|||
| `/target_branch <Local branch Name>` | Set target branch | | ✓ |
|
||||
| `/wip` | Toggle the Work In Progress status | | ✓ |
|
||||
| `/merge` | Merge (when pipeline succeeds) | | ✓ |
|
||||
| `/create_merge_request <branch name>` | Create a new merge request starting from the current issue | ✓ | |
|
||||
|
||||
|
||||
## Quick actions for commit messages
|
||||
|
|
|
@ -76,7 +76,7 @@ describe 'User creates branch and merge request on issue page', :js do
|
|||
|
||||
visit project_issue_path(project, issue)
|
||||
|
||||
expect(page).to have_content('created branch 1-cherry-coloured-funk')
|
||||
expect(page).to have_content("created merge request !1 to address this issue")
|
||||
expect(page).to have_content('mentioned in merge request !1')
|
||||
end
|
||||
|
||||
|
@ -106,7 +106,7 @@ describe 'User creates branch and merge request on issue page', :js do
|
|||
|
||||
visit project_issue_path(project, issue)
|
||||
|
||||
expect(page).to have_content('created branch custom-branch-name')
|
||||
expect(page).to have_content("created merge request !1 to address this issue")
|
||||
expect(page).to have_content('mentioned in merge request !1')
|
||||
end
|
||||
|
||||
|
|
|
@ -303,5 +303,63 @@ describe 'Issues > User uses quick actions', :js do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'create a merge request starting from an issue' do
|
||||
let(:project) { create(:project, :public, :repository) }
|
||||
let(:issue) { create(:issue, project: project) }
|
||||
|
||||
def expect_mr_quickaction(success)
|
||||
expect(page).to have_content 'Commands applied'
|
||||
|
||||
if success
|
||||
expect(page).to have_content 'created merge request'
|
||||
else
|
||||
expect(page).not_to have_content 'created merge request'
|
||||
end
|
||||
end
|
||||
|
||||
it "doesn't create a merge request when the branch name is invalid" do
|
||||
add_note("/create_merge_request invalid branch name")
|
||||
|
||||
wait_for_requests
|
||||
|
||||
expect_mr_quickaction(false)
|
||||
end
|
||||
|
||||
it "doesn't create a merge request when a branch with that name already exists" do
|
||||
add_note("/create_merge_request feature")
|
||||
|
||||
wait_for_requests
|
||||
|
||||
expect_mr_quickaction(false)
|
||||
end
|
||||
|
||||
it 'creates a new merge request using issue iid and title as branch name when the branch name is empty' do
|
||||
add_note("/create_merge_request")
|
||||
|
||||
wait_for_requests
|
||||
|
||||
expect_mr_quickaction(true)
|
||||
|
||||
created_mr = project.merge_requests.last
|
||||
expect(created_mr.source_branch).to eq(issue.to_branch_name)
|
||||
|
||||
visit project_merge_request_path(project, created_mr)
|
||||
expect(page).to have_content %{WIP: Resolve "#{issue.title}"}
|
||||
end
|
||||
|
||||
it 'creates a merge request using the given branch name' do
|
||||
branch_name = '1-feature'
|
||||
add_note("/create_merge_request #{branch_name}")
|
||||
|
||||
expect_mr_quickaction(true)
|
||||
|
||||
created_mr = project.merge_requests.last
|
||||
expect(created_mr.source_branch).to eq(branch_name)
|
||||
|
||||
visit project_merge_request_path(project, created_mr)
|
||||
expect(page).to have_content %{WIP: Resolve "#{issue.title}"}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -61,7 +61,15 @@ describe MergeRequests::CreateFromIssueService do
|
|||
expect(project.repository.branch_exists?(custom_source_branch)).to be_truthy
|
||||
end
|
||||
|
||||
it 'creates a system note' do
|
||||
it 'creates the new_merge_request system note' do
|
||||
expect(SystemNoteService).to receive(:new_merge_request).with(issue, project, user, instance_of(MergeRequest))
|
||||
|
||||
service.execute
|
||||
end
|
||||
|
||||
it 'creates the new_issue_branch system note when the branch could be created but the merge_request cannot be created' do
|
||||
project.project_feature.update!(merge_requests_access_level: ProjectFeature::DISABLED)
|
||||
|
||||
expect(SystemNoteService).to receive(:new_issue_branch).with(issue, project, user, issue.to_branch_name)
|
||||
|
||||
service.execute
|
||||
|
|
|
@ -1222,6 +1222,37 @@ describe QuickActions::InterpretService do
|
|||
expect(commands).to be_empty
|
||||
expect(text).to eq("#{described_class::SHRUG}\n/close")
|
||||
end
|
||||
|
||||
context '/create_merge_request command' do
|
||||
let(:branch_name) { '1-feature' }
|
||||
let(:content) { "/create_merge_request #{branch_name}" }
|
||||
let(:issuable) { issue }
|
||||
|
||||
context 'if issuable is not an Issue' do
|
||||
let(:issuable) { merge_request }
|
||||
|
||||
it_behaves_like 'empty command'
|
||||
end
|
||||
|
||||
context "when logged user cannot create_merge_requests in the project" do
|
||||
let(:project) { create(:project, :archived) }
|
||||
|
||||
it_behaves_like 'empty command'
|
||||
end
|
||||
|
||||
context 'when logged user cannot push code to the project' do
|
||||
let(:project) { create(:project, :private) }
|
||||
let(:service) { described_class.new(project, create(:user)) }
|
||||
|
||||
it_behaves_like 'empty command'
|
||||
end
|
||||
|
||||
it 'populates create_merge_request with branch_name and issue iid' do
|
||||
_, updates = service.execute(content, issuable)
|
||||
|
||||
expect(updates).to eq(create_merge_request: { branch_name: branch_name, issue_iid: issuable.iid })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#explain' do
|
||||
|
@ -1473,5 +1504,27 @@ describe QuickActions::InterpretService do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'create a merge request' do
|
||||
context 'with no branch name' do
|
||||
let(:content) { '/create_merge_request' }
|
||||
|
||||
it 'uses the default branch name' do
|
||||
_, explanations = service.explain(content, issue)
|
||||
|
||||
expect(explanations).to eq(['Creates a branch and a merge request to resolve this issue'])
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a branch name' do
|
||||
let(:content) { '/create_merge_request foo' }
|
||||
|
||||
it 'uses the given branch name' do
|
||||
_, explanations = service.explain(content, issue)
|
||||
|
||||
expect(explanations).to eq(["Creates branch 'foo' and a merge request to resolve this issue"])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -432,6 +432,20 @@ describe SystemNoteService do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.new_merge_request' do
|
||||
subject { described_class.new_merge_request(noteable, project, author, merge_request) }
|
||||
|
||||
let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
|
||||
|
||||
it_behaves_like 'a system note' do
|
||||
let(:action) { 'merge' }
|
||||
end
|
||||
|
||||
it 'sets the new merge request note text' do
|
||||
expect(subject.note).to eq("created merge request #{merge_request.to_reference} to address this issue")
|
||||
end
|
||||
end
|
||||
|
||||
describe '.cross_reference' do
|
||||
subject { described_class.cross_reference(noteable, mentioner, author) }
|
||||
|
||||
|
|
Loading…
Reference in a new issue