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
0
Merge Requests
0
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
Boxiang Sun
gitlab-ce
Commits
d4def9cb
Commit
d4def9cb
authored
Nov 17, 2016
by
Z.J. van de Weg
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Incorporate feedback, improve presenter class
[ci skip]
parent
1b4fdb98
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
151 additions
and
91 deletions
+151
-91
app/models/project_services/chat_service.rb
app/models/project_services/chat_service.rb
+0
-4
app/models/project_services/mattermost_command_service.rb
app/models/project_services/mattermost_command_service.rb
+21
-7
app/models/service.rb
app/models/service.rb
+2
-2
config/environments/development.rb
config/environments/development.rb
+0
-3
lib/api/services.rb
lib/api/services.rb
+5
-3
lib/gitlab/chat_commands/base_command.rb
lib/gitlab/chat_commands/base_command.rb
+4
-0
lib/gitlab/chat_commands/command.rb
lib/gitlab/chat_commands/command.rb
+11
-11
lib/gitlab/chat_commands/issue_create.rb
lib/gitlab/chat_commands/issue_create.rb
+2
-0
lib/gitlab/chat_commands/issue_search.rb
lib/gitlab/chat_commands/issue_search.rb
+1
-1
lib/gitlab/chat_commands/merge_request_command.rb
lib/gitlab/chat_commands/merge_request_command.rb
+2
-2
lib/gitlab/chat_commands/merge_request_search.rb
lib/gitlab/chat_commands/merge_request_search.rb
+1
-1
lib/mattermost/presenter.rb
lib/mattermost/presenter.rb
+44
-37
spec/lib/gitlab/chat_commands/issue_create_spec.rb
spec/lib/gitlab/chat_commands/issue_create_spec.rb
+27
-5
spec/lib/gitlab/chat_commands/issue_show_spec.rb
spec/lib/gitlab/chat_commands/issue_show_spec.rb
+21
-9
spec/lib/gitlab/chat_commands/merge_request_search_spec.rb
spec/lib/gitlab/chat_commands/merge_request_search_spec.rb
+10
-6
No files found.
app/models/project_services/chat_service.rb
View file @
d4def9cb
...
@@ -18,8 +18,4 @@ class ChatService < Service
...
@@ -18,8 +18,4 @@ class ChatService < Service
def
trigger
(
params
)
def
trigger
(
params
)
raise
NotImplementedError
raise
NotImplementedError
end
end
def
chat_user_params
(
params
)
params
.
permit
()
end
end
end
app/models/project_services/mattermost_c
hat
_service.rb
→
app/models/project_services/mattermost_c
ommand
_service.rb
View file @
d4def9cb
class
MattermostC
hat
Service
<
ChatService
class
MattermostC
ommand
Service
<
ChatService
include
TriggersHelper
include
TriggersHelper
prop_accessor
:token
prop_accessor
:token
...
@@ -8,7 +8,7 @@ class MattermostChatService < ChatService
...
@@ -8,7 +8,7 @@ class MattermostChatService < ChatService
end
end
def
title
def
title
'Mattermost'
'Mattermost
Command
'
end
end
def
description
def
description
...
@@ -16,7 +16,7 @@ class MattermostChatService < ChatService
...
@@ -16,7 +16,7 @@ class MattermostChatService < ChatService
end
end
def
to_param
def
to_param
'mattermost'
'mattermost
_command
'
end
end
def
help
def
help
...
@@ -33,10 +33,24 @@ class MattermostChatService < ChatService
...
@@ -33,10 +33,24 @@ class MattermostChatService < ChatService
end
end
def
trigger
(
params
)
def
trigger
(
params
)
user
=
ChatNames
::
FindUserService
.
new
(
chat_names
,
params
).
execute
return
nil
unless
valid_token?
(
params
[
:token
])
return
Mattermost
::
Presenter
.
authorize_chat_name
(
params
)
unless
user
Mattermost
::
CommandService
.
new
(
project
,
user
,
params
.
slice
(
:command
,
:text
)).
user
=
find_chat_user
(
params
)
execute
unless
user
url
=
authorize_chat_name_url
(
params
)
return
Mattermost
::
Presenter
.
authorize_user
(
url
)
end
Mattermost
::
CommandService
.
new
(
project
,
user
,
params
).
execute
end
private
def
find_chat_user
(
params
)
ChatNames
::
FindUserService
.
new
(
chat_names
,
params
).
execute
end
def
authorize_chat_name_url
(
params
)
ChatNames
::
RequestService
.
new
(
self
,
params
).
execute
end
end
end
end
app/models/service.rb
View file @
d4def9cb
...
@@ -202,7 +202,6 @@ class Service < ActiveRecord::Base
...
@@ -202,7 +202,6 @@ class Service < ActiveRecord::Base
bamboo
bamboo
buildkite
buildkite
builds_email
builds_email
pipelines_email
bugzilla
bugzilla
campfire
campfire
custom_issue_tracker
custom_issue_tracker
...
@@ -214,7 +213,8 @@ class Service < ActiveRecord::Base
...
@@ -214,7 +213,8 @@ class Service < ActiveRecord::Base
hipchat
hipchat
irker
irker
jira
jira
mattermost_chat
mattermost_command
pipelines_email
pivotaltracker
pivotaltracker
pushover
pushover
redmine
redmine
...
...
config/environments/development.rb
View file @
d4def9cb
...
@@ -45,7 +45,4 @@ Rails.application.configure do
...
@@ -45,7 +45,4 @@ Rails.application.configure do
# Do not log asset requests
# Do not log asset requests
config
.
assets
.
quiet
=
true
config
.
assets
.
quiet
=
true
# Make hot reloading to work with Grape API
ActiveSupport
::
Dependencies
.
explicitly_unloadable_constants
<<
"API"
end
end
lib/api/services.rb
View file @
d4def9cb
...
@@ -61,6 +61,10 @@ module API
...
@@ -61,6 +61,10 @@ module API
end
end
resource
:projects
do
resource
:projects
do
desc
'Trigger a slash command'
do
detail
'Added in GitLab 8.13'
end
post
':id/services/:service_slug/trigger'
do
post
':id/services/:service_slug/trigger'
do
project
=
Project
.
find_with_namespace
(
params
[
:id
])
||
Project
.
find_by
(
id:
params
[
:id
])
project
=
Project
.
find_with_namespace
(
params
[
:id
])
||
Project
.
find_by
(
id:
params
[
:id
])
...
@@ -71,9 +75,7 @@ module API
...
@@ -71,9 +75,7 @@ module API
service
=
project
.
public_send
(
service_method
)
service
=
project
.
public_send
(
service_method
)
result
=
if
service
.
try
(
:active?
)
&&
service
.
respond_to?
(
:trigger
)
result
=
service
.
try
(
:active?
)
&&
service
.
try
(
:trigger
,
params
)
service
.
trigger
(
params
)
end
if
result
if
result
present
result
,
status:
result
[
:status
]
||
200
present
result
,
status:
result
[
:status
]
||
200
...
...
lib/gitlab/chat_commands/base_command.rb
View file @
d4def9cb
...
@@ -38,6 +38,10 @@ module Gitlab
...
@@ -38,6 +38,10 @@ module Gitlab
def
present
(
resource
)
def
present
(
resource
)
Mattermost
::
Presenter
.
present
(
resource
)
Mattermost
::
Presenter
.
present
(
resource
)
end
end
def
help
(
messages
)
Mattermost
::
Presenter
.
help
(
messages
)
end
def
find_by_iid
(
iid
)
def
find_by_iid
(
iid
)
resource
=
collection
.
find_by
(
iid:
iid
)
resource
=
collection
.
find_by
(
iid:
iid
)
...
...
lib/gitlab/chat_commands/command.rb
View file @
d4def9cb
...
@@ -13,7 +13,7 @@ module Gitlab
...
@@ -13,7 +13,7 @@ module Gitlab
def
execute
def
execute
klass
,
match
=
fetch_klass
klass
,
match
=
fetch_klass
return
help
(
help_messages
)
unless
klass
.
try
(
:available?
,
project
)
return
help
(
help_messages
,
params
[
:command
]
)
unless
klass
.
try
(
:available?
,
project
)
klass
.
new
(
project
,
current_user
,
params
).
execute
(
match
)
klass
.
new
(
project
,
current_user
,
params
).
execute
(
match
)
end
end
...
@@ -22,23 +22,23 @@ module Gitlab
...
@@ -22,23 +22,23 @@ module Gitlab
def
fetch_klass
def
fetch_klass
match
=
nil
match
=
nil
service
=
COMMANDS
.
find
do
|
klass
|
service
=
available_commands
.
find
do
|
klass
|
if
klass
.
available?
(
project
)
match
=
klass
.
match
(
command
)
false
else
match
=
klass
.
match
(
command
)
end
end
end
[
service
,
match
]
[
service
,
match
]
end
end
def
help_messages
def
help_messages
COMMANDS
.
map
do
|
klass
|
available_commands
.
map
do
|
klass
|
next
unless
klass
.
available?
(
project
)
klass
.
help_message
klass
.
help_message
end
.
compact
end
end
def
available_commands
COMMANDS
.
select
do
|
klass
|
klass
.
available?
(
project
)
end
end
end
def
command
def
command
...
...
lib/gitlab/chat_commands/issue_create.rb
View file @
d4def9cb
...
@@ -6,6 +6,8 @@ module Gitlab
...
@@ -6,6 +6,8 @@ module Gitlab
end
end
def
execute
(
match
)
def
execute
(
match
)
present
nil
unless
can?
(
current_user
,
:create_issue
,
project
)
title
=
match
[
:title
]
title
=
match
[
:title
]
description
=
match
[
:description
]
description
=
match
[
:description
]
...
...
lib/gitlab/chat_commands/issue_search.rb
View file @
d4def9cb
...
@@ -2,7 +2,7 @@ module Gitlab
...
@@ -2,7 +2,7 @@ module Gitlab
module
ChatCommands
module
ChatCommands
class
IssueSearch
<
IssueCommand
class
IssueSearch
<
IssueCommand
def
self
.
match
(
text
)
def
self
.
match
(
text
)
/\Aissue\s+search\s+(?<query>.*)/
.
match
(
text
)
/\Aissue\s+search\s+(?<query>.*)
\s*
/
.
match
(
text
)
end
end
def
self
.
help_message
def
self
.
help_message
...
...
lib/gitlab/chat_commands/merge_request_command.rb
View file @
d4def9cb
...
@@ -9,8 +9,8 @@ module Gitlab
...
@@ -9,8 +9,8 @@ module Gitlab
project
.
merge_requests
project
.
merge_requests
end
end
def
readable?
(
_
)
def
readable?
(
merge_request
)
can?
(
current_user
,
:read_merge_request
,
projec
t
)
can?
(
current_user
,
:read_merge_request
,
merge_reques
t
)
end
end
end
end
end
end
...
...
lib/gitlab/chat_commands/merge_request_search.rb
View file @
d4def9cb
...
@@ -2,7 +2,7 @@ module Gitlab
...
@@ -2,7 +2,7 @@ module Gitlab
module
ChatCommands
module
ChatCommands
class
MergeRequestSearch
<
MergeRequestCommand
class
MergeRequestSearch
<
MergeRequestCommand
def
self
.
match
(
text
)
def
self
.
match
(
text
)
/\Amergerequest\s+search\s+(?<query>.*)/
.
match
(
text
)
/\Amergerequest\s+search\s+(?<query>.*)
\s*
/
.
match
(
text
)
end
end
def
self
.
help_message
def
self
.
help_message
...
...
lib/mattermost/presenter.rb
View file @
d4def9cb
module
Mattermost
module
Mattermost
class
Presenter
class
Presenter
class
<<
self
class
<<
self
COMMAND_PREFIX
=
'/gitlab'
.
freeze
def
authorize_chat_name
(
url
)
message
=
"Hi there! We've yet to get acquainted! Please [introduce yourself](
#{
url
}
)!"
def
authorize_chat_name
(
params
)
ephemeral_response
(
message
)
url
=
ChatNames
::
RequestService
.
new
(
service
,
params
).
execute
{
response_type: :ephemeral
,
message:
"You are not authorized. Click this [link](
#{
url
}
) to authorize."
}
end
end
def
help
(
messages
)
def
help
(
messages
,
command
)
message
s
=
[
"Available commands:"
]
message
=
[
"Available commands:"
]
messages
.
each
do
|
messsage
|
messages
.
each
do
|
messsage
|
message
s
<<
"-
#{
message
}
"
message
<<
"-
#{
command
}
#{
message
}
"
end
end
{
ephemeral_response
(
messages
.
join
(
"
\n
"
))
response_type: :ephemeral
,
text:
messages
.
join
(
"
\n
"
)
}
end
end
def
not_found
def
not_found
{
ephemeral_response
(
"404 not found! GitLab couldn't find what your were looking for! :boom:"
)
response_type: :ephemeral
,
text:
"404 not found! GitLab couldn't find what your were looking for! :boom:"
,
}
end
end
def
present
(
resource
)
def
present
(
resource
)
...
@@ -51,38 +40,56 @@ module Mattermost
...
@@ -51,38 +40,56 @@ module Mattermost
private
private
def
single_resource
(
resource
)
def
single_resource
(
resource
)
message
=
title
(
resource
)
return
error
(
resource
)
if
resource
.
errors
.
any?
message
=
"###
#{
title
(
resource
)
}
"
message
<<
"
\n\n
#{
resource
.
description
}
"
if
resource
.
description
message
<<
"
\n\n
#{
resource
.
description
}
"
if
resource
.
description
{
in_channel_response
(
message
)
response_type: :in_channel
,
text:
message
}
end
end
def
multiple_resources
(
resources
)
def
multiple_resources
(
resources
)
message
=
"Multiple results were found:
\n
"
message
=
"Multiple results were found:
\n
"
message
<<
resources
.
map
{
|
resource
|
"
#{
title
(
resource
)
}
"
}.
join
(
"
\n
"
)
message
<<
resources
.
map
{
|
resource
|
"
-
#{
title
(
resource
)
}
"
}.
join
(
"
\n
"
)
{
ephemeral_response
(
message
)
response_type: :ephemeral
,
end
text:
message
}
def
error
(
resource
)
message
=
"The action was not succesfull because:
\n
"
message
<<
resource
.
errors
.
messages
.
map
{
|
message
|
"-
#{
message
}
"
}.
join
(
"
\n
"
)
ephemeral_response
(
resource
.
errors
.
messages
.
join
(
"
\n
"
)
end
end
def
title
(
resource
)
def
title
(
resource
)
"
###
[
#{
resource
.
to_reference
}
#{
resource
.
title
}
](
#{
url
(
resource
)
}
)"
"[
#{
resource
.
to_reference
}
#{
resource
.
title
}
](
#{
url
(
resource
)
}
)"
end
end
def
url
(
resource
)
def
url
(
resource
)
helper
=
Rails
.
application
.
routes
.
url_helpers
polymorphic_url
(
[
resource
.
project
.
namespace
.
becomes
(
Namespace
),
resource
.
project
,
resource
],
id:
resource_id
,
routing_type: :url
)
end
case
resource
def
ephemeral_response
(
message
)
when
Issue
{
helper
.
namespace_project_issue_url
(
resource
.
project
.
namespace
.
becomes
(
Namespace
),
resource
.
project
,
resource
)
response_type: :ephemeral
,
when
MergeRequest
text:
message
helper
.
namespace_project_merge_request_url
(
resource
.
project
.
namespace
.
becomes
(
Namespace
),
resource
.
project
,
resource
)
}
end
end
def
in_channel_response
(
message
)
{
response_type: :in_channel
,
text:
message
}
end
end
end
end
end
end
...
...
spec/lib/gitlab/chat_commands/issue_create_spec.rb
View file @
d4def9cb
...
@@ -6,9 +6,13 @@ describe Gitlab::ChatCommands::IssueCreate, service: true do
...
@@ -6,9 +6,13 @@ describe Gitlab::ChatCommands::IssueCreate, service: true do
let
(
:user
)
{
create
(
:user
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:regex_match
)
{
described_class
.
match
(
"issue create bird is the word"
)
}
let
(
:regex_match
)
{
described_class
.
match
(
"issue create bird is the word"
)
}
before
{
project
.
team
<<
[
user
,
:master
]
}
before
do
project
.
team
<<
[
user
,
:master
]
end
subject
{
described_class
.
new
(
project
,
user
).
execute
(
regex_match
)
}
subject
do
described_class
.
new
(
project
,
user
).
execute
(
regex_match
)
end
context
'without description'
do
context
'without description'
do
it
'creates the issue'
do
it
'creates the issue'
do
...
@@ -17,7 +21,7 @@ describe Gitlab::ChatCommands::IssueCreate, service: true do
...
@@ -17,7 +21,7 @@ describe Gitlab::ChatCommands::IssueCreate, service: true do
end
.
to
change
{
project
.
issues
.
count
}.
by
(
1
)
end
.
to
change
{
project
.
issues
.
count
}.
by
(
1
)
expect
(
subject
[
:response_type
]).
to
be
:in_channel
expect
(
subject
[
:response_type
]).
to
be
:in_channel
expect
(
subject
[
:text
]).
to
match
'bird is the word'
expect
(
subject
[
:text
]).
to
match
(
'bird is the word'
)
end
end
end
end
...
@@ -25,11 +29,29 @@ describe Gitlab::ChatCommands::IssueCreate, service: true do
...
@@ -25,11 +29,29 @@ describe Gitlab::ChatCommands::IssueCreate, service: true do
let
(
:description
)
{
"Surfin bird"
}
let
(
:description
)
{
"Surfin bird"
}
let
(
:regex_match
)
{
described_class
.
match
(
"issue create bird is the word
\n
#{
description
}
"
)
}
let
(
:regex_match
)
{
described_class
.
match
(
"issue create bird is the word
\n
#{
description
}
"
)
}
before
{
subject
}
before
do
subject
end
it
'creates the issue with description'
do
it
'creates the issue with description'
do
expect
(
Issue
.
last
.
description
).
to
eq
description
expect
(
Issue
.
last
.
description
).
to
eq
(
description
)
end
end
end
end
end
end
describe
'self.match'
do
it
'matches the title without description'
do
match
=
described_class
.
match
(
"issue create my title"
)
expect
(
match
[
:title
]).
to
eq
(
'my title'
)
expect
(
match
[
:description
]).
to
eq
(
""
)
end
it
'matches the title with description'
do
match
=
described_class
.
match
(
"issue create my title
\n\n
description"
)
expect
(
match
[
:title
]).
to
eq
(
'my title'
)
expect
(
match
[
:description
]).
to
eq
(
'description'
)
end
end
end
end
spec/lib/gitlab/chat_commands/issue_show_spec.rb
View file @
d4def9cb
...
@@ -2,19 +2,23 @@ require 'spec_helper'
...
@@ -2,19 +2,23 @@ require 'spec_helper'
describe
Gitlab
::
ChatCommands
::
IssueShow
,
service:
true
do
describe
Gitlab
::
ChatCommands
::
IssueShow
,
service:
true
do
describe
'#execute'
do
describe
'#execute'
do
let
(
:issue
)
{
create
(
:issue
)
}
let
(
:issue
)
{
create
(
:issue
)
}
let
(
:project
)
{
issue
.
project
}
let
(
:project
)
{
issue
.
project
}
let
(
:user
)
{
issue
.
author
}
let
(
:user
)
{
issue
.
author
}
let
(
:regex_match
)
{
described_class
.
match
(
"issue show
#{
issue
.
iid
}
"
)
}
let
(
:regex_match
)
{
described_class
.
match
(
"issue show
#{
issue
.
iid
}
"
)
}
before
{
project
.
team
<<
[
user
,
:master
]
}
before
do
project
.
team
<<
[
user
,
:master
]
end
subject
{
described_class
.
new
(
project
,
user
).
execute
(
regex_match
)
}
subject
do
described_class
.
new
(
project
,
user
).
execute
(
regex_match
)
end
context
'the issue exists'
do
context
'the issue exists'
do
it
'returns the issue'
do
it
'returns the issue'
do
expect
(
subject
[
:response_type
]).
to
be
:in_channel
expect
(
subject
[
:response_type
]).
to
be
(
:in_channel
)
expect
(
subject
[
:text
]).
to
match
issue
.
title
expect
(
subject
[
:text
]).
to
match
(
issue
.
title
)
end
end
end
end
...
@@ -22,9 +26,17 @@ describe Gitlab::ChatCommands::IssueShow, service: true do
...
@@ -22,9 +26,17 @@ describe Gitlab::ChatCommands::IssueShow, service: true do
let
(
:regex_match
)
{
described_class
.
match
(
"issue show 1234"
)
}
let
(
:regex_match
)
{
described_class
.
match
(
"issue show 1234"
)
}
it
"returns nil"
do
it
"returns nil"
do
expect
(
subject
[
:response_type
]).
to
be
:ephemeral
expect
(
subject
[
:response_type
]).
to
be
(
:ephemeral
)
expect
(
subject
[
:text
]).
to
start_with
'404 not found!'
expect
(
subject
[
:text
]).
to
start_with
(
'404 not found!'
)
end
end
end
end
end
end
describe
'self.match'
do
it
'matches the iid'
do
match
=
described_class
.
match
(
"issue show 123"
)
expect
(
match
[
:iid
]).
to
eq
(
"123"
)
end
end
end
end
spec/lib/gitlab/chat_commands/merge_request_search_spec.rb
View file @
d4def9cb
...
@@ -7,14 +7,18 @@ describe Gitlab::ChatCommands::MergeRequestSearch, service: true do
...
@@ -7,14 +7,18 @@ describe Gitlab::ChatCommands::MergeRequestSearch, service: true do
let
(
:user
)
{
merge_request
.
author
}
let
(
:user
)
{
merge_request
.
author
}
let
(
:regex_match
)
{
described_class
.
match
(
"mergerequest search
#{
merge_request
.
title
}
"
)
}
let
(
:regex_match
)
{
described_class
.
match
(
"mergerequest search
#{
merge_request
.
title
}
"
)
}
before
{
project
.
team
<<
[
user
,
:master
]
}
before
do
project
.
team
<<
[
user
,
:master
]
end
subject
{
described_class
.
new
(
project
,
user
,
{}).
execute
(
regex_match
)
}
subject
do
described_class
.
new
(
project
,
user
).
execute
(
regex_match
)
end
context
'the merge request exists'
do
context
'the merge request exists'
do
it
'returns the merge request'
do
it
'returns the merge request'
do
expect
(
subject
[
:response_type
]).
to
be
:in_channel
expect
(
subject
[
:response_type
]).
to
be
(
:in_channel
)
expect
(
subject
[
:text
]).
to
match
merge_request
.
title
expect
(
subject
[
:text
]).
to
match
(
merge_request
.
title
)
end
end
end
end
...
@@ -22,8 +26,8 @@ describe Gitlab::ChatCommands::MergeRequestSearch, service: true do
...
@@ -22,8 +26,8 @@ describe Gitlab::ChatCommands::MergeRequestSearch, service: true do
let
(
:regex_match
)
{
described_class
.
match
(
"mergerequest search 12334"
)
}
let
(
:regex_match
)
{
described_class
.
match
(
"mergerequest search 12334"
)
}
it
"returns a 404 message"
do
it
"returns a 404 message"
do
expect
(
subject
[
:response_type
]).
to
be
:ephemeral
expect
(
subject
[
:response_type
]).
to
be
(
:ephemeral
)
expect
(
subject
[
:text
]).
to
start_with
'404 not found!'
expect
(
subject
[
:text
]).
to
start_with
(
'404 not found!'
)
end
end
end
end
end
end
...
...
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