diff options
author | Z.J. van de Weg <zegerjan@gitlab.com> | 2016-09-20 19:01:33 +0300 |
---|---|---|
committer | Z.J. van de Weg <zegerjan@gitlab.com> | 2016-09-22 17:42:11 +0300 |
commit | 6de9859263434d3a27f0a9c91ff5285c94816904 (patch) | |
tree | abed0e2c6227a71a797acbf129c2dc22243771ee | |
parent | 7cb7787a8b7a84ed14484252ecc379b70ba27086 (diff) |
Format messages for Slack
-rw-r--r-- | app/controllers/integrations_controller.rb | 6 | ||||
-rw-r--r-- | app/services/integrations/base_service.rb | 79 | ||||
-rw-r--r-- | app/services/integrations/issue_service.rb | 6 | ||||
-rw-r--r-- | app/services/integrations/merge_request_service.rb | 10 | ||||
-rw-r--r-- | app/services/integrations/pipeline_service.rb | 8 | ||||
-rw-r--r-- | app/services/integrations/project_snippet_service.rb | 22 | ||||
-rw-r--r-- | app/views/projects/integrations/_form.html.haml | 16 | ||||
-rw-r--r-- | app/views/projects/integrations/index.html.haml | 9 | ||||
-rw-r--r-- | app/views/projects/integrations/new.html.haml | 4 | ||||
-rw-r--r-- | spec/controllers/integrations_controller_spec.rb | 2 | ||||
-rw-r--r-- | spec/services/integrations/issue_service_spec.rb | 5 |
11 files changed, 109 insertions, 58 deletions
diff --git a/app/controllers/integrations_controller.rb b/app/controllers/integrations_controller.rb index a48015c8b98..bb2705f1ff9 100644 --- a/app/controllers/integrations_controller.rb +++ b/app/controllers/integrations_controller.rb @@ -37,10 +37,10 @@ class IntegrationsController < ApplicationController case command when '/issue' Integrations::IssueService - when '/merge_request' + when '/merge-request' Integrations::MergeRequestService - when '/environment' - Integrations::EnvironmentService + when '/pipeline' + Integrations::PipelineService when '/snippet' Integrations::ProjectSnippetService end diff --git a/app/services/integrations/base_service.rb b/app/services/integrations/base_service.rb index 2e72c12b5f5..4f91dc7ec1c 100644 --- a/app/services/integrations/base_service.rb +++ b/app/services/integrations/base_service.rb @@ -13,23 +13,15 @@ module Integrations private - def resource_id - if params[:text].is_a?(Integer) || params[:text].match(/\A\d+\z/) - params[:text].to_i - else - nil - end - end - def klass raise NotImplementedError end def find_resource - raise NotImplementedError + collection.find_by(iid: resource_id) end - def title + def title(*args) raise NotImplementedError end @@ -37,16 +29,16 @@ module Integrations raise NotImplementedError end - # Used when returning a collection - def to_attachment(resource) - { - "title": "Title", - "text": "Testing *right now!*", - "mrkdwn_in": [ - "text", - "pretext" - ] - } + def resource_id + if params[:text].is_a?(Integer) || params[:text].match(/\A\d+\z/) + params[:text].to_i + else + nil + end + end + + def fallback(*args) + raise NotImplementedError end def collection @@ -61,18 +53,14 @@ module Integrations return no_search_results if resource.empty? { - text: "Search results for #{params[:text]}", response_type: :ephemeral, - attachments: resource.map { |item| to_attachment(item) } + text: "Search results for #{params[:text]}", + attachments: resource.map { |item| small_attachment(item) } } else { - text: slack_format(title(resource)), response_type: :in_channel, - mrkdwn_in: [ - :text, - :pretext - ] + attachments: [ large_attachment(resource) ] } end end @@ -84,8 +72,7 @@ module Integrations def no_search_results { text: "No search results for #{params[:text]}. :(", - response_type: :ephemeral, - attachments: [] + response_type: :ephemeral } end @@ -95,5 +82,39 @@ module Integrations response_type: :ephemeral } end + + def large_attachment(issuable) + small_attachment(issuable).merge(fields: fields(issuable)) + end + + def small_attachment(issuable) + { + fallback: issuable.title, + title: title(issuable), + title_link: link(issuable), + text: issuable.description || "", # Slack doesn't like null + color: "#C95823" + } + end + + def fields(issuable) + result = [ + { + title: 'Author', + value: issuable.author.name, + short: true + } + ] + + if issuable.assignee + result << { + title: 'Assignee', + value: issuable.assignee.name, + short: true + } + end + + result + end end end diff --git a/app/services/integrations/issue_service.rb b/app/services/integrations/issue_service.rb index 6d6453b7e4c..b00901afe3d 100644 --- a/app/services/integrations/issue_service.rb +++ b/app/services/integrations/issue_service.rb @@ -8,7 +8,7 @@ module Integrations end def title(issue) - "[##{issue.iid} #{issue.title}](#{link(issue)})" + format("##{issue.iid} #{issue.title}") end def link(issue) @@ -16,9 +16,5 @@ module Integrations project, issue) end - - def find_resource - collection.find_by(iid: params[:text]) - end end end diff --git a/app/services/integrations/merge_request_service.rb b/app/services/integrations/merge_request_service.rb index d5a95821824..6d8b3485cb5 100644 --- a/app/services/integrations/merge_request_service.rb +++ b/app/services/integrations/merge_request_service.rb @@ -7,8 +7,12 @@ module Integrations MergeRequest end + def collection + klass.where(target_project: project) + end + def title(merge_request) - "[!#{merge_request.iid} #{merge_request.title}](#{link(merge_request)})" + format("!#{merge_request.iid} #{merge_request.title}") end def link(merge_request) @@ -16,9 +20,5 @@ module Integrations project, merge_request) end - - def find_resource - collection.find_by(iid: params[:text]) - end end end diff --git a/app/services/integrations/pipeline_service.rb b/app/services/integrations/pipeline_service.rb index 738bd19f581..d4562fe6ecd 100644 --- a/app/services/integrations/pipeline_service.rb +++ b/app/services/integrations/pipeline_service.rb @@ -27,7 +27,7 @@ module Integrations end def title(pipeline) - "[##{pipeline.id} Pipeline for #{pipeline.ref}: #{pipeline.status}](#{link(pipeline)})" + "##{pipeline.id} Pipeline for #{pipeline.ref}: #{pipeline.status}" end def link(pipeline) @@ -36,9 +36,11 @@ module Integrations pipeline) end - def attachment(pipeline) + def large_attachment(pipeline) { - text: "Status: #{pipeline.status}", + fallback: title(pipeline), + title: title(pipeline), + title_link: link(pipeline), color: "#C95823" } end diff --git a/app/services/integrations/project_snippet_service.rb b/app/services/integrations/project_snippet_service.rb index 20eca22d9fd..a363c176ed3 100644 --- a/app/services/integrations/project_snippet_service.rb +++ b/app/services/integrations/project_snippet_service.rb @@ -12,7 +12,7 @@ module Integrations end def title(snippet) - "[$#{snippet.id} #{snippet.title}](#{link(snippet)})" + format("$#{snippet.id} #{snippet.title}") end def link(snippet) @@ -26,5 +26,25 @@ module Integrations color: '#C95823', } end + + def small_attachment(snippet) + { + fallback: snippet.title, + title: title(snippet), + title_link: link(snippet), + text: snippet.description || "", # Slack doesn't like null + color: '#345' + } + end + + def fields(snippet) + [ + { + title: 'Author', + value: snippet.author, + short: true + } + ] + end end end diff --git a/app/views/projects/integrations/_form.html.haml b/app/views/projects/integrations/_form.html.haml index ddab6121011..1bb1b439996 100644 --- a/app/views/projects/integrations/_form.html.haml +++ b/app/views/projects/integrations/_form.html.haml @@ -1,18 +1,24 @@ .row.prepend-top-default.append-bottom-default .col-lg-3 %h4.prepend-top-0 - Integrations + Slack Integration (Experimental) %p - Integrations allow services to communicate with GitLab to enrich the experience. - = succeed "." do - = link_to "Read more about integrations", help_page_path("integrations") + -# TODO + In Slack, create a new custom integration, and add a slash commands for each: `/issue`, `/merge-request`, `/pipeline`, and `/snippet`. Enter each token in a new integration here. + + %p + The URL for slack to POST to is: + = integrations_trigger_url + + = succeed "." do + = link_to "Read more about Slack integration", help_page_path("integrations") = form_for [@project.namespace.becomes(Namespace), @project, @integration], html: { class: 'col-lg-9' } do |f| = form_errors(@integration) .form-group = f.label :name, 'Name', class: 'label-light' - = f.text_field :name, required: true, class: 'form-control' + = f.text_field :name, required: true, class: 'form-control', placeholder: 'Slack issue command' .form-group = f.label :external_token, 'External token', class: 'label-light' = f.text_field :external_token, class: 'form-control' diff --git a/app/views/projects/integrations/index.html.haml b/app/views/projects/integrations/index.html.haml index 6d116979368..3d228b297d8 100644 --- a/app/views/projects/integrations/index.html.haml +++ b/app/views/projects/integrations/index.html.haml @@ -1,6 +1,11 @@ - page_title "Integrations" %h3.page-title Integrations -%p.light Integrations allow other services to request data on this project. + +%p + Project integrations allow GitLab to respond to inbound webhooks from other applications. Currently GitLab has experimental support for Slack slash commands. + += succeed "." do + = link_to "Read more about integrations", help_page_path("integrations") %div - if can?(current_user, :create_integration, @project) @@ -15,7 +20,7 @@ %tr %th Name %th Enabled since - - @integrations.sort_by(&:type).each do |integration| + - @integrations.sort_by(&:name).each do |integration| %tr %td = link_to edit_namespace_project_integration_path(@project.namespace, @project, integration.id) do diff --git a/app/views/projects/integrations/new.html.haml b/app/views/projects/integrations/new.html.haml index ff1dfe4d734..f9648a20e7b 100644 --- a/app/views/projects/integrations/new.html.haml +++ b/app/views/projects/integrations/new.html.haml @@ -1,6 +1,6 @@ -- page_title 'New Integration' +- page_title 'New Slack slash command' %h3.page-title - New Integration + New Slack slash command %hr = render 'form' diff --git a/spec/controllers/integrations_controller_spec.rb b/spec/controllers/integrations_controller_spec.rb index 00c1f03690b..3aad02da4cb 100644 --- a/spec/controllers/integrations_controller_spec.rb +++ b/spec/controllers/integrations_controller_spec.rb @@ -42,7 +42,7 @@ RSpec.describe IntegrationsController, type: :controller do expect(response).to have_http_status(200) expect(json_response['response_type']).to eq 'in_channel' - expect(json_response['text']).to match /#\d+\s#{Regexp.quote(issue.title)}/ + expect(json_response['attachments']).not_to eq nil end end end diff --git a/spec/services/integrations/issue_service_spec.rb b/spec/services/integrations/issue_service_spec.rb index bf28aacc71d..55449510305 100644 --- a/spec/services/integrations/issue_service_spec.rb +++ b/spec/services/integrations/issue_service_spec.rb @@ -12,14 +12,15 @@ describe Integrations::IssueService, services: true do let(:params) { { text: issue.iid } } it 'returns the issue by IID' do - expect(subject[:text]).to match /#\d+\s#{Regexp.quote(issue.title)}/ + expect(subject[:response_type]).to be :in_channel + expect(subject[:attachments].count).to be 1 end context 'the IID is passed as string' do let(:params) { { text: issue.iid.to_s } } it 'returns the issue by IID' do - expect(subject[:text]).to match /#\d+\s#{Regexp.quote(issue.title)}/ + expect(subject[:attachments].first[:fallback]).to match /#{Regexp.quote(issue.title)}/ end end end |