Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/mailers/emails/pipelines.rb38
-rw-r--r--app/mailers/notify.rb1
-rw-r--r--app/models/project_services/pipelines_email_service.rb93
-rw-r--r--app/workers/pipeline_email_worker.rb39
4 files changed, 171 insertions, 0 deletions
diff --git a/app/mailers/emails/pipelines.rb b/app/mailers/emails/pipelines.rb
new file mode 100644
index 00000000000..7fdba850219
--- /dev/null
+++ b/app/mailers/emails/pipelines.rb
@@ -0,0 +1,38 @@
+module Emails
+ module Pipelines
+ def pipeline_succeeded_email(params, to)
+ pipeline_mail(params, to, 'succeeded') # TODO: missing template
+ end
+
+ def pipeline_failed_email(params, to)
+ pipeline_mail(params, to, 'failed') # TODO: missing template
+ end
+
+ private
+
+ def pipeline_mail(params, to, status)
+ @params = params
+ add_headers
+
+ mail(to: to, subject: pipeline_subject('failed'))
+ end
+
+ def add_headers
+ @project = @params.project # `add_project_headers` needs this
+ add_project_headers
+ add_pipeline_headers(@params.pipeline)
+ end
+
+ def add_pipeline_headers(pipeline)
+ headers['X-GitLab-Pipeline-Id'] = pipeline.id
+ headers['X-GitLab-Pipeline-Ref'] = pipeline.ref
+ headers['X-GitLab-Pipeline-Status'] = pipeline.status
+ end
+
+ def pipeline_subject(status)
+ subject(
+ "Pipeline #{status} for #{@params.project.name}",
+ @params.pipeline.short_sha)
+ end
+ end
+end
diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb
index 0cc709f68e4..fef8149b325 100644
--- a/app/mailers/notify.rb
+++ b/app/mailers/notify.rb
@@ -7,6 +7,7 @@ class Notify < BaseMailer
include Emails::Projects
include Emails::Profile
include Emails::Builds
+ include Emails::Pipelines
include Emails::Members
add_template_helper MergeRequestsHelper
diff --git a/app/models/project_services/pipelines_email_service.rb b/app/models/project_services/pipelines_email_service.rb
new file mode 100644
index 00000000000..1f852445c1c
--- /dev/null
+++ b/app/models/project_services/pipelines_email_service.rb
@@ -0,0 +1,93 @@
+class PipelinesEmailService < Service
+ prop_accessor :recipients
+ boolean_accessor :add_pusher
+ boolean_accessor :notify_only_broken_pipelines
+ validates :recipients,
+ presence: true,
+ if: ->(s) { s.activated? && !s.add_pusher? }
+
+ def initialize_properties
+ self.properties ||= { notify_only_broken_builds: true }
+ end
+
+ def title
+ 'Pipelines emails'
+ end
+
+ def description
+ 'Email the pipelines status to a list of recipients.'
+ end
+
+ def to_param
+ 'pipelines_email'
+ end
+
+ def supported_events
+ %w[pipeline]
+ end
+
+ def execute(data, force = false)
+ return unless supported_events.include?(data[:object_kind])
+ return unless force || should_build_be_notified?(data)
+
+ all_recipients = retrieve_recipients(data)
+
+ return unless all_recipients.any?
+
+ PipelineEmailWorker.perform_async(data, all_recipients)
+ end
+
+ def can_test?
+ project.pipelines.count > 0
+ end
+
+ def disabled_title
+ 'Please setup a pipeline on your repository.'
+ end
+
+ def test_data(project, user)
+ data = Gitlab::DataBuilder::Pipeline.build(project.pipelines.last)
+ data[:user] = user.hook_attrs
+ data
+ end
+
+ def fields
+ [
+ { type: 'textarea',
+ name: 'recipients',
+ placeholder: 'Emails separated by comma' },
+ { type: 'checkbox',
+ name: 'add_pusher',
+ label: 'Add pusher to recipients list' },
+ { type: 'checkbox',
+ name: 'notify_only_broken_pipelines' },
+ ]
+ end
+
+ def test(data)
+ result = execute(data, true)
+
+ { success: true, result: result }
+ rescue StandardError => error
+ { success: false, result: error }
+ end
+
+ def should_build_be_notified?(data)
+ case data[:object_attributes][:status]
+ when 'success'
+ !notify_only_broken_pipelines?
+ else
+ false
+ end
+ end
+
+ def retrieve_recipients(data)
+ all_recipients = recipients.to_s.split(',').reject(&:blank?)
+
+ if add_pusher? && data[:user].try(:[], :email)
+ all_recipients << data[:user][:email]
+ else
+ all_recipients
+ end
+ end
+end
diff --git a/app/workers/pipeline_email_worker.rb b/app/workers/pipeline_email_worker.rb
new file mode 100644
index 00000000000..2160207c901
--- /dev/null
+++ b/app/workers/pipeline_email_worker.rb
@@ -0,0 +1,39 @@
+class PipelineEmailWorker
+ include Sidekiq::Worker
+
+ ParamsStruct = Struct.new(:pipeline, :project, :email_template)
+ class Params < ParamsStruct
+ def initialize(pipeline_id)
+ self.pipeline = Ci::Pipeline.find(pipeline_id)
+ self.project = pipeline.project
+ self.email_template = case pipeline.status
+ when 'success'
+ :pipeline_succeeded_email
+ when 'failed'
+ :pipeline_failed_email
+ end
+ end
+ end
+
+ def perform(data, recipients)
+ params = Params.new(data['object_attributes']['id'])
+
+ return unless params.email_template
+
+ recipients.each do |to|
+ deliver(params, to) do
+ Notify.public_send(params.email_template, params, to).deliver_now
+ end
+ end
+ end
+
+ private
+
+ def deliver(params, to)
+ yield
+ # These are input errors and won't be corrected even if Sidekiq retries
+ rescue Net::SMTPFatalError, Net::SMTPSyntaxError => e
+ project_name = params.project.path_with_namespace
+ logger.info("Failed to send email for #{project_name} to #{to}: #{e}")
+ end
+end