From efe2d96a90cb5e2cc0c368294a021423aeeaeabe Mon Sep 17 00:00:00 2001 From: Tiago Botelho Date: Mon, 3 Apr 2017 16:37:23 +0100 Subject: [PATCH] adds initial microsoft teams integration --- app/models/project.rb | 1 + .../chat_message/note_message.rb | 2 +- .../chat_message/push_message.rb | 31 ++++++++- .../chat_notification_service.rb | 3 +- .../microsoft_teams_service.rb | 66 +++++++++++++++++++ app/models/service.rb | 1 + lib/microsoft_teams/notifier.rb | 37 +++++++++++ spec/lib/gitlab/import_export/all_models.yml | 1 + 8 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 app/models/project_services/microsoft_teams_service.rb create mode 100644 lib/microsoft_teams/notifier.rb diff --git a/app/models/project.rb b/app/models/project.rb index 12fd0668ff8..fb0e4a6ed5f 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/note_message.rb b/app/models/project_services/chat_message/note_message.rb index 552113bac29..e06c37df69e 100644 --- a/app/models/project_services/chat_message/note_message.rb +++ b/app/models/project_services/chat_message/note_message.rb @@ -10,6 +10,7 @@ module ChatMessage def initialize(params) params = HashWithIndifferentAccess.new(params) @user_name = params[:user][:username] + @user_avatar = params[:user][:avatar] @project_name = params[:project_name] @project_url = params[:project_url] @@ -18,7 +19,6 @@ module ChatMessage @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])) diff --git a/app/models/project_services/chat_message/push_message.rb b/app/models/project_services/chat_message/push_message.rb index 2d73b71ec37..9fb77d806ed 100644 --- a/app/models/project_services/chat_message/push_message.rb +++ b/app/models/project_services/chat_message/push_message.rb @@ -8,6 +8,7 @@ module ChatMessage attr_reader :ref attr_reader :ref_type attr_reader :user_name + attr_reader :user_avatar def initialize(params) @after = params[:after] @@ -18,16 +19,27 @@ module ChatMessage @ref_type = Gitlab::Git.tag_ref?(params[:ref]) ? 'tag' : 'branch' @ref = Gitlab::Git.ref_name(params[:ref]) @user_name = params[:user_name] + @user_avatar = params[:user_avatar] + @format = params[:format] + end + + def activity + { + title: activity_title, + subtitle: "to: #{project_link}", + text: compare_link, + image: params[:user_avatar] + } end def pretext - format(message) + @format ? format(message) : message end def attachments return [] if new_branch? || removed_branch? - commit_message_attachments + @format ? commit_message_attachments : commit_messages end private @@ -59,7 +71,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 @@ -103,6 +115,19 @@ module ChatMessage "[Compare changes](#{compare_url})" end + def activity_title + action = + if new_branch? + "created" + elsif removed_branch? + "removed" + else + "pushed to" + end + + "#{user_name} #{action} #{ref_type}" + end + def attachment_color '#345' end diff --git a/app/models/project_services/chat_notification_service.rb b/app/models/project_services/chat_notification_service.rb index 75834103db5..2957237faac 100644 --- a/app/models/project_services/chat_notification_service.rb +++ b/app/models/project_services/chat_notification_service.rb @@ -51,7 +51,8 @@ class ChatNotificationService < Service data = data.merge( project_url: project_url, - project_name: project_name + project_name: project_name, + format: true ) # WebHook events often have an 'update' event that follows a 'open' or 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..c0a3d2c0025 --- /dev/null +++ b/app/models/project_services/microsoft_teams_service.rb @@ -0,0 +1,66 @@ +class MicrosoftTeamsService < ChatNotificationService + def title + 'Microsoft Teams Notification' + end + + def description + 'Receive event notifications in Microsoft Team' + end + + def self.to_param + 'microsoft_teams' + end + + #TODO: Setup the description accordingly + def help + 'This service sends notifications about projects events to Microsoft Teams channels.
+ To set up this service: +
    +
  1. Getting started with 365 Office Connectors For Microsoft Teams.
  2. +
  3. Paste the Webhook URL into the field below.
  4. +
  5. Select events below to enable notifications.
  6. +
' + end + + def default_channel_placeholder + "Channel name (e.g. general)" + end + + def webhook_placeholder + 'https://outlook.office.com/webhook/…' + end + + def event_field(event) + 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 + + def execute(data) + return unless supported_events.include?(data[:object_kind]) + return unless webhook.present? + + object_kind = data[:object_kind] + + data = data.merge( + project_url: project_url, + project_name: project_name, + format: false + ) + + message = get_message(object_kind, data) + + return false unless message + + MicrosoftTeams::Notifier.new(webhook).ping({ + title: message.project_name, + activity: message.activity, + attachments: message.attachments, + }) + 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] diff --git a/lib/microsoft_teams/notifier.rb b/lib/microsoft_teams/notifier.rb new file mode 100644 index 00000000000..deff5fd26ee --- /dev/null +++ b/lib/microsoft_teams/notifier.rb @@ -0,0 +1,37 @@ +module MicrosoftTeams + class Notifier + def initialize(webhook) + @webhook = webhook + end + + def ping(options = {}) + HTTParty.post( + @webhook.to_str, + headers: { 'Content-type' => 'application/json' }, + body: body(options) + ) + end + + private + + def body(options = {}) + result = { 'sections' => [] } + + result['title'] = options[:title] if options[:title] + result['summary'] = options[:activity][:title] + result['sections'] << { + 'activityTitle' => options[:activity][:title], + 'activitySubtitle' => options[:activity][:subtitle], + 'activityText' => options[:activity][:text], + 'activityImage' => options[:activity][:image] + } + result['sections'] << { 'title' => 'Details', 'facts' => attachments(options[:attachments]) } if options[:attachments] + + result.to_json + end + + def attachments(content) + [{ 'name' => 'Attachments', 'value' => content }] + end + end +end diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 24654bf6afd..f4b542f7bbb 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -143,6 +143,7 @@ project: - asana_service - gemnasium_service - slack_service +- microsoft_teams_service - mattermost_service - buildkite_service - bamboo_service