Commit 8c201ae4 authored by Bob Van Landuyt's avatar Bob Van Landuyt

Merge branch 'awgeorge1/gitlab-ee-6249-related-quick-action' into 'master'

Add `/relate` quick action

Closes #6249

See merge request gitlab-org/gitlab-ee!14257
parents 56b16f26 77f2d364
...@@ -57,6 +57,7 @@ discussions, and descriptions: ...@@ -57,6 +57,7 @@ discussions, and descriptions:
| `/approve` | Approve the merge request | | ✓ | | `/approve` | Approve the merge request | | ✓ |
| `/merge` | Merge (when pipeline succeeds) | | ✓ | | `/merge` | Merge (when pipeline succeeds) | | ✓ |
| `/create_merge_request <branch name>` | Create a new merge request starting from the current issue | ✓ | | | `/create_merge_request <branch name>` | Create a new merge request starting from the current issue | ✓ | |
| `/relate #issue1 #issue2` | Mark issues as related **[STARTER]** | ✓ | |
## Quick actions for commit messages ## Quick actions for commit messages
......
...@@ -12,6 +12,7 @@ module EE ...@@ -12,6 +12,7 @@ module EE
include EE::Gitlab::QuickActions::IssueActions include EE::Gitlab::QuickActions::IssueActions
include EE::Gitlab::QuickActions::MergeRequestActions include EE::Gitlab::QuickActions::MergeRequestActions
include EE::Gitlab::QuickActions::IssueAndMergeRequestActions include EE::Gitlab::QuickActions::IssueAndMergeRequestActions
include EE::Gitlab::QuickActions::RelateActions
# rubocop: enable Cop/InjectEnterpriseEditionModule # rubocop: enable Cop/InjectEnterpriseEditionModule
end end
end end
......
---
title: Related quick action added
merge_request: 14257
author: William George
type: added
# frozen_string_literal: true
module EE
module Gitlab
module QuickActions
module RelateActions
extend ActiveSupport::Concern
include ::Gitlab::QuickActions::Dsl
included do
desc _('Mark this issue as related to another issue')
explanation do |related_reference|
_('Marks this issue as related to %{issue_ref}.') % { issue_ref: related_reference }
end
params '#issue'
types Issue
condition do
quick_action_target.persisted? &&
current_user.can?(:"update_#{quick_action_target.to_ability_name}", quick_action_target)
end
command :relate do |related_param|
IssueLinks::CreateService.new(quick_action_target, current_user, { issuable_references: [related_param] }).execute
end
end
end
end
end
end
...@@ -257,4 +257,46 @@ describe Notes::QuickActionsService do ...@@ -257,4 +257,46 @@ describe Notes::QuickActionsService do
end end
end end
end end
context '/relate' do
let(:other_issue) { create(:issue, project: project) }
let(:note_text) { "/relate #{other_issue.to_reference}" }
let(:note) { create(:note_on_issue, noteable: issue, project: project, note: note_text) }
context 'user cannot relate issues' do
before do
project.update(visibility: Gitlab::VisibilityLevel::PUBLIC)
end
it 'does not create issue relation' do
expect { execute(note) }.not_to change { IssueLink.count }
end
end
context 'user is allowed to relate issues' do
before do
group.add_developer(user)
end
context 'related issues are not enabled' do
before do
stub_licensed_features(related_issues: false)
end
it 'does not create issue relation' do
expect { execute(note) }.not_to change { IssueLink.count }
end
end
context 'related issues are enabled' do
before do
stub_licensed_features(related_issues: true)
end
it 'creates issue relation' do
expect { execute(note) }.to change { IssueLink.count }.by(1)
end
end
end
end
end end
...@@ -771,6 +771,101 @@ describe QuickActions::InterpretService do ...@@ -771,6 +771,101 @@ describe QuickActions::InterpretService do
let(:issuable) { build(:merge_request, source_project: project) } let(:issuable) { build(:merge_request, source_project: project) }
end end
end end
context 'relate command' do
shared_examples 'relate command' do
it 'relates issues' do
service.execute(content, issue)
expect(IssueLink.where(source: issue).map(&:target)).to match_array(issues_related)
end
end
context 'user is member of group' do
before do
group.add_developer(user)
end
context 'relate a single issue' do
let(:other_issue) { create(:issue, project: project) }
let(:issues_related) { [other_issue] }
let(:content) { "/relate #{other_issue.to_reference}" }
it_behaves_like 'relate command'
end
context 'relate multiple issues at once' do
let(:second_issue) { create(:issue, project: project) }
let(:third_issue) { create(:issue, project: project) }
let(:issues_related) { [second_issue, third_issue] }
let(:content) { "/relate #{second_issue.to_reference} #{third_issue.to_reference}" }
it_behaves_like 'relate command'
end
context 'empty relate command' do
let(:issues_related) { [] }
let(:content) { '/relate' }
it_behaves_like 'relate command'
end
context 'already having related issues' do
let(:second_issue) { create(:issue, project: project) }
let(:third_issue) { create(:issue, project: project) }
let(:issues_related) { [second_issue, third_issue] }
let(:content) { "/relate #{third_issue.to_reference(project)}" }
before do
create(:issue_link, source: issue, target: second_issue)
end
it_behaves_like 'relate command'
end
context 'cross project' do
let(:another_group) { create(:group, :public) }
let(:other_project) { create(:project, group: another_group) }
before do
another_group.add_developer(current_user)
end
context 'relate a cross project issue' do
let(:other_issue) { create(:issue, project: other_project) }
let(:issues_related) { [other_issue] }
let(:content) { "/relate #{other_issue.to_reference(project)}" }
it_behaves_like 'relate command'
end
context 'relate multiple cross projects issues at once' do
let(:second_issue) { create(:issue, project: other_project) }
let(:third_issue) { create(:issue, project: other_project) }
let(:issues_related) { [second_issue, third_issue] }
let(:content) { "/relate #{second_issue.to_reference(project)} #{third_issue.to_reference(project)}" }
it_behaves_like 'relate command'
end
context 'relate a non-existing issue' do
let(:issues_related) { [] }
let(:content) { "/relate imaginary#1234" }
it_behaves_like 'relate command'
end
context 'relate a private issue' do
let(:private_project) { create(:project, :private) }
let(:other_issue) { create(:issue, project: private_project) }
let(:issues_related) { [] }
let(:content) { "/relate #{other_issue.to_reference(project)}" }
it_behaves_like 'relate command'
end
end
end
end
end end
describe '#explain' do describe '#explain' do
......
...@@ -8178,6 +8178,9 @@ msgstr "" ...@@ -8178,6 +8178,9 @@ msgstr ""
msgid "Mark this issue as a duplicate of another issue" msgid "Mark this issue as a duplicate of another issue"
msgstr "" msgstr ""
msgid "Mark this issue as related to another issue"
msgstr ""
msgid "Mark todo as done" msgid "Mark todo as done"
msgstr "" msgstr ""
...@@ -8193,6 +8196,9 @@ msgstr "" ...@@ -8193,6 +8196,9 @@ msgstr ""
msgid "Marks this issue as a duplicate of %{duplicate_reference}." msgid "Marks this issue as a duplicate of %{duplicate_reference}."
msgstr "" msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
msgstr ""
msgid "Marks todo as done." msgid "Marks todo as done."
msgstr "" msgstr ""
......
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