From 0541f237441a8a046273ac0c15cc509064affa41 Mon Sep 17 00:00:00 2001 From: Mateusz Bajorski Date: Mon, 15 Jan 2018 07:46:19 +0100 Subject: [PATCH 1/9] Add Inherit quick action Closes #38450 --- .../quick_actions/interpret_service.rb | 18 +++++ changelogs/unreleased/add-inherit-command.yml | 5 ++ doc/user/project/quick_actions.md | 3 +- .../quick_actions/interpret_service_spec.rb | 65 +++++++++++++++++++ 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/add-inherit-command.yml diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb index 669c1ba0a22..b8818399f78 100644 --- a/app/services/quick_actions/interpret_service.rb +++ b/app/services/quick_actions/interpret_service.rb @@ -256,6 +256,24 @@ module QuickActions end end + desc 'Inherit (copy) labels and milestone from other issue' + explanation do |issue_id| + "Inherit (copy) labels and milestone from issue \"#{issue_id}\"." + end + params '#issue' + condition do + issuable.persisted? && + current_user.can?(:"update_#{issuable.to_ability_name}", issuable) + end + command :inherit do |issue_id| + issue = extract_references(issue_id, :issue).first + if issue.present? && issue.project_id == issuable.project_id + @updates[:add_label_ids] = issue.labels.map(&:id) + + @updates[:milestone_id] = issue.milestone.id if issue.milestone + end + end + desc 'Add a todo' explanation 'Adds a todo.' condition do diff --git a/changelogs/unreleased/add-inherit-command.yml b/changelogs/unreleased/add-inherit-command.yml new file mode 100644 index 00000000000..84f5bc97fbe --- /dev/null +++ b/changelogs/unreleased/add-inherit-command.yml @@ -0,0 +1,5 @@ +--- +title: Add Inherit quick action +merge_request: +author: Mateusz Bajorski +type: added diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md index 442fc978284..3b6bdc8ca3d 100644 --- a/doc/user/project/quick_actions.md +++ b/doc/user/project/quick_actions.md @@ -40,4 +40,5 @@ do. | `/duplicate #issue` | Closes this issue and marks it as a duplicate of another issue | | `/move path/to/project` | Moves issue to another project | | `/tableflip` | Append the comment with `(╯°□°)╯︵ ┻━┻` | -| `/shrug` | Append the comment with `¯\_(ツ)_/¯` | \ No newline at end of file +| `/shrug` | Append the comment with `¯\_(ツ)_/¯` | +| `/inherit #issue` | Inherit (copy) labels and milestone from other issue | diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb index ae160d104f1..31f9296e3bb 100644 --- a/spec/services/quick_actions/interpret_service_spec.rb +++ b/spec/services/quick_actions/interpret_service_spec.rb @@ -306,6 +306,23 @@ describe QuickActions::InterpretService do end end + shared_examples 'inherit command' do + it 'fetches issue and copies labels and milestone if content contains /inherit issue_reference' do + issue_father # populate the issue + todo_label # populate this label + inreview_label # populate this label + _, updates = service.execute(content, issuable) + + expect(updates[:add_label_ids]).to match_array([inreview_label.id, todo_label.id]) + + if issue_father.milestone + expect(updates[:milestone_id]).to eq(issue_father.milestone.id) + else + expect(updates).not_to have_key(:milestone_id) + end + end + end + shared_examples 'shrug command' do it 'appends ¯\_(ツ)_/¯ to the comment' do new_content, _ = service.execute(content, issuable) @@ -741,6 +758,54 @@ describe QuickActions::InterpretService do let(:issuable) { issue } end + context '/inherit command' do + let!(:todo_label) { create(:label, project: project, title: 'To Do') } + let!(:inreview_label) { create(:label, project: project, title: 'In Review') } + + it_behaves_like 'inherit command' do + # Without milestone assignment + let(:issue_father) { create(:labeled_issue, project: project, labels: [inreview_label, todo_label]) } + + let(:content) { "/inherit #{issue_father.to_reference}" } + let(:issuable) { issue } + end + + it_behaves_like 'inherit command' do + # With milestone assignment + let(:issue_father) { create(:labeled_issue, project: project, labels: [todo_label, inreview_label], milestone: milestone) } + + let(:content) { "/inherit #{issue_father.to_reference(project)}" } + let(:issuable) { issue } + end + + it_behaves_like 'empty command' do + let(:content) { '/inherit' } + let(:issuable) { issue } + end + + context 'cross project references' do + it_behaves_like 'empty command' do + let(:other_project) { create(:project, :public) } + let(:issue_father) { create(:labeled_issue, project: other_project, labels: [todo_label, inreview_label]) } + let(:content) { "/inherit #{issue_father.to_reference(project)}" } + let(:issuable) { issue } + end + + it_behaves_like 'empty command' do + let(:content) { "/inherit imaginary#1234" } + let(:issuable) { issue } + end + + it_behaves_like 'empty command' do + let(:other_project) { create(:project, :private) } + let(:issue_father) { create(:issue, project: other_project) } + + let(:content) { "/inherit #{issue_father.to_reference(project)}" } + let(:issuable) { issue } + end + end + end + context '/duplicate command' do it_behaves_like 'duplicate command' do let(:issue_duplicate) { create(:issue, project: project) } From d691df02560f06dc87aa5812ebea31de62e0e6e6 Mon Sep 17 00:00:00 2001 From: Mateusz Bajorski Date: Sun, 21 Jan 2018 18:16:56 +0100 Subject: [PATCH 2/9] Changed command name to copy_metadata and added MR support --- .../quick_actions/interpret_service.rb | 16 +++--- changelogs/unreleased/add-inherit-command.yml | 2 +- doc/user/project/quick_actions.md | 2 +- .../quick_actions/interpret_service_spec.rb | 56 +++++++++---------- 4 files changed, 39 insertions(+), 37 deletions(-) diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb index b8818399f78..d9f33ebb108 100644 --- a/app/services/quick_actions/interpret_service.rb +++ b/app/services/quick_actions/interpret_service.rb @@ -256,18 +256,20 @@ module QuickActions end end - desc 'Inherit (copy) labels and milestone from other issue' - explanation do |issue_id| - "Inherit (copy) labels and milestone from issue \"#{issue_id}\"." + desc 'Copy labels and milestone from other issue or merge request' + explanation do |issueable_id| + "Copy labels and milestone from issue or merge_request \"#{issueable_id}\"." end - params '#issue' + params '< #issue | !merge_request >' condition do issuable.persisted? && current_user.can?(:"update_#{issuable.to_ability_name}", issuable) end - command :inherit do |issue_id| - issue = extract_references(issue_id, :issue).first - if issue.present? && issue.project_id == issuable.project_id + command :copy_metadata do |issueable_id| + reference_type = issueable_id.include?("#") ? :issue : :merge_request + issue = extract_references(issueable_id, reference_type).first + + if issue.present? && issue.project.id == issuable.project.id @updates[:add_label_ids] = issue.labels.map(&:id) @updates[:milestone_id] = issue.milestone.id if issue.milestone diff --git a/changelogs/unreleased/add-inherit-command.yml b/changelogs/unreleased/add-inherit-command.yml index 84f5bc97fbe..d47aa8c7b36 100644 --- a/changelogs/unreleased/add-inherit-command.yml +++ b/changelogs/unreleased/add-inherit-command.yml @@ -1,5 +1,5 @@ --- title: Add Inherit quick action -merge_request: +merge_request: 16473 author: Mateusz Bajorski type: added diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md index 3b6bdc8ca3d..e2e2b859d35 100644 --- a/doc/user/project/quick_actions.md +++ b/doc/user/project/quick_actions.md @@ -41,4 +41,4 @@ do. | `/move path/to/project` | Moves issue to another project | | `/tableflip` | Append the comment with `(╯°□°)╯︵ ┻━┻` | | `/shrug` | Append the comment with `¯\_(ツ)_/¯` | -| `/inherit #issue` | Inherit (copy) labels and milestone from other issue | +| /copy_metadata < #issue | !merge_request > | copy_metadata labels and milestone from other issue or merge request | diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb index 31f9296e3bb..54be5020a54 100644 --- a/spec/services/quick_actions/interpret_service_spec.rb +++ b/spec/services/quick_actions/interpret_service_spec.rb @@ -306,17 +306,17 @@ describe QuickActions::InterpretService do end end - shared_examples 'inherit command' do - it 'fetches issue and copies labels and milestone if content contains /inherit issue_reference' do - issue_father # populate the issue + shared_examples 'copy_metadata command' do + it 'fetches issue or merge request and copies labels and milestone if content contains /copy_metadata reference' do + issueable_father # populate the issue todo_label # populate this label inreview_label # populate this label _, updates = service.execute(content, issuable) expect(updates[:add_label_ids]).to match_array([inreview_label.id, todo_label.id]) - if issue_father.milestone - expect(updates[:milestone_id]).to eq(issue_father.milestone.id) + if issueable_father.milestone + expect(updates[:milestone_id]).to eq(issueable_father.milestone.id) else expect(updates).not_to have_key(:milestone_id) end @@ -758,49 +758,49 @@ describe QuickActions::InterpretService do let(:issuable) { issue } end - context '/inherit command' do + context '/copy_metadata command' do let!(:todo_label) { create(:label, project: project, title: 'To Do') } let!(:inreview_label) { create(:label, project: project, title: 'In Review') } - it_behaves_like 'inherit command' do - # Without milestone assignment - let(:issue_father) { create(:labeled_issue, project: project, labels: [inreview_label, todo_label]) } - - let(:content) { "/inherit #{issue_father.to_reference}" } - let(:issuable) { issue } - end - - it_behaves_like 'inherit command' do - # With milestone assignment - let(:issue_father) { create(:labeled_issue, project: project, labels: [todo_label, inreview_label], milestone: milestone) } - - let(:content) { "/inherit #{issue_father.to_reference(project)}" } - let(:issuable) { issue } - end - it_behaves_like 'empty command' do - let(:content) { '/inherit' } + let(:content) { '/copy_metadata' } let(:issuable) { issue } end + it_behaves_like 'copy_metadata command' do + let(:issueable_father) { create(:labeled_issue, project: project, labels: [inreview_label, todo_label]) } + + let(:content) { "/copy_metadata #{issueable_father.to_reference}" } + let(:issuable) { issue } + end + + context 'when the parent issueable has a milestone' do + it_behaves_like 'copy_metadata command' do + let(:issueable_father) { create(:labeled_issue, project: project, labels: [todo_label, inreview_label], milestone: milestone) } + + let(:content) { "/copy_metadata #{issueable_father.to_reference(project)}" } + let(:issuable) { issue } + end + end + context 'cross project references' do it_behaves_like 'empty command' do let(:other_project) { create(:project, :public) } - let(:issue_father) { create(:labeled_issue, project: other_project, labels: [todo_label, inreview_label]) } - let(:content) { "/inherit #{issue_father.to_reference(project)}" } + let(:issueable_father) { create(:labeled_issue, project: other_project, labels: [todo_label, inreview_label]) } + let(:content) { "/copy_metadata #{issueable_father.to_reference(project)}" } let(:issuable) { issue } end it_behaves_like 'empty command' do - let(:content) { "/inherit imaginary#1234" } + let(:content) { "/copy_metadata imaginary#1234" } let(:issuable) { issue } end it_behaves_like 'empty command' do let(:other_project) { create(:project, :private) } - let(:issue_father) { create(:issue, project: other_project) } + let(:issueable_father) { create(:issue, project: other_project) } - let(:content) { "/inherit #{issue_father.to_reference(project)}" } + let(:content) { "/copy_metadata #{issueable_father.to_reference(project)}" } let(:issuable) { issue } end end From 427bfae287cb893bb02f6ae54b9e7a08ebe2a267 Mon Sep 17 00:00:00 2001 From: Mateusz Bajorski Date: Wed, 31 Jan 2018 18:41:06 +0100 Subject: [PATCH 3/9] Fixed typos and improved reference checking --- .../quick_actions/interpret_service.rb | 18 +++++++------- ...mand.yml => add-copy-metadata-command.yml} | 2 +- doc/user/project/quick_actions.md | 2 +- .../quick_actions/interpret_service_spec.rb | 24 +++++++++---------- 4 files changed, 23 insertions(+), 23 deletions(-) rename changelogs/unreleased/{add-inherit-command.yml => add-copy-metadata-command.yml} (62%) diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb index d9f33ebb108..6b0d8802a4e 100644 --- a/app/services/quick_actions/interpret_service.rb +++ b/app/services/quick_actions/interpret_service.rb @@ -257,22 +257,22 @@ module QuickActions end desc 'Copy labels and milestone from other issue or merge request' - explanation do |issueable_id| - "Copy labels and milestone from issue or merge_request \"#{issueable_id}\"." + explanation do |issuable_id| + "Copy labels and milestone from issue or merge_request \"#{issuable_id}\"." end - params '< #issue | !merge_request >' + params '#issue | !merge_request' condition do issuable.persisted? && current_user.can?(:"update_#{issuable.to_ability_name}", issuable) end - command :copy_metadata do |issueable_id| - reference_type = issueable_id.include?("#") ? :issue : :merge_request - issue = extract_references(issueable_id, reference_type).first + command :copy_metadata do |issuable_id| + source_issuable = extract_references(issuable_id, :issue).first + source_issuable = extract_references(issuable_id, :merge_request).first if !source_issuable.present? - if issue.present? && issue.project.id == issuable.project.id - @updates[:add_label_ids] = issue.labels.map(&:id) + if source_issuable.present? && source_issuable.project.id == issuable.project.id + @updates[:add_label_ids] = source_issuable.labels.map(&:id) - @updates[:milestone_id] = issue.milestone.id if issue.milestone + @updates[:milestone_id] = source_issuable.milestone.id if source_issuable.milestone end end diff --git a/changelogs/unreleased/add-inherit-command.yml b/changelogs/unreleased/add-copy-metadata-command.yml similarity index 62% rename from changelogs/unreleased/add-inherit-command.yml rename to changelogs/unreleased/add-copy-metadata-command.yml index d47aa8c7b36..3bf25ae6ce0 100644 --- a/changelogs/unreleased/add-inherit-command.yml +++ b/changelogs/unreleased/add-copy-metadata-command.yml @@ -1,5 +1,5 @@ --- -title: Add Inherit quick action +title: Add Copy metadata quick action merge_request: 16473 author: Mateusz Bajorski type: added diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md index e2e2b859d35..75799caacde 100644 --- a/doc/user/project/quick_actions.md +++ b/doc/user/project/quick_actions.md @@ -41,4 +41,4 @@ do. | `/move path/to/project` | Moves issue to another project | | `/tableflip` | Append the comment with `(╯°□°)╯︵ ┻━┻` | | `/shrug` | Append the comment with `¯\_(ツ)_/¯` | -| /copy_metadata < #issue | !merge_request > | copy_metadata labels and milestone from other issue or merge request | +| /copy_metadata < #issue | !merge_request > | Copy labels and milestone from other issue or merge request | diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb index 54be5020a54..5b70e434e23 100644 --- a/spec/services/quick_actions/interpret_service_spec.rb +++ b/spec/services/quick_actions/interpret_service_spec.rb @@ -308,15 +308,15 @@ describe QuickActions::InterpretService do shared_examples 'copy_metadata command' do it 'fetches issue or merge request and copies labels and milestone if content contains /copy_metadata reference' do - issueable_father # populate the issue + source_issuable # populate the issue todo_label # populate this label inreview_label # populate this label _, updates = service.execute(content, issuable) expect(updates[:add_label_ids]).to match_array([inreview_label.id, todo_label.id]) - if issueable_father.milestone - expect(updates[:milestone_id]).to eq(issueable_father.milestone.id) + if source_issuable.milestone + expect(updates[:milestone_id]).to eq(source_issuable.milestone.id) else expect(updates).not_to have_key(:milestone_id) end @@ -768,17 +768,17 @@ describe QuickActions::InterpretService do end it_behaves_like 'copy_metadata command' do - let(:issueable_father) { create(:labeled_issue, project: project, labels: [inreview_label, todo_label]) } + let(:source_issuable) { create(:labeled_issue, project: project, labels: [inreview_label, todo_label]) } - let(:content) { "/copy_metadata #{issueable_father.to_reference}" } + let(:content) { "/copy_metadata #{source_issuable.to_reference}" } let(:issuable) { issue } end - context 'when the parent issueable has a milestone' do + context 'when the parent issuable has a milestone' do it_behaves_like 'copy_metadata command' do - let(:issueable_father) { create(:labeled_issue, project: project, labels: [todo_label, inreview_label], milestone: milestone) } + let(:source_issuable) { create(:labeled_issue, project: project, labels: [todo_label, inreview_label], milestone: milestone) } - let(:content) { "/copy_metadata #{issueable_father.to_reference(project)}" } + let(:content) { "/copy_metadata #{source_issuable.to_reference(project)}" } let(:issuable) { issue } end end @@ -786,8 +786,8 @@ describe QuickActions::InterpretService do context 'cross project references' do it_behaves_like 'empty command' do let(:other_project) { create(:project, :public) } - let(:issueable_father) { create(:labeled_issue, project: other_project, labels: [todo_label, inreview_label]) } - let(:content) { "/copy_metadata #{issueable_father.to_reference(project)}" } + let(:source_issuable) { create(:labeled_issue, project: other_project, labels: [todo_label, inreview_label]) } + let(:content) { "/copy_metadata #{source_issuable.to_reference(project)}" } let(:issuable) { issue } end @@ -798,9 +798,9 @@ describe QuickActions::InterpretService do it_behaves_like 'empty command' do let(:other_project) { create(:project, :private) } - let(:issueable_father) { create(:issue, project: other_project) } + let(:source_issuable) { create(:issue, project: other_project) } - let(:content) { "/copy_metadata #{issueable_father.to_reference(project)}" } + let(:content) { "/copy_metadata #{source_issuable.to_reference(project)}" } let(:issuable) { issue } end end From da15007f2314e367ccd7e2bed13629864a5e4307 Mon Sep 17 00:00:00 2001 From: Mateusz Bajorski Date: Thu, 1 Feb 2018 19:38:10 +0100 Subject: [PATCH 4/9] Fixed inconsistent descriptions and refactored reference checking --- app/services/quick_actions/interpret_service.rb | 4 ++-- doc/user/project/quick_actions.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb index 6b0d8802a4e..88ca26be1d5 100644 --- a/app/services/quick_actions/interpret_service.rb +++ b/app/services/quick_actions/interpret_service.rb @@ -258,7 +258,7 @@ module QuickActions desc 'Copy labels and milestone from other issue or merge request' explanation do |issuable_id| - "Copy labels and milestone from issue or merge_request \"#{issuable_id}\"." + "Copy labels and milestone from issue or merge_request #{issuable_id}." end params '#issue | !merge_request' condition do @@ -267,7 +267,7 @@ module QuickActions end command :copy_metadata do |issuable_id| source_issuable = extract_references(issuable_id, :issue).first - source_issuable = extract_references(issuable_id, :merge_request).first if !source_issuable.present? + source_issuable ||= extract_references(issuable_id, :merge_request).first if source_issuable.present? && source_issuable.project.id == issuable.project.id @updates[:add_label_ids] = source_issuable.labels.map(&:id) diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md index 75799caacde..3e3b699edc4 100644 --- a/doc/user/project/quick_actions.md +++ b/doc/user/project/quick_actions.md @@ -41,4 +41,4 @@ do. | `/move path/to/project` | Moves issue to another project | | `/tableflip` | Append the comment with `(╯°□°)╯︵ ┻━┻` | | `/shrug` | Append the comment with `¯\_(ツ)_/¯` | -| /copy_metadata < #issue | !merge_request > | Copy labels and milestone from other issue or merge request | +| /copy_metadata #issue | !merge_request | Copy labels and milestone from other issue or merge request | From 4f10cad9ffdc508dbcecd477e93921367a69477d Mon Sep 17 00:00:00 2001 From: Mateusz Bajorski Date: Mon, 15 Jan 2018 07:46:19 +0100 Subject: [PATCH 5/9] Add Inherit quick action Closes #38450 --- .../quick_actions/interpret_service.rb | 18 +++++ changelogs/unreleased/add-inherit-command.yml | 5 ++ doc/user/project/quick_actions.md | 3 +- .../quick_actions/interpret_service_spec.rb | 65 +++++++++++++++++++ 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/add-inherit-command.yml diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb index 1e9bd84e749..4abb936e14a 100644 --- a/app/services/quick_actions/interpret_service.rb +++ b/app/services/quick_actions/interpret_service.rb @@ -268,6 +268,24 @@ module QuickActions end end + desc 'Inherit (copy) labels and milestone from other issue' + explanation do |issue_id| + "Inherit (copy) labels and milestone from issue \"#{issue_id}\"." + end + params '#issue' + condition do + issuable.persisted? && + current_user.can?(:"update_#{issuable.to_ability_name}", issuable) + end + command :inherit do |issue_id| + issue = extract_references(issue_id, :issue).first + if issue.present? && issue.project_id == issuable.project_id + @updates[:add_label_ids] = issue.labels.map(&:id) + + @updates[:milestone_id] = issue.milestone.id if issue.milestone + end + end + desc 'Add a todo' explanation 'Adds a todo.' condition do diff --git a/changelogs/unreleased/add-inherit-command.yml b/changelogs/unreleased/add-inherit-command.yml new file mode 100644 index 00000000000..84f5bc97fbe --- /dev/null +++ b/changelogs/unreleased/add-inherit-command.yml @@ -0,0 +1,5 @@ +--- +title: Add Inherit quick action +merge_request: +author: Mateusz Bajorski +type: added diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md index 442fc978284..3b6bdc8ca3d 100644 --- a/doc/user/project/quick_actions.md +++ b/doc/user/project/quick_actions.md @@ -40,4 +40,5 @@ do. | `/duplicate #issue` | Closes this issue and marks it as a duplicate of another issue | | `/move path/to/project` | Moves issue to another project | | `/tableflip` | Append the comment with `(╯°□°)╯︵ ┻━┻` | -| `/shrug` | Append the comment with `¯\_(ツ)_/¯` | \ No newline at end of file +| `/shrug` | Append the comment with `¯\_(ツ)_/¯` | +| `/inherit #issue` | Inherit (copy) labels and milestone from other issue | diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb index f793f55e51b..ebe0c7639a0 100644 --- a/spec/services/quick_actions/interpret_service_spec.rb +++ b/spec/services/quick_actions/interpret_service_spec.rb @@ -306,6 +306,23 @@ describe QuickActions::InterpretService do end end + shared_examples 'inherit command' do + it 'fetches issue and copies labels and milestone if content contains /inherit issue_reference' do + issue_father # populate the issue + todo_label # populate this label + inreview_label # populate this label + _, updates = service.execute(content, issuable) + + expect(updates[:add_label_ids]).to match_array([inreview_label.id, todo_label.id]) + + if issue_father.milestone + expect(updates[:milestone_id]).to eq(issue_father.milestone.id) + else + expect(updates).not_to have_key(:milestone_id) + end + end + end + shared_examples 'shrug command' do it 'appends ¯\_(ツ)_/¯ to the comment' do new_content, _ = service.execute(content, issuable) @@ -757,6 +774,54 @@ describe QuickActions::InterpretService do let(:issuable) { issue } end + context '/inherit command' do + let!(:todo_label) { create(:label, project: project, title: 'To Do') } + let!(:inreview_label) { create(:label, project: project, title: 'In Review') } + + it_behaves_like 'inherit command' do + # Without milestone assignment + let(:issue_father) { create(:labeled_issue, project: project, labels: [inreview_label, todo_label]) } + + let(:content) { "/inherit #{issue_father.to_reference}" } + let(:issuable) { issue } + end + + it_behaves_like 'inherit command' do + # With milestone assignment + let(:issue_father) { create(:labeled_issue, project: project, labels: [todo_label, inreview_label], milestone: milestone) } + + let(:content) { "/inherit #{issue_father.to_reference(project)}" } + let(:issuable) { issue } + end + + it_behaves_like 'empty command' do + let(:content) { '/inherit' } + let(:issuable) { issue } + end + + context 'cross project references' do + it_behaves_like 'empty command' do + let(:other_project) { create(:project, :public) } + let(:issue_father) { create(:labeled_issue, project: other_project, labels: [todo_label, inreview_label]) } + let(:content) { "/inherit #{issue_father.to_reference(project)}" } + let(:issuable) { issue } + end + + it_behaves_like 'empty command' do + let(:content) { "/inherit imaginary#1234" } + let(:issuable) { issue } + end + + it_behaves_like 'empty command' do + let(:other_project) { create(:project, :private) } + let(:issue_father) { create(:issue, project: other_project) } + + let(:content) { "/inherit #{issue_father.to_reference(project)}" } + let(:issuable) { issue } + end + end + end + context '/duplicate command' do it_behaves_like 'duplicate command' do let(:issue_duplicate) { create(:issue, project: project) } From a0adf87707e44fda83aca859b41ce18372a1c72b Mon Sep 17 00:00:00 2001 From: Mateusz Bajorski Date: Sun, 21 Jan 2018 18:16:56 +0100 Subject: [PATCH 6/9] Changed command name to copy_metadata and added MR support --- .../quick_actions/interpret_service.rb | 16 +++--- changelogs/unreleased/add-inherit-command.yml | 2 +- doc/user/project/quick_actions.md | 2 +- .../quick_actions/interpret_service_spec.rb | 56 +++++++++---------- 4 files changed, 39 insertions(+), 37 deletions(-) diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb index 4abb936e14a..28fa887bf2d 100644 --- a/app/services/quick_actions/interpret_service.rb +++ b/app/services/quick_actions/interpret_service.rb @@ -268,18 +268,20 @@ module QuickActions end end - desc 'Inherit (copy) labels and milestone from other issue' - explanation do |issue_id| - "Inherit (copy) labels and milestone from issue \"#{issue_id}\"." + desc 'Copy labels and milestone from other issue or merge request' + explanation do |issueable_id| + "Copy labels and milestone from issue or merge_request \"#{issueable_id}\"." end - params '#issue' + params '< #issue | !merge_request >' condition do issuable.persisted? && current_user.can?(:"update_#{issuable.to_ability_name}", issuable) end - command :inherit do |issue_id| - issue = extract_references(issue_id, :issue).first - if issue.present? && issue.project_id == issuable.project_id + command :copy_metadata do |issueable_id| + reference_type = issueable_id.include?("#") ? :issue : :merge_request + issue = extract_references(issueable_id, reference_type).first + + if issue.present? && issue.project.id == issuable.project.id @updates[:add_label_ids] = issue.labels.map(&:id) @updates[:milestone_id] = issue.milestone.id if issue.milestone diff --git a/changelogs/unreleased/add-inherit-command.yml b/changelogs/unreleased/add-inherit-command.yml index 84f5bc97fbe..d47aa8c7b36 100644 --- a/changelogs/unreleased/add-inherit-command.yml +++ b/changelogs/unreleased/add-inherit-command.yml @@ -1,5 +1,5 @@ --- title: Add Inherit quick action -merge_request: +merge_request: 16473 author: Mateusz Bajorski type: added diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md index 3b6bdc8ca3d..e2e2b859d35 100644 --- a/doc/user/project/quick_actions.md +++ b/doc/user/project/quick_actions.md @@ -41,4 +41,4 @@ do. | `/move path/to/project` | Moves issue to another project | | `/tableflip` | Append the comment with `(╯°□°)╯︵ ┻━┻` | | `/shrug` | Append the comment with `¯\_(ツ)_/¯` | -| `/inherit #issue` | Inherit (copy) labels and milestone from other issue | +| /copy_metadata < #issue | !merge_request > | copy_metadata labels and milestone from other issue or merge request | diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb index ebe0c7639a0..9a8240f9491 100644 --- a/spec/services/quick_actions/interpret_service_spec.rb +++ b/spec/services/quick_actions/interpret_service_spec.rb @@ -306,17 +306,17 @@ describe QuickActions::InterpretService do end end - shared_examples 'inherit command' do - it 'fetches issue and copies labels and milestone if content contains /inherit issue_reference' do - issue_father # populate the issue + shared_examples 'copy_metadata command' do + it 'fetches issue or merge request and copies labels and milestone if content contains /copy_metadata reference' do + issueable_father # populate the issue todo_label # populate this label inreview_label # populate this label _, updates = service.execute(content, issuable) expect(updates[:add_label_ids]).to match_array([inreview_label.id, todo_label.id]) - if issue_father.milestone - expect(updates[:milestone_id]).to eq(issue_father.milestone.id) + if issueable_father.milestone + expect(updates[:milestone_id]).to eq(issueable_father.milestone.id) else expect(updates).not_to have_key(:milestone_id) end @@ -774,49 +774,49 @@ describe QuickActions::InterpretService do let(:issuable) { issue } end - context '/inherit command' do + context '/copy_metadata command' do let!(:todo_label) { create(:label, project: project, title: 'To Do') } let!(:inreview_label) { create(:label, project: project, title: 'In Review') } - it_behaves_like 'inherit command' do - # Without milestone assignment - let(:issue_father) { create(:labeled_issue, project: project, labels: [inreview_label, todo_label]) } - - let(:content) { "/inherit #{issue_father.to_reference}" } - let(:issuable) { issue } - end - - it_behaves_like 'inherit command' do - # With milestone assignment - let(:issue_father) { create(:labeled_issue, project: project, labels: [todo_label, inreview_label], milestone: milestone) } - - let(:content) { "/inherit #{issue_father.to_reference(project)}" } - let(:issuable) { issue } - end - it_behaves_like 'empty command' do - let(:content) { '/inherit' } + let(:content) { '/copy_metadata' } let(:issuable) { issue } end + it_behaves_like 'copy_metadata command' do + let(:issueable_father) { create(:labeled_issue, project: project, labels: [inreview_label, todo_label]) } + + let(:content) { "/copy_metadata #{issueable_father.to_reference}" } + let(:issuable) { issue } + end + + context 'when the parent issueable has a milestone' do + it_behaves_like 'copy_metadata command' do + let(:issueable_father) { create(:labeled_issue, project: project, labels: [todo_label, inreview_label], milestone: milestone) } + + let(:content) { "/copy_metadata #{issueable_father.to_reference(project)}" } + let(:issuable) { issue } + end + end + context 'cross project references' do it_behaves_like 'empty command' do let(:other_project) { create(:project, :public) } - let(:issue_father) { create(:labeled_issue, project: other_project, labels: [todo_label, inreview_label]) } - let(:content) { "/inherit #{issue_father.to_reference(project)}" } + let(:issueable_father) { create(:labeled_issue, project: other_project, labels: [todo_label, inreview_label]) } + let(:content) { "/copy_metadata #{issueable_father.to_reference(project)}" } let(:issuable) { issue } end it_behaves_like 'empty command' do - let(:content) { "/inherit imaginary#1234" } + let(:content) { "/copy_metadata imaginary#1234" } let(:issuable) { issue } end it_behaves_like 'empty command' do let(:other_project) { create(:project, :private) } - let(:issue_father) { create(:issue, project: other_project) } + let(:issueable_father) { create(:issue, project: other_project) } - let(:content) { "/inherit #{issue_father.to_reference(project)}" } + let(:content) { "/copy_metadata #{issueable_father.to_reference(project)}" } let(:issuable) { issue } end end From 26087ae91c0397054786bed7bcc078b03dd8752b Mon Sep 17 00:00:00 2001 From: Mateusz Bajorski Date: Wed, 31 Jan 2018 18:41:06 +0100 Subject: [PATCH 7/9] Fixed typos and improved reference checking --- .../quick_actions/interpret_service.rb | 18 +++++++------- ...mand.yml => add-copy-metadata-command.yml} | 2 +- doc/user/project/quick_actions.md | 2 +- .../quick_actions/interpret_service_spec.rb | 24 +++++++++---------- 4 files changed, 23 insertions(+), 23 deletions(-) rename changelogs/unreleased/{add-inherit-command.yml => add-copy-metadata-command.yml} (62%) diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb index 28fa887bf2d..87937fef8f4 100644 --- a/app/services/quick_actions/interpret_service.rb +++ b/app/services/quick_actions/interpret_service.rb @@ -269,22 +269,22 @@ module QuickActions end desc 'Copy labels and milestone from other issue or merge request' - explanation do |issueable_id| - "Copy labels and milestone from issue or merge_request \"#{issueable_id}\"." + explanation do |issuable_id| + "Copy labels and milestone from issue or merge_request \"#{issuable_id}\"." end - params '< #issue | !merge_request >' + params '#issue | !merge_request' condition do issuable.persisted? && current_user.can?(:"update_#{issuable.to_ability_name}", issuable) end - command :copy_metadata do |issueable_id| - reference_type = issueable_id.include?("#") ? :issue : :merge_request - issue = extract_references(issueable_id, reference_type).first + command :copy_metadata do |issuable_id| + source_issuable = extract_references(issuable_id, :issue).first + source_issuable = extract_references(issuable_id, :merge_request).first if !source_issuable.present? - if issue.present? && issue.project.id == issuable.project.id - @updates[:add_label_ids] = issue.labels.map(&:id) + if source_issuable.present? && source_issuable.project.id == issuable.project.id + @updates[:add_label_ids] = source_issuable.labels.map(&:id) - @updates[:milestone_id] = issue.milestone.id if issue.milestone + @updates[:milestone_id] = source_issuable.milestone.id if source_issuable.milestone end end diff --git a/changelogs/unreleased/add-inherit-command.yml b/changelogs/unreleased/add-copy-metadata-command.yml similarity index 62% rename from changelogs/unreleased/add-inherit-command.yml rename to changelogs/unreleased/add-copy-metadata-command.yml index d47aa8c7b36..3bf25ae6ce0 100644 --- a/changelogs/unreleased/add-inherit-command.yml +++ b/changelogs/unreleased/add-copy-metadata-command.yml @@ -1,5 +1,5 @@ --- -title: Add Inherit quick action +title: Add Copy metadata quick action merge_request: 16473 author: Mateusz Bajorski type: added diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md index e2e2b859d35..75799caacde 100644 --- a/doc/user/project/quick_actions.md +++ b/doc/user/project/quick_actions.md @@ -41,4 +41,4 @@ do. | `/move path/to/project` | Moves issue to another project | | `/tableflip` | Append the comment with `(╯°□°)╯︵ ┻━┻` | | `/shrug` | Append the comment with `¯\_(ツ)_/¯` | -| /copy_metadata < #issue | !merge_request > | copy_metadata labels and milestone from other issue or merge request | +| /copy_metadata < #issue | !merge_request > | Copy labels and milestone from other issue or merge request | diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb index 9a8240f9491..4aad2aaef79 100644 --- a/spec/services/quick_actions/interpret_service_spec.rb +++ b/spec/services/quick_actions/interpret_service_spec.rb @@ -308,15 +308,15 @@ describe QuickActions::InterpretService do shared_examples 'copy_metadata command' do it 'fetches issue or merge request and copies labels and milestone if content contains /copy_metadata reference' do - issueable_father # populate the issue + source_issuable # populate the issue todo_label # populate this label inreview_label # populate this label _, updates = service.execute(content, issuable) expect(updates[:add_label_ids]).to match_array([inreview_label.id, todo_label.id]) - if issueable_father.milestone - expect(updates[:milestone_id]).to eq(issueable_father.milestone.id) + if source_issuable.milestone + expect(updates[:milestone_id]).to eq(source_issuable.milestone.id) else expect(updates).not_to have_key(:milestone_id) end @@ -784,17 +784,17 @@ describe QuickActions::InterpretService do end it_behaves_like 'copy_metadata command' do - let(:issueable_father) { create(:labeled_issue, project: project, labels: [inreview_label, todo_label]) } + let(:source_issuable) { create(:labeled_issue, project: project, labels: [inreview_label, todo_label]) } - let(:content) { "/copy_metadata #{issueable_father.to_reference}" } + let(:content) { "/copy_metadata #{source_issuable.to_reference}" } let(:issuable) { issue } end - context 'when the parent issueable has a milestone' do + context 'when the parent issuable has a milestone' do it_behaves_like 'copy_metadata command' do - let(:issueable_father) { create(:labeled_issue, project: project, labels: [todo_label, inreview_label], milestone: milestone) } + let(:source_issuable) { create(:labeled_issue, project: project, labels: [todo_label, inreview_label], milestone: milestone) } - let(:content) { "/copy_metadata #{issueable_father.to_reference(project)}" } + let(:content) { "/copy_metadata #{source_issuable.to_reference(project)}" } let(:issuable) { issue } end end @@ -802,8 +802,8 @@ describe QuickActions::InterpretService do context 'cross project references' do it_behaves_like 'empty command' do let(:other_project) { create(:project, :public) } - let(:issueable_father) { create(:labeled_issue, project: other_project, labels: [todo_label, inreview_label]) } - let(:content) { "/copy_metadata #{issueable_father.to_reference(project)}" } + let(:source_issuable) { create(:labeled_issue, project: other_project, labels: [todo_label, inreview_label]) } + let(:content) { "/copy_metadata #{source_issuable.to_reference(project)}" } let(:issuable) { issue } end @@ -814,9 +814,9 @@ describe QuickActions::InterpretService do it_behaves_like 'empty command' do let(:other_project) { create(:project, :private) } - let(:issueable_father) { create(:issue, project: other_project) } + let(:source_issuable) { create(:issue, project: other_project) } - let(:content) { "/copy_metadata #{issueable_father.to_reference(project)}" } + let(:content) { "/copy_metadata #{source_issuable.to_reference(project)}" } let(:issuable) { issue } end end From 593e3ffc325a600a070ce6c247e33412473ec651 Mon Sep 17 00:00:00 2001 From: Mateusz Bajorski Date: Thu, 1 Feb 2018 19:38:10 +0100 Subject: [PATCH 8/9] Fixed inconsistent descriptions and refactored reference checking --- app/services/quick_actions/interpret_service.rb | 4 ++-- doc/user/project/quick_actions.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb index 87937fef8f4..1a0e27d551a 100644 --- a/app/services/quick_actions/interpret_service.rb +++ b/app/services/quick_actions/interpret_service.rb @@ -270,7 +270,7 @@ module QuickActions desc 'Copy labels and milestone from other issue or merge request' explanation do |issuable_id| - "Copy labels and milestone from issue or merge_request \"#{issuable_id}\"." + "Copy labels and milestone from issue or merge_request #{issuable_id}." end params '#issue | !merge_request' condition do @@ -279,7 +279,7 @@ module QuickActions end command :copy_metadata do |issuable_id| source_issuable = extract_references(issuable_id, :issue).first - source_issuable = extract_references(issuable_id, :merge_request).first if !source_issuable.present? + source_issuable ||= extract_references(issuable_id, :merge_request).first if source_issuable.present? && source_issuable.project.id == issuable.project.id @updates[:add_label_ids] = source_issuable.labels.map(&:id) diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md index 75799caacde..3e3b699edc4 100644 --- a/doc/user/project/quick_actions.md +++ b/doc/user/project/quick_actions.md @@ -41,4 +41,4 @@ do. | `/move path/to/project` | Moves issue to another project | | `/tableflip` | Append the comment with `(╯°□°)╯︵ ┻━┻` | | `/shrug` | Append the comment with `¯\_(ツ)_/¯` | -| /copy_metadata < #issue | !merge_request > | Copy labels and milestone from other issue or merge request | +| /copy_metadata #issue | !merge_request | Copy labels and milestone from other issue or merge request | From db3774376aafbdea8db6840c88bd6d875cb9bac3 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 20 Apr 2018 08:28:17 +0100 Subject: [PATCH 9/9] Make /copy_metadata only handle the first issuable passed --- app/services/quick_actions/interpret_service.rb | 14 +++++++------- doc/user/project/quick_actions.md | 8 ++++---- .../quick_actions/interpret_service_spec.rb | 15 +++++++++++++-- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb index c1bcff34b6f..bc4febf61f0 100644 --- a/app/services/quick_actions/interpret_service.rb +++ b/app/services/quick_actions/interpret_service.rb @@ -269,21 +269,21 @@ module QuickActions end desc 'Copy labels and milestone from other issue or merge request' - explanation do |issuable_id| - "Copy labels and milestone from issue or merge_request #{issuable_id}." + explanation do |source_issuable| + "Copy labels and milestone from #{source_issuable.to_reference}." end params '#issue | !merge_request' condition do issuable.persisted? && current_user.can?(:"update_#{issuable.to_ability_name}", issuable) end - command :copy_metadata do |issuable_id| - source_issuable = extract_references(issuable_id, :issue).first - source_issuable ||= extract_references(issuable_id, :merge_request).first - + parse_params do |issuable_param| + extract_references(issuable_param, :issue).first || + extract_references(issuable_param, :merge_request).first + end + command :copy_metadata do |source_issuable| if source_issuable.present? && source_issuable.project.id == issuable.project.id @updates[:add_label_ids] = source_issuable.labels.map(&:id) - @updates[:milestone_id] = source_issuable.milestone.id if source_issuable.milestone end end diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md index 3e3b699edc4..2f4ed3493c2 100644 --- a/doc/user/project/quick_actions.md +++ b/doc/user/project/quick_actions.md @@ -38,7 +38,7 @@ do. | `/award :emoji:` | Toggle award for :emoji: | | `/board_move ~column` | Move issue to column on the board | | `/duplicate #issue` | Closes this issue and marks it as a duplicate of another issue | -| `/move path/to/project` | Moves issue to another project | -| `/tableflip` | Append the comment with `(╯°□°)╯︵ ┻━┻` | -| `/shrug` | Append the comment with `¯\_(ツ)_/¯` | -| /copy_metadata #issue | !merge_request | Copy labels and milestone from other issue or merge request | +| `/move path/to/project` | Moves issue to another project | +| `/tableflip` | Append the comment with `(╯°□°)╯︵ ┻━┻` | +| `/shrug` | Append the comment with `¯\_(ツ)_/¯` | +| /copy_metadata #issue | !merge_request | Copy labels and milestone from other issue or merge request | diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb index 4aad2aaef79..bd835a1fca6 100644 --- a/spec/services/quick_actions/interpret_service_spec.rb +++ b/spec/services/quick_actions/interpret_service_spec.rb @@ -775,8 +775,8 @@ describe QuickActions::InterpretService do end context '/copy_metadata command' do - let!(:todo_label) { create(:label, project: project, title: 'To Do') } - let!(:inreview_label) { create(:label, project: project, title: 'In Review') } + let(:todo_label) { create(:label, project: project, title: 'To Do') } + let(:inreview_label) { create(:label, project: project, title: 'In Review') } it_behaves_like 'empty command' do let(:content) { '/copy_metadata' } @@ -799,6 +799,17 @@ describe QuickActions::InterpretService do end end + context 'when more than one issuable is passed' do + it_behaves_like 'copy_metadata command' do + let(:source_issuable) { create(:labeled_issue, project: project, labels: [inreview_label, todo_label]) } + let(:other_label) { create(:label, project: project, title: 'Other') } + let(:other_source_issuable) { create(:labeled_issue, project: project, labels: [other_label]) } + + let(:content) { "/copy_metadata #{source_issuable.to_reference} #{other_source_issuable.to_reference}" } + let(:issuable) { issue } + end + end + context 'cross project references' do it_behaves_like 'empty command' do let(:other_project) { create(:project, :public) }