Commit 79127877 authored by Jan Provaznik's avatar Jan Provaznik

Merge branch '297011-add-additional-aliases-for-reviewer-quick-commands' into 'master'

Resolve "Add additional aliases for reviewer quick commands"

See merge request gitlab-org/gitlab!51384
parents 5229a766 b6cc96d0
---
title: Adding /reviewer and /remove_reviewer aliases and specs
merge_request: 51384
author:
type: added
...@@ -163,16 +163,17 @@ module Gitlab ...@@ -163,16 +163,17 @@ module Gitlab
end end
end end
explanation do |users| explanation do |users|
reviewers = reviewers_to_add(users)
_('Assigns %{reviewer_users_sentence} as %{reviewer_text}.') % { reviewer_users_sentence: reviewer_users_sentence(users), _('Assigns %{reviewer_users_sentence} as %{reviewer_text}.') % { reviewer_users_sentence: reviewer_users_sentence(users),
reviewer_text: 'reviewer'.pluralize(users.size) } reviewer_text: 'reviewer'.pluralize(reviewers.size) }
end end
execution_message do |users = nil| execution_message do |users = nil|
if users.blank? reviewers = reviewers_to_add(users)
if reviewers.blank?
_("Failed to assign a reviewer because no user was found.") _("Failed to assign a reviewer because no user was found.")
else else
users = [users.first] unless quick_action_target.allows_multiple_reviewers?
_('Assigned %{reviewer_users_sentence} as %{reviewer_text}.') % { reviewer_users_sentence: reviewer_users_sentence(users), _('Assigned %{reviewer_users_sentence} as %{reviewer_text}.') % { reviewer_users_sentence: reviewer_users_sentence(users),
reviewer_text: 'reviewer'.pluralize(users.size) } reviewer_text: 'reviewer'.pluralize(reviewers.size) }
end end
end end
params do params do
...@@ -186,7 +187,7 @@ module Gitlab ...@@ -186,7 +187,7 @@ module Gitlab
parse_params do |reviewer_param| parse_params do |reviewer_param|
extract_users(reviewer_param) extract_users(reviewer_param)
end end
command :assign_reviewer do |users| command :assign_reviewer, :reviewer do |users|
next if users.empty? next if users.empty?
if quick_action_target.allows_multiple_reviewers? if quick_action_target.allows_multiple_reviewers?
...@@ -228,7 +229,7 @@ module Gitlab ...@@ -228,7 +229,7 @@ module Gitlab
# When multiple users are assigned, all will be unassigned if multiple reviewers are no longer allowed # When multiple users are assigned, all will be unassigned if multiple reviewers are no longer allowed
extract_users(unassign_reviewer_param) if quick_action_target.allows_multiple_reviewers? extract_users(unassign_reviewer_param) if quick_action_target.allows_multiple_reviewers?
end end
command :unassign_reviewer do |users = nil| command :unassign_reviewer, :remove_reviewer do |users = nil|
if quick_action_target.allows_multiple_reviewers? && users&.any? if quick_action_target.allows_multiple_reviewers? && users&.any?
@updates[:reviewer_ids] ||= quick_action_target.reviewers.map(&:id) @updates[:reviewer_ids] ||= quick_action_target.reviewers.map(&:id)
@updates[:reviewer_ids] -= users.map(&:id) @updates[:reviewer_ids] -= users.map(&:id)
...@@ -239,11 +240,7 @@ module Gitlab ...@@ -239,11 +240,7 @@ module Gitlab
end end
def reviewer_users_sentence(users) def reviewer_users_sentence(users)
if quick_action_target.allows_multiple_reviewers? reviewers_to_add(users).map(&:to_reference).to_sentence
users
else
[users.first]
end.map(&:to_reference).to_sentence
end end
def reviewers_for_removal(users) def reviewers_for_removal(users)
...@@ -255,6 +252,16 @@ module Gitlab ...@@ -255,6 +252,16 @@ module Gitlab
end end
end end
def reviewers_to_add(users)
return if users.blank?
if quick_action_target.allows_multiple_reviewers?
users
else
[users.first]
end
end
def merge_orchestration_service def merge_orchestration_service
@merge_orchestration_service ||= MergeRequests::MergeOrchestrationService.new(project, current_user) @merge_orchestration_service ||= MergeRequests::MergeOrchestrationService.new(project, current_user)
end end
......
...@@ -669,15 +669,19 @@ RSpec.describe QuickActions::InterpretService do ...@@ -669,15 +669,19 @@ RSpec.describe QuickActions::InterpretService do
shared_examples 'assign_reviewer command' do shared_examples 'assign_reviewer command' do
it 'assigns a reviewer to a single user' do it 'assigns a reviewer to a single user' do
_, updates, _ = service.execute(content, issuable) _, updates, message = service.execute(content, issuable)
expect(updates).to eq(reviewer_ids: [developer.id]) expect(updates).to eq(reviewer_ids: [developer.id])
expect(message).to eq("Assigned #{developer.to_reference} as reviewer.")
end end
end
it 'returns the assign reviewer message' do shared_examples 'unassign_reviewer command' do
_, _, message = service.execute(content, issuable) it 'removes a single reviewer' do
_, updates, message = service.execute(content, issuable)
expect(message).to eq("Assigned #{developer.to_reference} as reviewer.") expect(updates).to eq(reviewer_ids: [])
expect(message).to eq("Removed reviewer #{developer.to_reference}.")
end end
end end
...@@ -876,85 +880,117 @@ RSpec.describe QuickActions::InterpretService do ...@@ -876,85 +880,117 @@ RSpec.describe QuickActions::InterpretService do
end end
context 'when the merge_request_reviewers flag is enabled' do context 'when the merge_request_reviewers flag is enabled' do
context 'assign_reviewer command with one user' do describe 'assign_reviewer command' do
it_behaves_like 'assign_reviewer command' do let(:content) { "/assign_reviewer @#{developer.username}" }
let(:content) { "/assign_reviewer @#{developer.username}" } let(:issuable) { merge_request }
let(:issuable) { merge_request }
context 'with one user' do
it_behaves_like 'assign_reviewer command'
end end
it_behaves_like 'empty command' do context 'with an issue instead of a merge request' do
let(:content) { "/assign_reviewer @#{developer.username}" }
let(:issuable) { issue } let(:issuable) { issue }
it_behaves_like 'empty command'
end end
end
# CE does not have multiple reviewers # CE does not have multiple reviewers
context 'assign_reviewer command with multiple assignees' do context 'assign command with multiple assignees' do
let(:issuable) { merge_request } before do
project.add_developer(developer2)
end
# There's no guarantee that the reference extractor will preserve
# the order of the mentioned users since this is dependent on the
# order in which rows are returned. We just ensure that at least
# one of the mentioned users is assigned.
context 'assigns to one of the two users' do
let(:content) { "/assign_reviewer @#{developer.username} @#{developer2.username}" }
it 'assigns only the first reviewer to the merge request' do it 'assigns to a single reviewer' do
content = "/assign_reviewer @#{developer.username} @#{developer2.username}" _, updates, message = service.execute(content, issuable)
_, updates, _ = service.execute(content, issuable)
expect(updates).to eq(reviewer_ids: [developer.id]) expect(updates[:reviewer_ids].count).to eq(1)
reviewer = updates[:reviewer_ids].first
expect([developer.id, developer2.id]).to include(reviewer)
user = reviewer == developer.id ? developer : developer2
expect(message).to match("Assigned #{user.to_reference} as reviewer.")
end
end
end end
end
context 'assign_reviewer command with me alias' do context 'with "me" alias' do
it_behaves_like 'assign_reviewer command' do
let(:content) { '/assign_reviewer me' } let(:content) { '/assign_reviewer me' }
let(:issuable) { merge_request }
it_behaves_like 'assign_reviewer command'
end end
end
context 'assign_reviewer command with me alias and whitespace' do context 'with an alias and whitespace' do
it_behaves_like 'assign_reviewer command' do
let(:content) { '/assign_reviewer me ' } let(:content) { '/assign_reviewer me ' }
let(:issuable) { merge_request }
it_behaves_like 'assign_reviewer command'
end end
end
it_behaves_like 'empty command', "Failed to assign a reviewer because no user was found." do context 'with an incorrect user' do
let(:content) { '/assign_reviewer @abcd1234' } let(:content) { '/assign_reviewer @abcd1234' }
let(:issuable) { merge_request }
end
it_behaves_like 'empty command', "Failed to assign a reviewer because no user was found." do it_behaves_like 'empty command', "Failed to assign a reviewer because no user was found."
let(:content) { '/assign_reviewer' } end
let(:issuable) { merge_request }
end
describe 'assign_reviewer command' do context 'with the "reviewer" alias' do
let(:content) { "/assign_reviewer @#{developer.username} do it!" } let(:content) { "/reviewer @#{developer.username}" }
it_behaves_like 'assign_reviewer command'
end
context 'with no user' do
let(:content) { '/assign_reviewer' }
it_behaves_like 'empty command', "Failed to assign a reviewer because no user was found."
end
it 'includes only the user reference' do context 'includes only the user reference with extra text' do
_, explanations = service.explain(content, merge_request) let(:content) { "/assign_reviewer @#{developer.username} do it!" }
expect(explanations).to eq(["Assigns @#{developer.username} as reviewer."]) it_behaves_like 'assign_reviewer command'
end end
end end
describe 'unassign_reviewer command' do describe 'unassign_reviewer command' do
let(:content) { '/unassign_reviewer' } # CE does not have multiple reviewers, so basically anything
let(:merge_request) { create(:merge_request, reviewers: [developer]) } # after /unassign_reviewer (including whitespace) will remove
# all the current reviewers.
let(:issuable) { create(:merge_request, reviewers: [developer]) }
let(:content) { "/unassign_reviewer @#{developer.username}" }
context 'with one user' do
it_behaves_like 'unassign_reviewer command'
end
it 'includes current reviewer reference' do context 'with an issue instead of a merge request' do
_, explanations = service.explain(content, merge_request) let(:issuable) { issue }
expect(explanations).to eq(["Removes reviewer @#{developer.username}."]) it_behaves_like 'empty command'
end end
it 'populates reviewer_ids: [] if content contains /unassign_reviewer' do context 'with anything after the command' do
_, updates, _ = service.execute(content, merge_request) let(:content) { '/unassign_reviewer supercalifragilisticexpialidocious' }
expect(updates).to eq(reviewer_ids: []) it_behaves_like 'unassign_reviewer command'
end end
it 'returns the unassign reviewer message for all the reviewers if content contains /unassign_reviewer' do context 'with the "remove_reviewer" alias' do
merge_request.update!(reviewer_ids: [developer.id, developer2.id]) let(:content) { "/remove_reviewer @#{developer.username}" }
_, _, message = service.execute(content, merge_request)
expect(message).to eq("Removed reviewers #{developer.to_reference} and #{developer2.to_reference}.") it_behaves_like 'unassign_reviewer command'
end
context 'with no user' do
let(:content) { '/unassign_reviewer' }
it_behaves_like 'unassign_reviewer command'
end end
end end
end end
...@@ -1969,6 +2005,28 @@ RSpec.describe QuickActions::InterpretService do ...@@ -1969,6 +2005,28 @@ RSpec.describe QuickActions::InterpretService do
end end
end end
describe 'unassign_reviewer command' do
let(:content) { '/unassign_reviewer' }
let(:merge_request) { create(:merge_request, source_project: project, reviewers: [developer]) }
it 'includes current assignee reference' do
_, explanations = service.explain(content, merge_request)
expect(explanations).to eq(["Removes reviewer @#{developer.username}."])
end
end
describe 'assign_reviewer command' do
let(:content) { "/assign_reviewer #{developer.to_reference}" }
let(:merge_request) { create(:merge_request, source_project: project, assignees: [developer]) }
it 'includes only the user reference' do
_, explanations = service.explain(content, merge_request)
expect(explanations).to eq(["Assigns #{developer.to_reference} as reviewer."])
end
end
describe 'milestone command' do describe 'milestone command' do
let(:content) { '/milestone %wrong-milestone' } let(:content) { '/milestone %wrong-milestone' }
let!(:milestone) { create(:milestone, project: project, title: '9.10') } let!(:milestone) { create(:milestone, project: project, title: '9.10') }
......
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