summaryrefslogtreecommitdiff
path: root/app/models
diff options
context:
space:
mode:
authorDouwe Maan <douwe@gitlab.com>2017-04-06 19:37:25 +0000
committerDouwe Maan <douwe@gitlab.com>2017-04-06 19:37:25 +0000
commit00e00cacf8cb4ce3bfb733bae47e7e594e91e294 (patch)
tree607671987a66dbb16d49738aef22616c13b6936b /app/models
parent73cb71e41c0ade92b9673a5d74c7dd78679fae91 (diff)
parent1f404065ca602593dc18aa051515fd88132ddfdf (diff)
downloadgitlab-ce-00e00cacf8cb4ce3bfb733bae47e7e594e91e294.tar.gz
Merge branch 'microsoft-teams-integration' into 'master'
adds initial microsoft teams integration See merge request !10412
Diffstat (limited to 'app/models')
-rw-r--r--app/models/project.rb1
-rw-r--r--app/models/project_services/chat_message/base_message.rb18
-rw-r--r--app/models/project_services/chat_message/issue_message.rb22
-rw-r--r--app/models/project_services/chat_message/merge_message.rb32
-rw-r--r--app/models/project_services/chat_message/note_message.rb80
-rw-r--r--app/models/project_services/chat_message/pipeline_message.rb36
-rw-r--r--app/models/project_services/chat_message/push_message.rb32
-rw-r--r--app/models/project_services/chat_message/wiki_page_message.rb18
-rw-r--r--app/models/project_services/chat_notification_service.rb20
-rw-r--r--app/models/project_services/microsoft_teams_service.rb56
-rw-r--r--app/models/service.rb1
11 files changed, 218 insertions, 98 deletions
diff --git a/app/models/project.rb b/app/models/project.rb
index c1909c6d4a8..19835a72a75 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -116,6 +116,7 @@ class Project < ActiveRecord::Base
has_one :mock_ci_service, dependent: :destroy
has_one :mock_deployment_service, dependent: :destroy
has_one :mock_monitoring_service, dependent: :destroy
+ has_one :microsoft_teams_service, dependent: :destroy
has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
has_one :forked_from_project, through: :forked_project_link
diff --git a/app/models/project_services/chat_message/base_message.rb b/app/models/project_services/chat_message/base_message.rb
index 86d271a3f69..7621a5fa2d8 100644
--- a/app/models/project_services/chat_message/base_message.rb
+++ b/app/models/project_services/chat_message/base_message.rb
@@ -2,11 +2,23 @@ require 'slack-notifier'
module ChatMessage
class BaseMessage
+ attr_reader :markdown
+ attr_reader :user_name
+ attr_reader :user_avatar
+ attr_reader :project_name
+ attr_reader :project_url
+
def initialize(params)
- raise NotImplementedError
+ @markdown = params[:markdown] || false
+ @project_name = params.dig(:project, :path_with_namespace) || params[:project_name]
+ @project_url = params.dig(:project, :web_url) || params[:project_url]
+ @user_name = params.dig(:user, :username) || params[:user_name]
+ @user_avatar = params.dig(:user, :avatar_url) || params[:user_avatar]
end
def pretext
+ return message if markdown
+
format(message)
end
@@ -17,6 +29,10 @@ module ChatMessage
raise NotImplementedError
end
+ def activity
+ raise NotImplementedError
+ end
+
private
def message
diff --git a/app/models/project_services/chat_message/issue_message.rb b/app/models/project_services/chat_message/issue_message.rb
index 791e5b0cec7..4b9a2b1e1f3 100644
--- a/app/models/project_services/chat_message/issue_message.rb
+++ b/app/models/project_services/chat_message/issue_message.rb
@@ -1,9 +1,6 @@
module ChatMessage
class IssueMessage < BaseMessage
- attr_reader :user_name
attr_reader :title
- attr_reader :project_name
- attr_reader :project_url
attr_reader :issue_iid
attr_reader :issue_url
attr_reader :action
@@ -11,9 +8,7 @@ module ChatMessage
attr_reader :description
def initialize(params)
- @user_name = params[:user][:username]
- @project_name = params[:project_name]
- @project_url = params[:project_url]
+ super
obj_attr = params[:object_attributes]
obj_attr = HashWithIndifferentAccess.new(obj_attr)
@@ -27,15 +22,24 @@ module ChatMessage
def attachments
return [] unless opened_issue?
+ return description if markdown
description_message
end
+ def activity
+ {
+ title: "Issue #{state} by #{user_name}",
+ subtitle: "in #{project_link}",
+ text: issue_link,
+ image: user_avatar
+ }
+ end
+
private
def message
- case state
- when "opened"
+ if state == 'opened'
"[#{project_link}] Issue #{state} by #{user_name}"
else
"[#{project_link}] Issue #{issue_link} #{state} by #{user_name}"
@@ -64,7 +68,7 @@ module ChatMessage
end
def issue_title
- "##{issue_iid} #{title}"
+ "#{Issue.reference_prefix}#{issue_iid} #{title}"
end
end
end
diff --git a/app/models/project_services/chat_message/merge_message.rb b/app/models/project_services/chat_message/merge_message.rb
index 5e5efca7bec..7d0de81cdf0 100644
--- a/app/models/project_services/chat_message/merge_message.rb
+++ b/app/models/project_services/chat_message/merge_message.rb
@@ -1,36 +1,36 @@
module ChatMessage
class MergeMessage < BaseMessage
- attr_reader :user_name
- attr_reader :project_name
- attr_reader :project_url
- attr_reader :merge_request_id
+ attr_reader :merge_request_iid
attr_reader :source_branch
attr_reader :target_branch
attr_reader :state
attr_reader :title
def initialize(params)
- @user_name = params[:user][:username]
- @project_name = params[:project_name]
- @project_url = params[:project_url]
+ super
obj_attr = params[:object_attributes]
obj_attr = HashWithIndifferentAccess.new(obj_attr)
- @merge_request_id = obj_attr[:iid]
+ @merge_request_iid = obj_attr[:iid]
@source_branch = obj_attr[:source_branch]
@target_branch = obj_attr[:target_branch]
@state = obj_attr[:state]
@title = format_title(obj_attr[:title])
end
- def pretext
- format(message)
- end
-
def attachments
[]
end
+ def activity
+ {
+ title: "Merge Request #{state} by #{user_name}",
+ subtitle: "in #{project_link}",
+ text: merge_request_link,
+ image: user_avatar
+ }
+ end
+
private
def format_title(title)
@@ -50,11 +50,15 @@ module ChatMessage
end
def merge_request_link
- link("merge request !#{merge_request_id}", merge_request_url)
+ link(merge_request_title, merge_request_url)
+ end
+
+ def merge_request_title
+ "#{MergeRequest.reference_prefix}#{merge_request_iid} #{title}"
end
def merge_request_url
- "#{project_url}/merge_requests/#{merge_request_id}"
+ "#{project_url}/merge_requests/#{merge_request_iid}"
end
end
end
diff --git a/app/models/project_services/chat_message/note_message.rb b/app/models/project_services/chat_message/note_message.rb
index 552113bac29..2da4c244229 100644
--- a/app/models/project_services/chat_message/note_message.rb
+++ b/app/models/project_services/chat_message/note_message.rb
@@ -1,70 +1,74 @@
module ChatMessage
class NoteMessage < BaseMessage
- attr_reader :message
- attr_reader :user_name
- attr_reader :project_name
- attr_reader :project_url
attr_reader :note
attr_reader :note_url
+ attr_reader :title
+ attr_reader :target
def initialize(params)
- params = HashWithIndifferentAccess.new(params)
- @user_name = params[:user][:username]
- @project_name = params[:project_name]
- @project_url = params[:project_url]
+ super
+ params = HashWithIndifferentAccess.new(params)
obj_attr = params[:object_attributes]
- obj_attr = HashWithIndifferentAccess.new(obj_attr)
@note = obj_attr[:note]
@note_url = obj_attr[:url]
- noteable_type = obj_attr[:noteable_type]
-
- case noteable_type
- when "Commit"
- create_commit_note(HashWithIndifferentAccess.new(params[:commit]))
- when "Issue"
- create_issue_note(HashWithIndifferentAccess.new(params[:issue]))
- when "MergeRequest"
- create_merge_note(HashWithIndifferentAccess.new(params[:merge_request]))
- when "Snippet"
- create_snippet_note(HashWithIndifferentAccess.new(params[:snippet]))
- end
+ @target, @title = case obj_attr[:noteable_type]
+ when "Commit"
+ create_commit_note(params[:commit])
+ when "Issue"
+ create_issue_note(params[:issue])
+ when "MergeRequest"
+ create_merge_note(params[:merge_request])
+ when "Snippet"
+ create_snippet_note(params[:snippet])
+ end
end
def attachments
+ return note if markdown
+
description_message
end
+ def activity
+ {
+ title: "#{user_name} #{link('commented on ' + target, note_url)}",
+ subtitle: "in #{project_link}",
+ text: formatted_title,
+ image: user_avatar
+ }
+ end
+
private
+ def message
+ "#{user_name} #{link('commented on ' + target, note_url)} in #{project_link}: *#{formatted_title}*"
+ end
+
def format_title(title)
title.lines.first.chomp
end
- def create_commit_note(commit)
- commit_sha = commit[:id]
- commit_sha = Commit.truncate_sha(commit_sha)
- commented_on_message(
- "commit #{commit_sha}",
- format_title(commit[:message]))
+ def formatted_title
+ format_title(title)
end
def create_issue_note(issue)
- commented_on_message(
- "issue ##{issue[:iid]}",
- format_title(issue[:title]))
+ ["issue #{Issue.reference_prefix}#{issue[:iid]}", issue[:title]]
+ end
+
+ def create_commit_note(commit)
+ commit_sha = Commit.truncate_sha(commit[:id])
+
+ ["commit #{commit_sha}", commit[:message]]
end
def create_merge_note(merge_request)
- commented_on_message(
- "merge request !#{merge_request[:iid]}",
- format_title(merge_request[:title]))
+ ["merge request #{MergeRequest.reference_prefix}#{merge_request[:iid]}", merge_request[:title]]
end
def create_snippet_note(snippet)
- commented_on_message(
- "snippet ##{snippet[:id]}",
- format_title(snippet[:title]))
+ ["snippet #{Snippet.reference_prefix}#{snippet[:id]}", snippet[:title]]
end
def description_message
@@ -74,9 +78,5 @@ module ChatMessage
def project_link
link(project_name, project_url)
end
-
- def commented_on_message(target, title)
- @message = "#{user_name} #{link('commented on ' + target, note_url)} in #{project_link}: *#{title}*"
- end
end
end
diff --git a/app/models/project_services/chat_message/pipeline_message.rb b/app/models/project_services/chat_message/pipeline_message.rb
index 210027565a8..4628d9b1a7b 100644
--- a/app/models/project_services/chat_message/pipeline_message.rb
+++ b/app/models/project_services/chat_message/pipeline_message.rb
@@ -1,19 +1,22 @@
module ChatMessage
class PipelineMessage < BaseMessage
- attr_reader :ref_type, :ref, :status, :project_name, :project_url,
- :user_name, :duration, :pipeline_id
+ attr_reader :ref_type
+ attr_reader :ref
+ attr_reader :status
+ attr_reader :duration
+ attr_reader :pipeline_id
def initialize(data)
+ super
+
+ @user_name = data.dig(:user, :name) || 'API'
+
pipeline_attributes = data[:object_attributes]
@ref_type = pipeline_attributes[:tag] ? 'tag' : 'branch'
@ref = pipeline_attributes[:ref]
@status = pipeline_attributes[:status]
@duration = pipeline_attributes[:duration]
@pipeline_id = pipeline_attributes[:id]
-
- @project_name = data[:project][:path_with_namespace]
- @project_url = data[:project][:web_url]
- @user_name = (data[:user] && data[:user][:name]) || 'API'
end
def pretext
@@ -25,17 +28,24 @@ module ChatMessage
end
def attachments
+ return message if markdown
+
[{ text: format(message), color: attachment_color }]
end
+ def activity
+ {
+ title: "Pipeline #{pipeline_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status}",
+ subtitle: "in #{project_link}",
+ text: "in #{duration} #{time_measure}",
+ image: user_avatar || ''
+ }
+ end
+
private
def message
- "#{project_link}: Pipeline #{pipeline_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status} in #{duration} #{'second'.pluralize(duration)}"
- end
-
- def format(string)
- Slack::Notifier::LinkFormatter.format(string)
+ "#{project_link}: Pipeline #{pipeline_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status} in #{duration} #{time_measure}"
end
def humanized_status
@@ -74,5 +84,9 @@ module ChatMessage
def pipeline_link
"[##{pipeline_id}](#{pipeline_url})"
end
+
+ def time_measure
+ 'second'.pluralize(duration)
+ end
end
end
diff --git a/app/models/project_services/chat_message/push_message.rb b/app/models/project_services/chat_message/push_message.rb
index 2d73b71ec37..c52dd6ef8ef 100644
--- a/app/models/project_services/chat_message/push_message.rb
+++ b/app/models/project_services/chat_message/push_message.rb
@@ -3,33 +3,43 @@ module ChatMessage
attr_reader :after
attr_reader :before
attr_reader :commits
- attr_reader :project_name
- attr_reader :project_url
attr_reader :ref
attr_reader :ref_type
- attr_reader :user_name
def initialize(params)
+ super
+
@after = params[:after]
@before = params[:before]
@commits = params.fetch(:commits, [])
- @project_name = params[:project_name]
- @project_url = params[:project_url]
@ref_type = Gitlab::Git.tag_ref?(params[:ref]) ? 'tag' : 'branch'
@ref = Gitlab::Git.ref_name(params[:ref])
- @user_name = params[:user_name]
- end
-
- def pretext
- format(message)
end
def attachments
return [] if new_branch? || removed_branch?
+ return commit_messages if markdown
commit_message_attachments
end
+ def activity
+ action = if new_branch?
+ "created"
+ elsif removed_branch?
+ "removed"
+ else
+ "pushed to"
+ end
+
+ {
+ title: "#{user_name} #{action} #{ref_type}",
+ subtitle: "in #{project_link}",
+ text: compare_link,
+ image: user_avatar
+ }
+ end
+
private
def message
@@ -59,7 +69,7 @@ module ChatMessage
end
def commit_messages
- commits.map { |commit| compose_commit_message(commit) }.join("\n")
+ commits.map { |commit| compose_commit_message(commit) }.join("\n\n")
end
def commit_message_attachments
diff --git a/app/models/project_services/chat_message/wiki_page_message.rb b/app/models/project_services/chat_message/wiki_page_message.rb
index 134083e4504..a139a8ee727 100644
--- a/app/models/project_services/chat_message/wiki_page_message.rb
+++ b/app/models/project_services/chat_message/wiki_page_message.rb
@@ -1,17 +1,12 @@
module ChatMessage
class WikiPageMessage < BaseMessage
- attr_reader :user_name
attr_reader :title
- attr_reader :project_name
- attr_reader :project_url
attr_reader :wiki_page_url
attr_reader :action
attr_reader :description
def initialize(params)
- @user_name = params[:user][:username]
- @project_name = params[:project_name]
- @project_url = params[:project_url]
+ super
obj_attr = params[:object_attributes]
obj_attr = HashWithIndifferentAccess.new(obj_attr)
@@ -29,9 +24,20 @@ module ChatMessage
end
def attachments
+ return description if markdown
+
description_message
end
+ def activity
+ {
+ title: "#{user_name} #{action} #{wiki_page_link}",
+ subtitle: "in #{project_link}",
+ text: title,
+ image: user_avatar
+ }
+ end
+
private
def message
diff --git a/app/models/project_services/chat_notification_service.rb b/app/models/project_services/chat_notification_service.rb
index 75834103db5..fa782c6fbb7 100644
--- a/app/models/project_services/chat_notification_service.rb
+++ b/app/models/project_services/chat_notification_service.rb
@@ -49,10 +49,7 @@ class ChatNotificationService < Service
object_kind = data[:object_kind]
- data = data.merge(
- project_url: project_url,
- project_name: project_name
- )
+ data = custom_data(data)
# WebHook events often have an 'update' event that follows a 'open' or
# 'close' action. Ignore update events for now to prevent duplicate
@@ -68,8 +65,7 @@ class ChatNotificationService < Service
opts[:channel] = channel_name if channel_name
opts[:username] = username if username
- notifier = Slack::Notifier.new(webhook, opts)
- notifier.ping(message.pretext, attachments: message.attachments, fallback: message.fallback)
+ return false unless notify(message, opts)
true
end
@@ -92,6 +88,18 @@ class ChatNotificationService < Service
private
+ def notify(message, opts)
+ Slack::Notifier.new(webhook, opts).ping(
+ message.pretext,
+ attachments: message.attachments,
+ fallback: message.fallback
+ )
+ end
+
+ def custom_data(data)
+ data.merge(project_url: project_url, project_name: project_name)
+ end
+
def get_message(object_kind, data)
case object_kind
when "push", "tag_push"
diff --git a/app/models/project_services/microsoft_teams_service.rb b/app/models/project_services/microsoft_teams_service.rb
new file mode 100644
index 00000000000..9b218fd81b4
--- /dev/null
+++ b/app/models/project_services/microsoft_teams_service.rb
@@ -0,0 +1,56 @@
+class MicrosoftTeamsService < ChatNotificationService
+ def title
+ 'Microsoft Teams Notification'
+ end
+
+ def description
+ 'Receive event notifications in Microsoft Teams'
+ end
+
+ def self.to_param
+ 'microsoft_teams'
+ end
+
+ def help
+ 'This service sends notifications about projects events to Microsoft Teams channels.<br />
+ To set up this service:
+ <ol>
+ <li><a href="https://msdn.microsoft.com/en-us/microsoft-teams/connectors">Getting started with 365 Office Connectors For Microsoft Teams</a>.</li>
+ <li>Paste the <strong>Webhook URL</strong> into the field below.</li>
+ <li>Select events below to enable notifications.</li>
+ </ol>'
+ end
+
+ def webhook_placeholder
+ 'https://outlook.office.com/webhook/…'
+ end
+
+ def event_field(event)
+ end
+
+ def default_channel_placeholder
+ end
+
+ def default_fields
+ [
+ { type: 'text', name: 'webhook', placeholder: "e.g. #{webhook_placeholder}" },
+ { type: 'checkbox', name: 'notify_only_broken_pipelines' },
+ { type: 'checkbox', name: 'notify_only_default_branch' },
+ ]
+ end
+
+ private
+
+ def notify(message, opts)
+ MicrosoftTeams::Notifier.new(webhook).ping(
+ title: message.project_name,
+ pretext: message.pretext,
+ activity: message.activity,
+ attachments: message.attachments
+ )
+ end
+
+ def custom_data(data)
+ super(data).merge(markdown: true)
+ end
+end
diff --git a/app/models/service.rb b/app/models/service.rb
index 5a0ec58d193..dc76bf925d3 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -237,6 +237,7 @@ class Service < ActiveRecord::Base
slack_slash_commands
slack
teamcity
+ microsoft_teams
]
if Rails.env.development?
service_names += %w[mock_ci mock_deployment mock_monitoring]