Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
8b8c552e
Commit
8b8c552e
authored
Aug 14, 2018
by
Jarka Kadlecová
Committed by
Jarka Košanová
Sep 06, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Quick action for adding/removing epic to issues
parent
f401f3b6
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
360 additions
and
3 deletions
+360
-3
doc/user/project/quick_actions.md
doc/user/project/quick_actions.md
+2
-0
ee/app/services/ee/issues/update_service.rb
ee/app/services/ee/issues/update_service.rb
+19
-0
ee/app/services/ee/quick_actions/interpret_service.rb
ee/app/services/ee/quick_actions/interpret_service.rb
+30
-0
ee/changelogs/unreleased/6959-add-epic-quick.yml
ee/changelogs/unreleased/6959-add-epic-quick.yml
+5
-0
ee/spec/services/ee/issues/create_service_spec.rb
ee/spec/services/ee/issues/create_service_spec.rb
+34
-0
ee/spec/services/ee/issues/update_service_spec.rb
ee/spec/services/ee/issues/update_service_spec.rb
+87
-2
ee/spec/services/ee/notes/quick_actions_service_spec.rb
ee/spec/services/ee/notes/quick_actions_service_spec.rb
+112
-0
ee/spec/services/quick_actions/interpret_service_spec.rb
ee/spec/services/quick_actions/interpret_service_spec.rb
+71
-1
No files found.
doc/user/project/quick_actions.md
View file @
8b8c552e
...
...
@@ -47,6 +47,8 @@ do.
|
`/shrug`
| Append the comment with
`¯\_(ツ)_/¯`
|
|
<code>
/copy_metadata #issue
|
!merge_request
</code>
| Copy labels and milestone from other issue or merge request |
|
`/confidential`
| Makes the issue confidential |
|
`/epic <group&epic | Epic URL>`
| Adds an issue to an epic |
|
`/remove_epic`
| Removes an issue from an epic |
Note: In GitLab Starter every issue can have more than one assignee, so commands
`/assign`
,
`/unassign`
and
`/reassign`
support multiple assignees.
ee/app/services/ee/issues/update_service.rb
View file @
8b8c552e
...
...
@@ -7,6 +7,7 @@ module EE
override
:execute
def
execute
(
issue
)
handle_epic
(
issue
)
result
=
super
if
issue
.
previous_changes
.
include?
(
:milestone_id
)
&&
issue
.
epic
...
...
@@ -15,6 +16,24 @@ module EE
result
end
private
def
handle_epic
(
issue
)
return
unless
params
.
key?
(
:epic
)
epic_param
=
params
.
delete
(
:epic
)
if
epic_param
EpicIssues
::
CreateService
.
new
(
epic_param
,
current_user
,
{
target_issue:
issue
}).
execute
else
link
=
EpicIssue
.
find_by
(
issue_id:
issue
.
id
)
return
unless
link
EpicIssues
::
DestroyService
.
new
(
link
,
current_user
).
execute
end
end
end
end
end
ee/app/services/ee/quick_actions/interpret_service.rb
View file @
8b8c552e
...
...
@@ -47,6 +47,36 @@ module EE
command
:clear_weight
do
@updates
[
:weight
]
=
nil
end
desc
'Add to epic'
explanation
'Adds an issue to an epic.'
condition
do
issuable
.
is_a?
(
::
Issue
)
&&
issuable
.
project
.
group
&
.
feature_available?
(
:epics
)
&&
current_user
.
can?
(
:"admin_
#{
issuable
.
to_ability_name
}
"
,
issuable
)
end
params
'<group&epic | Epic URL>'
command
:epic
do
|
epic_param
|
@updates
[
:epic
]
=
extract_epic
(
epic_param
)
end
desc
'Remove from epic'
explanation
'Removes an issue from an epic.'
condition
do
issuable
.
is_a?
(
::
Issue
)
&&
issuable
.
persisted?
&&
issuable
.
project
.
group
&
.
feature_available?
(
:epics
)
&&
current_user
.
can?
(
:"admin_
#{
issuable
.
to_ability_name
}
"
,
issuable
)
end
command
:remove_epic
do
@updates
[
:epic
]
=
nil
end
def
extract_epic
(
params
)
return
nil
if
params
.
nil?
extract_references
(
params
,
:epic
).
first
end
end
end
end
ee/changelogs/unreleased/6959-add-epic-quick.yml
0 → 100644
View file @
8b8c552e
---
title
:
Quick action for adding/removing epic to issues
merge_request
:
6934
author
:
type
:
added
ee/spec/services/ee/issues/create_service_spec.rb
0 → 100644
View file @
8b8c552e
# frozen_string_literal: true
require
'spec_helper'
describe
Issues
::
CreateService
do
let
(
:group
)
{
create
(
:group
)
}
let
(
:project
)
{
create
(
:project
,
group:
group
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:issue
)
{
described_class
.
new
(
project
,
user
,
opts
).
execute
}
before
do
stub_licensed_features
(
epics:
true
)
project
.
add_maintainer
(
user
)
end
context
'quick actions'
do
context
'/epic action'
do
let
(
:epic
)
{
create
(
:epic
,
group:
group
)
}
let
(
:opts
)
do
{
title:
'New issue'
,
description:
"/epic
#{
epic
.
to_reference
(
project
)
}
"
}
end
it
'adds an issue to the passed epic'
do
expect
(
issue
).
to
be_persisted
expect
(
issue
.
epic
).
to
eq
(
epic
)
end
end
end
end
ee/spec/services/ee/issues/update_service_spec.rb
View file @
8b8c552e
...
...
@@ -2,9 +2,10 @@
require
'spec_helper'
describe
Issues
::
UpdateService
do
let
(
:issue
)
{
create
(
:issue
)
}
let
(
:group
)
{
create
(
:group
)
}
let
(
:project
)
{
create
(
:project
,
group:
group
)
}
let
(
:issue
)
{
create
(
:issue
,
project:
project
)
}
let
(
:user
)
{
issue
.
author
}
let
(
:project
)
{
issue
.
project
}
describe
'execute'
do
def
update_issue
(
opts
)
...
...
@@ -33,5 +34,89 @@ describe Issues::UpdateService do
end
end
end
context
'assigning epic'
do
before
do
stub_licensed_features
(
epics:
true
)
group
.
add_maintainer
(
user
)
end
let
(
:epic
)
{
create
(
:epic
,
group:
group
)
}
context
'when issue does not belong to an epic yet'
do
it
'assigns an issue to the provided epic'
do
expect
{
update_issue
(
epic:
epic
)
}.
to
change
{
issue
.
reload
.
epic
}.
from
(
nil
).
to
(
epic
)
end
it
'creates system notes for the epic and the issue'
do
expect
{
update_issue
(
epic:
epic
)
}.
to
change
{
Note
.
count
}.
from
(
0
).
to
(
2
)
epic_note
=
Note
.
find_by
(
noteable_id:
epic
.
id
,
noteable_type:
'Epic'
)
issue_note
=
Note
.
find_by
(
noteable_id:
issue
.
id
,
noteable_type:
'Issue'
)
expect
(
epic_note
.
system_note_metadata
.
action
).
to
eq
(
'epic_issue_added'
)
expect
(
issue_note
.
system_note_metadata
.
action
).
to
eq
(
'issue_added_to_epic'
)
end
end
context
'when issue does belongs to another epic'
do
let
(
:epic2
)
{
create
(
:epic
,
group:
group
)
}
before
do
issue
.
update!
(
epic:
epic2
)
end
it
'assigns the issue passed to the provided epic'
do
expect
{
update_issue
(
epic:
epic
)
}.
to
change
{
issue
.
reload
.
epic
}.
from
(
epic2
).
to
(
epic
)
end
it
'creates system notes for the epic and the issue'
do
expect
{
update_issue
(
epic:
epic
)
}.
to
change
{
Note
.
count
}.
from
(
0
).
to
(
3
)
epic_note
=
Note
.
find_by
(
noteable_id:
epic
.
id
,
noteable_type:
'Epic'
)
epic2_note
=
Note
.
find_by
(
noteable_id:
epic2
.
id
,
noteable_type:
'Epic'
)
issue_note
=
Note
.
find_by
(
noteable_id:
issue
.
id
,
noteable_type:
'Issue'
)
expect
(
epic_note
.
system_note_metadata
.
action
).
to
eq
(
'epic_issue_moved'
)
expect
(
epic2_note
.
system_note_metadata
.
action
).
to
eq
(
'epic_issue_moved'
)
expect
(
issue_note
.
system_note_metadata
.
action
).
to
eq
(
'issue_changed_epic'
)
end
end
end
context
'removing epic'
do
before
do
stub_licensed_features
(
epics:
true
)
group
.
add_maintainer
(
user
)
end
let
(
:epic
)
{
create
(
:epic
,
group:
group
)
}
context
'when issue does not belong to an epic yet'
do
it
'does not do anything'
do
expect
{
update_issue
(
epic:
nil
)
}.
not_to
change
{
issue
.
reload
.
epic
}
end
end
context
'when issue does belongs to an epic'
do
before
do
issue
.
update!
(
epic:
epic
)
end
it
'assigns a new issue to the provided epic'
do
expect
{
update_issue
(
epic:
nil
)
}.
to
change
{
issue
.
reload
.
epic
}.
from
(
epic
).
to
(
nil
)
end
it
'creates system notes for the epic and the issue'
do
expect
{
update_issue
(
epic:
nil
)
}.
to
change
{
Note
.
count
}.
from
(
0
).
to
(
2
)
epic_note
=
Note
.
find_by
(
noteable_id:
epic
.
id
,
noteable_type:
'Epic'
)
issue_note
=
Note
.
find_by
(
noteable_id:
issue
.
id
,
noteable_type:
'Issue'
)
expect
(
epic_note
.
system_note_metadata
.
action
).
to
eq
(
'epic_issue_removed'
)
expect
(
issue_note
.
system_note_metadata
.
action
).
to
eq
(
'issue_removed_from_epic'
)
end
end
end
end
end
ee/spec/services/ee/notes/quick_actions_service_spec.rb
0 → 100644
View file @
8b8c552e
# frozen_string_literal: true
require
'spec_helper'
describe
Notes
::
QuickActionsService
do
let
(
:group
)
{
create
(
:group
)
}
let
(
:project
)
{
create
(
:project
,
group:
group
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:issue
)
{
create
(
:issue
,
project:
project
)
}
let
(
:epic
)
{
create
(
:epic
,
group:
group
)}
let
(
:service
)
{
described_class
.
new
(
project
,
user
)
}
before
do
project
.
add_maintainer
(
user
)
end
def
execute
(
note
)
content
,
command_params
=
service
.
extract_commands
(
note
)
service
.
execute
(
command_params
,
note
)
content
end
describe
'/epic'
do
let
(
:note_text
)
{
"/epic
#{
epic
.
to_reference
(
project
)
}
"
}
let
(
:note
)
{
create
(
:note_on_issue
,
noteable:
issue
,
project:
project
,
note:
note_text
)
}
before
do
group
.
add_developer
(
user
)
end
context
'when epics are not enabled'
do
it
'does not assign the epic'
do
expect
(
execute
(
note
)).
to
be_empty
expect
(
issue
.
epic
).
to
be_nil
end
end
context
'when epics are enabled'
do
before
do
stub_licensed_features
(
epics:
true
)
end
context
'on an issue'
do
it
'assigns the issue to the epic'
do
expect
{
execute
(
note
)
}.
to
change
{
issue
.
reload
.
epic
}.
from
(
nil
).
to
(
epic
)
end
it
'leaves the note empty'
do
expect
(
execute
(
note
)).
to
eq
(
''
)
end
it
'creates a system note'
do
expect
{
execute
(
note
)
}.
to
change
{
Note
.
system
.
count
}.
from
(
0
).
to
(
2
)
end
end
context
'on a merge request'
do
let
(
:note_mr
)
{
create
(
:note_on_merge_request
,
project:
project
,
note:
note_text
)
}
it
'leaves the note empty'
do
expect
(
execute
(
note_mr
)).
to
be_empty
end
end
end
end
describe
'/remove_epic'
do
let
(
:note_text
)
{
"/remove_epic"
}
let
(
:note
)
{
create
(
:note_on_issue
,
noteable:
issue
,
project:
project
,
note:
note_text
)
}
before
do
issue
.
update!
(
epic:
epic
)
group
.
add_developer
(
user
)
end
context
'when epics are not enabled'
do
it
'does not remove the epic'
do
expect
(
execute
(
note
)).
to
be_empty
expect
(
issue
.
epic
).
to
eq
(
epic
)
end
end
context
'when epics are enabled'
do
before
do
stub_licensed_features
(
epics:
true
)
end
context
'on an issue'
do
it
'removes the epic'
do
expect
{
execute
(
note
)
}.
to
change
{
issue
.
reload
.
epic
}.
from
(
epic
).
to
(
nil
)
end
it
'leaves the note empty'
do
expect
(
execute
(
note
)).
to
eq
(
''
)
end
it
'creates a system note'
do
expect
{
execute
(
note
)
}.
to
change
{
Note
.
system
.
count
}.
from
(
0
).
to
(
2
)
end
end
context
'on a merge request'
do
let
(
:note_mr
)
{
create
(
:note_on_merge_request
,
project:
project
,
note:
note_text
)
}
it
'leaves the note empty'
do
expect
(
execute
(
note_mr
)).
to
be_empty
end
end
end
end
end
ee/spec/services/quick_actions/interpret_service_spec.rb
View file @
8b8c552e
...
...
@@ -5,7 +5,8 @@ describe QuickActions::InterpretService do
let
(
:developer
)
{
create
(
:user
)
}
let
(
:developer2
)
{
create
(
:user
)
}
let
(
:developer3
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
,
:public
)
}
let
(
:group
)
{
create
(
:group
)
}
let
(
:project
)
{
create
(
:project
,
:public
,
group:
group
)
}
let
(
:issue
)
{
create
(
:issue
,
project:
project
)
}
let
(
:service
)
{
described_class
.
new
(
project
,
developer
)
}
...
...
@@ -115,6 +116,75 @@ describe QuickActions::InterpretService do
end
end
end
context
'epic command'
do
let
(
:epic
)
{
create
(
:epic
,
group:
group
)}
let
(
:content
)
{
"/epic
#{
epic
.
to_reference
(
project
)
}
"
}
context
'when epics are enabled'
do
before
do
stub_licensed_features
(
epics:
true
)
end
it
'assigns an issue to an epic'
do
_
,
updates
=
service
.
execute
(
content
,
issue
)
expect
(
updates
).
to
eq
(
epic:
epic
)
end
context
'when an issue belongs to a project without group'
do
let
(
:user_project
)
{
create
(
:project
)
}
let
(
:issue
)
{
create
(
:issue
,
project:
user_project
)
}
before
do
user_project
.
add_developer
(
user
)
end
it
'does not assign an issue to an epic'
do
_
,
updates
=
service
.
execute
(
content
,
issue
)
expect
(
updates
).
to
be_empty
end
end
end
context
'when epics are disabled'
do
it
'does not recognize /epic'
do
_
,
updates
=
service
.
execute
(
content
,
issue
)
expect
(
updates
).
to
be_empty
end
end
end
context
'remove_epic command'
do
let
(
:epic
)
{
create
(
:epic
,
group:
group
)}
let
(
:content
)
{
"/remove_epic
#{
epic
.
to_reference
(
project
)
}
"
}
before
do
issue
.
update!
(
epic:
epic
)
end
context
'when epics are disabled'
do
it
'does not recognize /remove_epic'
do
_
,
updates
=
service
.
execute
(
content
,
issue
)
expect
(
updates
).
to
be_empty
end
end
context
'when epics are enabled'
do
before
do
stub_licensed_features
(
epics:
true
)
end
it
'unassigns an issue from an epic'
do
_
,
updates
=
service
.
execute
(
content
,
issue
)
expect
(
updates
).
to
eq
(
epic:
nil
)
end
end
end
end
describe
'#explain'
do
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment