Commit 0d3e2435 authored by Z.J. van de Weg's avatar Z.J. van de Weg Committed by Kamil Trzcinski

Create Slack Slash command service

parent ae71032d
...@@ -170,7 +170,7 @@ gem 'gitlab-flowdock-git-hook', '~> 1.0.1' ...@@ -170,7 +170,7 @@ gem 'gitlab-flowdock-git-hook', '~> 1.0.1'
gem 'gemnasium-gitlab-service', '~> 0.2' gem 'gemnasium-gitlab-service', '~> 0.2'
# Slack integration # Slack integration
gem 'slack-notifier', '~> 1.2.0' gem 'slack-notifier', '~> 1.5.1'
# Asana integration # Asana integration
gem 'asana', '~> 0.4.0' gem 'asana', '~> 0.4.0'
......
...@@ -687,7 +687,7 @@ GEM ...@@ -687,7 +687,7 @@ GEM
json (>= 1.8, < 3) json (>= 1.8, < 3)
simplecov-html (~> 0.10.0) simplecov-html (~> 0.10.0)
simplecov-html (0.10.0) simplecov-html (0.10.0)
slack-notifier (1.2.1) slack-notifier (1.5.1)
slop (3.6.0) slop (3.6.0)
spinach (0.8.10) spinach (0.8.10)
colorize colorize
...@@ -957,7 +957,7 @@ DEPENDENCIES ...@@ -957,7 +957,7 @@ DEPENDENCIES
sidekiq-cron (~> 0.4.4) sidekiq-cron (~> 0.4.4)
sidekiq-limit_fetch (~> 3.4) sidekiq-limit_fetch (~> 3.4)
simplecov (= 0.12.0) simplecov (= 0.12.0)
slack-notifier (~> 1.2.0) slack-notifier (~> 1.5.1)
spinach-rails (~> 0.2.1) spinach-rails (~> 0.2.1)
spinach-rerun-reporter (~> 0.0.2) spinach-rerun-reporter (~> 0.0.2)
spring (~> 1.7.0) spring (~> 1.7.0)
......
...@@ -96,6 +96,7 @@ class Project < ActiveRecord::Base ...@@ -96,6 +96,7 @@ class Project < ActiveRecord::Base
has_one :gemnasium_service, dependent: :destroy has_one :gemnasium_service, dependent: :destroy
has_one :mattermost_slash_commands_service, dependent: :destroy has_one :mattermost_slash_commands_service, dependent: :destroy
has_one :mattermost_notification_service, dependent: :destroy has_one :mattermost_notification_service, dependent: :destroy
has_one :slack_slash_commands_service, dependent: :destroy
has_one :slack_notification_service, dependent: :destroy has_one :slack_notification_service, dependent: :destroy
has_one :buildkite_service, dependent: :destroy has_one :buildkite_service, dependent: :destroy
has_one :bamboo_service, dependent: :destroy has_one :bamboo_service, dependent: :destroy
......
class SlackSlashCommandsService < ChatService
include TriggersHelper
prop_accessor :token
def can_test?
false
end
def title
'Slack Slash Command'
end
def description
"Perform common operations on GitLab in Slack"
end
def to_param
'slack_slash_commands'
end
def fields
[
{ type: 'text', name: 'token', placeholder: '' }
]
end
def trigger(params)
return nil unless valid_token?(params[:token])
user = find_chat_user(params)
unless user
url = authorize_chat_name_url(params)
return Gitlab::ChatCommands::Presenters::Access.new(url).authorize
end
Gitlab::ChatCommands::Command.new(project, user, params).execute
end
private
def find_chat_user(params)
ChatNames::FindUserService.new(self, params).execute
end
def authorize_chat_name_url(params)
ChatNames::AuthorizeUserService.new(self, params).execute
end
end
...@@ -216,11 +216,12 @@ class Service < ActiveRecord::Base ...@@ -216,11 +216,12 @@ class Service < ActiveRecord::Base
jira jira
kubernetes kubernetes
mattermost_slash_commands mattermost_slash_commands
mattermost_notification
pipelines_email pipelines_email
pivotaltracker pivotaltracker
pushover pushover
redmine redmine
mattermost_notification slack_slash_commands
slack_notification slack_notification
teamcity teamcity
] ]
......
- pretty_path_with_namespace = "#{@project ? @project.namespace.name : 'namespace'} / #{@project ? @project.name : 'name'}" - pretty_path_with_namespace = "#{@project.namespace ? @project.namespace.name : 'namespace'} / #{@project ? @project.name : 'name'}"
- run_actions_text = "Perform common operations on this project: #{pretty_path_with_namespace}" - run_actions_text = "Perform common operations on this project: #{pretty_path_with_namespace}"
.well .well
......
---
title: Refactor presenters ChatCommands
merge_request: 7846
author:
...@@ -4,7 +4,7 @@ module Gitlab ...@@ -4,7 +4,7 @@ module Gitlab
include Gitlab::Routing.url_helpers include Gitlab::Routing.url_helpers
def self.match(text) def self.match(text)
/\Adeploy\s+(?<from>.*)\s+to+\s+(?<to>.*)\z/.match(text) /\Adeploy\s+(?<from>\S+.*)\s+to+\s+(?<to>\S+.*)\z/.match(text)
end end
def self.help_message def self.help_message
......
module Gitlab
module ChatCommands
class Help < BaseCommand
# This class has to be used last, as it always matches. It has to match
# because other commands were not triggered and we want to show the help
# command
def self.match(_text)
true
end
def self.help_message
'help'
end
def self.allowed?(_project, _user)
true
end
def execute(commands)
Gitlab::ChatCommands::Presenters::Help.new(commands).present(trigger)
end
def trigger
params[:command]
end
end
end
end
...@@ -64,7 +64,7 @@ describe Gitlab::ChatCommands::Command, service: true do ...@@ -64,7 +64,7 @@ describe Gitlab::ChatCommands::Command, service: true do
context 'and user can not create deployment' do context 'and user can not create deployment' do
it 'returns action' do it 'returns action' do
expect(subject[:response_type]).to be(:ephemeral) expect(subject[:response_type]).to be(:ephemeral)
expect(subject[:text]).to start_with('Whoops! That action is not allowed') expect(subject[:text]).to start_with('Whoops! This action is not allowed')
end end
end end
...@@ -74,7 +74,7 @@ describe Gitlab::ChatCommands::Command, service: true do ...@@ -74,7 +74,7 @@ describe Gitlab::ChatCommands::Command, service: true do
end end
it 'returns action' do it 'returns action' do
expect(subject[:text]).to include('Deployment from staging to production started') expect(subject[:text]).to include('Deployment started from staging to production')
expect(subject[:response_type]).to be(:in_channel) expect(subject[:response_type]).to be(:in_channel)
end end
...@@ -91,4 +91,26 @@ describe Gitlab::ChatCommands::Command, service: true do ...@@ -91,4 +91,26 @@ describe Gitlab::ChatCommands::Command, service: true do
end end
end end
end end
describe '#match_command' do
subject { described_class.new(project, user, params).match_command.first }
context 'IssueShow is triggered' do
let(:params) { { text: 'issue show 123' } }
it { is_expected.to eq(Gitlab::ChatCommands::IssueShow) }
end
context 'IssueCreate is triggered' do
let(:params) { { text: 'issue create my title' } }
it { is_expected.to eq(Gitlab::ChatCommands::IssueCreate) }
end
context 'IssueSearch is triggered' do
let(:params) { { text: 'issue search my query' } }
it { is_expected.to eq(Gitlab::ChatCommands::IssueSearch) }
end
end
end end
...@@ -10,7 +10,7 @@ describe ChatMessage::BuildMessage do ...@@ -10,7 +10,7 @@ describe ChatMessage::BuildMessage do
tag: false, tag: false,
project_name: 'project_name', project_name: 'project_name',
project_url: 'example.gitlab.com', project_url: 'http://example.gitlab.com',
commit: { commit: {
status: status, status: status,
...@@ -48,10 +48,10 @@ describe ChatMessage::BuildMessage do ...@@ -48,10 +48,10 @@ describe ChatMessage::BuildMessage do
end end
def build_message(status_text = status) def build_message(status_text = status)
"<example.gitlab.com|project_name>:" \ "<http://example.gitlab.com|project_name>:" \
" Commit <example.gitlab.com/commit/" \ " Commit <http://example.gitlab.com/commit/" \
"97de212e80737a608d939f648d959671fb0a0142/builds|97de212e>" \ "97de212e80737a608d939f648d959671fb0a0142/builds|97de212e>" \
" of <example.gitlab.com/commits/develop|develop> branch" \ " of <http://example.gitlab.com/commits/develop|develop> branch" \
" by hacker #{status_text} in #{duration} #{'second'.pluralize(duration)}" " by hacker #{status_text} in #{duration} #{'second'.pluralize(duration)}"
end end
end end
...@@ -10,14 +10,14 @@ describe ChatMessage::IssueMessage, models: true do ...@@ -10,14 +10,14 @@ describe ChatMessage::IssueMessage, models: true do
username: 'test.user' username: 'test.user'
}, },
project_name: 'project_name', project_name: 'project_name',
project_url: 'somewhere.com', project_url: 'http://somewhere.com',
object_attributes: { object_attributes: {
title: 'Issue title', title: 'Issue title',
id: 10, id: 10,
iid: 100, iid: 100,
assignee_id: 1, assignee_id: 1,
url: 'url', url: 'http://url.com',
action: 'open', action: 'open',
state: 'opened', state: 'opened',
description: 'issue description' description: 'issue description'
...@@ -40,11 +40,11 @@ describe ChatMessage::IssueMessage, models: true do ...@@ -40,11 +40,11 @@ describe ChatMessage::IssueMessage, models: true do
context 'open' do context 'open' do
it 'returns a message regarding opening of issues' do it 'returns a message regarding opening of issues' do
expect(subject.pretext).to eq( expect(subject.pretext).to eq(
'<somewhere.com|[project_name>] Issue opened by test.user') '[<http://somewhere.com|project_name>] Issue opened by test.user')
expect(subject.attachments).to eq([ expect(subject.attachments).to eq([
{ {
title: "#100 Issue title", title: "#100 Issue title",
title_link: "url", title_link: "http://url.com",
text: "issue description", text: "issue description",
color: color, color: color,
} }
...@@ -60,7 +60,7 @@ describe ChatMessage::IssueMessage, models: true do ...@@ -60,7 +60,7 @@ describe ChatMessage::IssueMessage, models: true do
it 'returns a message regarding closing of issues' do it 'returns a message regarding closing of issues' do
expect(subject.pretext). to eq( expect(subject.pretext). to eq(
'<somewhere.com|[project_name>] Issue <url|#100 Issue title> closed by test.user') '[<http://somewhere.com|project_name>] Issue <http://url.com|#100 Issue title> closed by test.user')
expect(subject.attachments).to be_empty expect(subject.attachments).to be_empty
end end
end end
......
...@@ -10,14 +10,14 @@ describe ChatMessage::MergeMessage, models: true do ...@@ -10,14 +10,14 @@ describe ChatMessage::MergeMessage, models: true do
username: 'test.user' username: 'test.user'
}, },
project_name: 'project_name', project_name: 'project_name',
project_url: 'somewhere.com', project_url: 'http://somewhere.com',
object_attributes: { object_attributes: {
title: "Issue title\nSecond line", title: "Issue title\nSecond line",
id: 10, id: 10,
iid: 100, iid: 100,
assignee_id: 1, assignee_id: 1,
url: 'url', url: 'http://url.com',
state: 'opened', state: 'opened',
description: 'issue description', description: 'issue description',
source_branch: 'source_branch', source_branch: 'source_branch',
...@@ -31,8 +31,8 @@ describe ChatMessage::MergeMessage, models: true do ...@@ -31,8 +31,8 @@ describe ChatMessage::MergeMessage, models: true do
context 'open' do context 'open' do
it 'returns a message regarding opening of merge requests' do it 'returns a message regarding opening of merge requests' do
expect(subject.pretext).to eq( expect(subject.pretext).to eq(
'test.user opened <somewhere.com/merge_requests/100|merge request !100> '\ 'test.user opened <http://somewhere.com/merge_requests/100|merge request !100> '\
'in <somewhere.com|project_name>: *Issue title*') 'in <http://somewhere.com|project_name>: *Issue title*')
expect(subject.attachments).to be_empty expect(subject.attachments).to be_empty
end end
end end
...@@ -43,8 +43,8 @@ describe ChatMessage::MergeMessage, models: true do ...@@ -43,8 +43,8 @@ describe ChatMessage::MergeMessage, models: true do
end end
it 'returns a message regarding closing of merge requests' do it 'returns a message regarding closing of merge requests' do
expect(subject.pretext).to eq( expect(subject.pretext).to eq(
'test.user closed <somewhere.com/merge_requests/100|merge request !100> '\ 'test.user closed <http://somewhere.com/merge_requests/100|merge request !100> '\
'in <somewhere.com|project_name>: *Issue title*') 'in <http://somewhere.com|project_name>: *Issue title*')
expect(subject.attachments).to be_empty expect(subject.attachments).to be_empty
end end
end end
......
...@@ -11,15 +11,15 @@ describe ChatMessage::NoteMessage, models: true do ...@@ -11,15 +11,15 @@ describe ChatMessage::NoteMessage, models: true do
avatar_url: 'http://fakeavatar' avatar_url: 'http://fakeavatar'
}, },
project_name: 'project_name', project_name: 'project_name',
project_url: 'somewhere.com', project_url: 'http://somewhere.com',
repository: { repository: {
name: 'project_name', name: 'project_name',
url: 'somewhere.com', url: 'http://somewhere.com',
}, },
object_attributes: { object_attributes: {
id: 10, id: 10,
note: 'comment on a commit', note: 'comment on a commit',
url: 'url', url: 'http://url.com',
noteable_type: 'Commit' noteable_type: 'Commit'
} }
} }
...@@ -37,8 +37,8 @@ describe ChatMessage::NoteMessage, models: true do ...@@ -37,8 +37,8 @@ describe ChatMessage::NoteMessage, models: true do
it 'returns a message regarding notes on commits' do it 'returns a message regarding notes on commits' do
message = described_class.new(@args) message = described_class.new(@args)
expect(message.pretext).to eq("test.user <url|commented on " \ expect(message.pretext).to eq("test.user <http://url.com|commented on " \
"commit 5f163b2b> in <somewhere.com|project_name>: " \ "commit 5f163b2b> in <http://somewhere.com|project_name>: " \
"*Added a commit message*") "*Added a commit message*")
expected_attachments = [ expected_attachments = [
{ {
...@@ -63,8 +63,8 @@ describe ChatMessage::NoteMessage, models: true do ...@@ -63,8 +63,8 @@ describe ChatMessage::NoteMessage, models: true do
it 'returns a message regarding notes on a merge request' do it 'returns a message regarding notes on a merge request' do
message = described_class.new(@args) message = described_class.new(@args)
expect(message.pretext).to eq("test.user <url|commented on " \ expect(message.pretext).to eq("test.user <http://url.com|commented on " \
"merge request !30> in <somewhere.com|project_name>: " \ "merge request !30> in <http://somewhere.com|project_name>: " \
"*merge request title*") "*merge request title*")
expected_attachments = [ expected_attachments = [
{ {
...@@ -90,8 +90,8 @@ describe ChatMessage::NoteMessage, models: true do ...@@ -90,8 +90,8 @@ describe ChatMessage::NoteMessage, models: true do
it 'returns a message regarding notes on an issue' do it 'returns a message regarding notes on an issue' do
message = described_class.new(@args) message = described_class.new(@args)
expect(message.pretext).to eq( expect(message.pretext).to eq(
"test.user <url|commented on " \ "test.user <http://url.com|commented on " \
"issue #20> in <somewhere.com|project_name>: " \ "issue #20> in <http://somewhere.com|project_name>: " \
"*issue title*") "*issue title*")
expected_attachments = [ expected_attachments = [
{ {
...@@ -115,8 +115,8 @@ describe ChatMessage::NoteMessage, models: true do ...@@ -115,8 +115,8 @@ describe ChatMessage::NoteMessage, models: true do
it 'returns a message regarding notes on a project snippet' do it 'returns a message regarding notes on a project snippet' do
message = described_class.new(@args) message = described_class.new(@args)
expect(message.pretext).to eq("test.user <url|commented on " \ expect(message.pretext).to eq("test.user <http://url.com|commented on " \
"snippet #5> in <somewhere.com|project_name>: " \ "snippet #5> in <http://somewhere.com|project_name>: " \
"*snippet title*") "*snippet title*")
expected_attachments = [ expected_attachments = [
{ {
......
...@@ -10,7 +10,7 @@ describe ChatMessage::PushMessage, models: true do ...@@ -10,7 +10,7 @@ describe ChatMessage::PushMessage, models: true do
project_name: 'project_name', project_name: 'project_name',
ref: 'refs/heads/master', ref: 'refs/heads/master',
user_name: 'test.user', user_name: 'test.user',
project_url: 'url' project_url: 'http://url.com'
} }
end end
...@@ -19,20 +19,20 @@ describe ChatMessage::PushMessage, models: true do ...@@ -19,20 +19,20 @@ describe ChatMessage::PushMessage, models: true do
context 'push' do context 'push' do
before do before do
args[:commits] = [ args[:commits] = [
{ message: 'message1', url: 'url1', id: 'abcdefghijkl', author: { name: 'author1' } }, { message: 'message1', url: 'http://url1.com', id: 'abcdefghijkl', author: { name: 'author1' } },
{ message: 'message2', url: 'url2', id: '123456789012', author: { name: 'author2' } }, { message: 'message2', url: 'http://url2.com', id: '123456789012', author: { name: 'author2' } },
] ]
end end
it 'returns a message regarding pushes' do it 'returns a message regarding pushes' do
expect(subject.pretext).to eq( expect(subject.pretext).to eq(
'test.user pushed to branch <url/commits/master|master> of '\ 'test.user pushed to branch <http://url.com/commits/master|master> of '\
'<url|project_name> (<url/compare/before...after|Compare changes>)' '<http://url.com|project_name> (<http://url.com/compare/before...after|Compare changes>)'
) )
expect(subject.attachments).to eq([ expect(subject.attachments).to eq([
{ {
text: "<url1|abcdefgh>: message1 - author1\n"\ text: "<http://url1.com|abcdefgh>: message1 - author1\n"\
"<url2|12345678>: message2 - author2", "<http://url2.com|12345678>: message2 - author2",
color: color, color: color,
} }
]) ])
...@@ -47,14 +47,14 @@ describe ChatMessage::PushMessage, models: true do ...@@ -47,14 +47,14 @@ describe ChatMessage::PushMessage, models: true do
project_name: 'project_name', project_name: 'project_name',
ref: 'refs/tags/new_tag', ref: 'refs/tags/new_tag',
user_name: 'test.user', user_name: 'test.user',
project_url: 'url' project_url: 'http://url.com'
} }
end end
it 'returns a message regarding pushes' do it 'returns a message regarding pushes' do
expect(subject.pretext).to eq('test.user pushed new tag ' \ expect(subject.pretext).to eq('test.user pushed new tag ' \
'<url/commits/new_tag|new_tag> to ' \ '<http://url.com/commits/new_tag|new_tag> to ' \
'<url|project_name>') '<http://url.com|project_name>')
expect(subject.attachments).to be_empty expect(subject.attachments).to be_empty
end end
end end
...@@ -66,8 +66,8 @@ describe ChatMessage::PushMessage, models: true do ...@@ -66,8 +66,8 @@ describe ChatMessage::PushMessage, models: true do
it 'returns a message regarding a new branch' do it 'returns a message regarding a new branch' do
expect(subject.pretext).to eq( expect(subject.pretext).to eq(
'test.user pushed new branch <url/commits/master|master> to '\ 'test.user pushed new branch <http://url.com/commits/master|master> to '\
'<url|project_name>' '<http://url.com|project_name>'
) )
expect(subject.attachments).to be_empty expect(subject.attachments).to be_empty
end end
...@@ -80,7 +80,7 @@ describe ChatMessage::PushMessage, models: true do ...@@ -80,7 +80,7 @@ describe ChatMessage::PushMessage, models: true do
it 'returns a message regarding a removed branch' do it 'returns a message regarding a removed branch' do
expect(subject.pretext).to eq( expect(subject.pretext).to eq(
'test.user removed branch master from <url|project_name>' 'test.user removed branch master from <http://url.com|project_name>'
) )
expect(subject.attachments).to be_empty expect(subject.attachments).to be_empty
end end
......
...@@ -10,10 +10,10 @@ describe ChatMessage::WikiPageMessage, models: true do ...@@ -10,10 +10,10 @@ describe ChatMessage::WikiPageMessage, models: true do
username: 'test.user' username: 'test.user'
}, },
project_name: 'project_name', project_name: 'project_name',
project_url: 'somewhere.com', project_url: 'http://somewhere.com',
object_attributes: { object_attributes: {
title: 'Wiki page title', title: 'Wiki page title',
url: 'url', url: 'http://url.com',
content: 'Wiki page description' content: 'Wiki page description'
} }
} }
...@@ -25,7 +25,7 @@ describe ChatMessage::WikiPageMessage, models: true do ...@@ -25,7 +25,7 @@ describe ChatMessage::WikiPageMessage, models: true do
it 'returns a message that a new wiki page was created' do it 'returns a message that a new wiki page was created' do
expect(subject.pretext).to eq( expect(subject.pretext).to eq(
'test.user created <url|wiki page> in <somewhere.com|project_name>: '\ 'test.user created <http://url.com|wiki page> in <http://somewhere.com|project_name>: '\
'*Wiki page title*') '*Wiki page title*')
end end
end end
...@@ -35,7 +35,7 @@ describe ChatMessage::WikiPageMessage, models: true do ...@@ -35,7 +35,7 @@ describe ChatMessage::WikiPageMessage, models: true do
it 'returns a message that a wiki page was updated' do it 'returns a message that a wiki page was updated' do
expect(subject.pretext).to eq( expect(subject.pretext).to eq(
'test.user edited <url|wiki page> in <somewhere.com|project_name>: '\ 'test.user edited <http://url.com|wiki page> in <http://somewhere.com|project_name>: '\
'*Wiki page title*') '*Wiki page title*')
end end
end end
......
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