diff options
author | Mayra Cabrera <mcabrera@gitlab.com> | 2018-09-06 19:20:42 +0000 |
---|---|---|
committer | Kamil Trzciński <ayufan@ayufan.eu> | 2018-09-06 19:20:42 +0000 |
commit | 177d847cf5c0ad9f282f599fbd5e9dafdc3b6289 (patch) | |
tree | cf94abe3e3ae6b79582d9aa87e1d595b3f0dbda2 /app | |
parent | a286e20d014e4092be7f03a2e1679f8f8434afa2 (diff) | |
download | gitlab-ce-177d847cf5c0ad9f282f599fbd5e9dafdc3b6289.tar.gz |
Automatically disable Auto DevOps for project upon first pipeline failure
Diffstat (limited to 'app')
-rw-r--r-- | app/mailers/emails/auto_devops.rb | 24 | ||||
-rw-r--r-- | app/mailers/notify.rb | 1 | ||||
-rw-r--r-- | app/mailers/previews/notify_preview.rb | 4 | ||||
-rw-r--r-- | app/models/ci/pipeline.rb | 6 | ||||
-rw-r--r-- | app/services/notification_service.rb | 6 | ||||
-rw-r--r-- | app/services/projects/auto_devops/disable_service.rb | 39 | ||||
-rw-r--r-- | app/views/notify/_failed_builds.html.haml | 32 | ||||
-rw-r--r-- | app/views/notify/autodevops_disabled_email.html.haml | 49 | ||||
-rw-r--r-- | app/views/notify/autodevops_disabled_email.text.erb | 20 | ||||
-rw-r--r-- | app/views/notify/pipeline_failed_email.html.haml | 35 | ||||
-rw-r--r-- | app/workers/all_queues.yml | 2 | ||||
-rw-r--r-- | app/workers/auto_devops/disable_worker.rb | 35 | ||||
-rw-r--r-- | app/workers/concerns/auto_devops_queue.rb | 9 |
13 files changed, 229 insertions, 33 deletions
diff --git a/app/mailers/emails/auto_devops.rb b/app/mailers/emails/auto_devops.rb new file mode 100644 index 00000000000..9705a3052d4 --- /dev/null +++ b/app/mailers/emails/auto_devops.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module Emails + module AutoDevops + def autodevops_disabled_email(pipeline, recipient) + @pipeline = pipeline + @project = pipeline.project + + add_project_headers + + mail(to: recipient, + subject: auto_devops_disabled_subject(@project.name)) do |format| + format.html { render layout: 'mailer' } + format.text { render layout: 'mailer' } + end + end + + private + + def auto_devops_disabled_subject(project_name) + subject("Auto DevOps pipeline was disabled for #{project_name}") + end + end +end diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb index f4eeb85270e..f7347ee61b4 100644 --- a/app/mailers/notify.rb +++ b/app/mailers/notify.rb @@ -12,6 +12,7 @@ class Notify < BaseMailer include Emails::Profile include Emails::Pipelines include Emails::Members + include Emails::AutoDevops helper MergeRequestsHelper helper DiffHelper diff --git a/app/mailers/previews/notify_preview.rb b/app/mailers/previews/notify_preview.rb index df470930e9e..c133f4e6dbb 100644 --- a/app/mailers/previews/notify_preview.rb +++ b/app/mailers/previews/notify_preview.rb @@ -125,6 +125,10 @@ class NotifyPreview < ActionMailer::Preview Notify.pipeline_failed_email(pipeline, pipeline.user.try(:email)) end + def autodevops_disabled_email + Notify.autodevops_disabled_email(pipeline, user.email).message + end + private def project diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 526bf7af99b..2955e0b2bca 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -161,6 +161,12 @@ module Ci PipelineNotificationWorker.perform_async(pipeline.id) end end + + after_transition any => [:failed] do |pipeline| + next unless pipeline.auto_devops_source? + + pipeline.run_after_commit { AutoDevops::DisableWorker.perform_async(pipeline.id) } + end end scope :internal, -> { where(source: internal_sources) } diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 4511c500fca..50fa373025b 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -407,6 +407,12 @@ class NotificationService end end + def autodevops_disabled(pipeline, recipients) + recipients.each do |recipient| + mailer.autodevops_disabled_email(pipeline, recipient).deliver_later + end + end + def pages_domain_verification_succeeded(domain) recipients_for_pages_domain(domain).each do |user| mailer.pages_domain_verification_succeeded_email(domain, user).deliver_later diff --git a/app/services/projects/auto_devops/disable_service.rb b/app/services/projects/auto_devops/disable_service.rb new file mode 100644 index 00000000000..9745ab67dbd --- /dev/null +++ b/app/services/projects/auto_devops/disable_service.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module Projects + module AutoDevops + class DisableService < BaseService + def execute + return false unless implicitly_enabled_and_first_pipeline_failure? + + disable_auto_devops + end + + private + + def implicitly_enabled_and_first_pipeline_failure? + project.has_auto_devops_implicitly_enabled? && + first_pipeline_failure? + end + + # We're using `limit` to optimize `auto_devops pipeline` query, + # since we only care about the first element, and using only `.count` + # is an expensive operation. See + # https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21172#note_99037378 + # for more context. + def first_pipeline_failure? + auto_devops_pipelines.success.limit(1).count.zero? && + auto_devops_pipelines.failed.limit(1).count.nonzero? + end + + def disable_auto_devops + project.auto_devops_attributes = { enabled: false } + project.save! + end + + def auto_devops_pipelines + @auto_devops_pipelines ||= project.pipelines.auto_devops_source + end + end + end +end diff --git a/app/views/notify/_failed_builds.html.haml b/app/views/notify/_failed_builds.html.haml new file mode 100644 index 00000000000..7c563bb016c --- /dev/null +++ b/app/views/notify/_failed_builds.html.haml @@ -0,0 +1,32 @@ +%tr + %td{ colspan: 2, style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; color: #333333; font-size: 14px; font-weight: 400; line-height: 1.4; padding: 0 8px 16px; text-align: center;" } + had + = failed.size + failed + #{'build'.pluralize(failed.size)}. +%tr.table-warning + %td{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; border: 1px solid #ededed; border-bottom: 0; border-radius: 4px 4px 0 0; overflow: hidden; background-color: #fdf4f6; color: #d22852; font-size: 14px; line-height: 1.4; text-align: center; padding: 8px 16px;" } + Logs may contain sensitive data. Please consider before forwarding this email. +%tr.section + %td{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; padding: 0 16px; border: 1px solid #ededed; border-radius: 4px; overflow: hidden; border-top: 0; border-radius: 0 0 4px 4px;" } + %table.builds{ border: "0", cellpadding: "0", cellspacing: "0", style: "width: 100%; border-collapse: collapse;" } + %tbody + - failed.each do |build| + %tr.build-state + %td{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; padding: 16px 0; color: #8c8c8c; font-weight: 500; font-size: 14px;" } + %table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse: collapse;" } + %tbody + %tr + %td{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; color: #d22f57; font-weight: 500; font-size: 16px; vertical-align: middle; padding-right: 8px; line-height: 10px" } + %img{ alt: "✖", height: "10", src: image_url('mailers/ci_pipeline_notif_v1/icon-x-red.gif'), style: "display: block;", width: "10" }/ + %td{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; color: #8c8c8c; font-weight: 500; font-size: 14px; vertical-align: middle;" } + = build.stage + %td{ align: "right", style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; padding: 16px 0; color: #8c8c8c; font-weight: 500; font-size: 14px;" } + = render "notify/links/#{build.to_partial_path}", pipeline: pipeline, build: build + %tr.build-log + - if build.has_trace? + %td{ colspan: "2", style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; padding: 0 0 16px;" } + %pre{ style: "font-family: Monaco,'Lucida Console','Courier New',Courier,monospace; background-color: #fafafa; border-radius: 4px; overflow: hidden; white-space: pre-wrap; word-break: break-all; font-size:13px; line-height: 1.4; padding: 16px 8px; color: #333333; margin: 0;" } + = build.trace.html(last_lines: 10).html_safe + - else + %td{ colspan: "2" } diff --git a/app/views/notify/autodevops_disabled_email.html.haml b/app/views/notify/autodevops_disabled_email.html.haml new file mode 100644 index 00000000000..65a2f75a3e2 --- /dev/null +++ b/app/views/notify/autodevops_disabled_email.html.haml @@ -0,0 +1,49 @@ +%tr.alert + %td{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; padding: 8px 16px; border-radius: 4px; font-size: 14px; line-height: 1.3; text-align: center; overflow: hidden; background-color: #d22f57; color: #ffffff;" } + %table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse: collapse; margin: 0 auto;" } + %tbody + %tr + %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; vertical-align: middle; color: #ffffff; text-align: center;" } + Auto DevOps pipeline was disabled for #{@project.name} + +%tr.pre-section + %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; color: #333333; font-size: 14px; font-weight: 400; line-height: 1.7; padding: 16px 8px 0;" } + The Auto DevOps pipeline failed for pipeline + %a{ href: pipeline_url(@pipeline), style: "color: #1b69b6; text-decoration:none;" } + = "\##{@pipeline.iid}" + and has been disabled for + %a{ href: project_url(@project), style: "color: #1b69b6; text-decoration: none;" } + = @project.name + "." + In order to use the Auto DevOps pipeline with your project, please review the + %a{ href: 'https://docs.gitlab.com/ee/topics/autodevops/#currently-supported-languages', style: "color:#1b69b6;text-decoration:none;" } currently supported languages, + adjust your project accordingly, and turn on the Auto DevOps pipeline within your + %a{ href: project_settings_ci_cd_url(@project), style: "color: #1b69b6; text-decoration: none;" } + CI/CD project settings. + +%tr.pre-section + %td{ style: 'text-align: center;border-bottom:1px solid #ededed' } + %a{ href: 'https://docs.gitlab.com/ee/topics/autodevops/', style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;" } + %button{ type: 'button', style: 'border-color: #dfdfdf; border-style: solid; border-width: 1px; border-radius: 4px; font-size: 14px; padding: 8px 16px; background-color:#fff; margin: 8px 0; cursor: pointer;' } + Learn more about Auto DevOps + +%tr.pre-section + %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; color: #333333; font-size: 14px; font-weight: 400; line-height: 1.4; padding: 16px 8px; text-align: center;" } + %table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" } + %tbody + %tr + %td{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:14px; font-weight:500;line-height: 1.4; vertical-align: baseline;" } + Pipeline + %a{ href: pipeline_url(@pipeline), style: "color: #1b69b6; text-decoration: none;" } + = "\##{@pipeline.id}" + triggered by + - if @pipeline.user + %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size: 15px; line-height: 1.4; vertical-align: middle; padding-right: 8px; padding-left:8px", width: "24" } + %img.avatar{ height: "24", src: avatar_icon_for_user(@pipeline.user, 24, only_path: false), style: "display: block; border-radius: 12px; margin: -2px 0;", width: "24", alt: "" }/ + %td{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; font-size: 14px; font-weight: 500; line-height: 1.4; vertical-align: baseline;" } + %a.muted{ href: user_url(@pipeline.user), style: "color: #333333; text-decoration: none;" } + = @pipeline.user.name + - else + %td{ style: "font-family: 'Menlo','Liberation Mono','Consolas','DejaVu Sans Mono','Ubuntu Mono','Courier New','andale mono','lucida console',monospace; font-size: 14px; line-height: 1.4; vertical-align: baseline; padding:0 8px;" } + API + += render 'notify/failed_builds', pipeline: @pipeline, failed: @pipeline.statuses.latest.failed diff --git a/app/views/notify/autodevops_disabled_email.text.erb b/app/views/notify/autodevops_disabled_email.text.erb new file mode 100644 index 00000000000..695780c3145 --- /dev/null +++ b/app/views/notify/autodevops_disabled_email.text.erb @@ -0,0 +1,20 @@ +Auto DevOps pipeline was disabled for <%= @project.name %> + +The Auto DevOps pipeline failed for pipeline <%= @pipeline.iid %> (<%= pipeline_url(@pipeline) %>) and has been disabled for <%= @project.name %>. In order to use the Auto DevOps pipeline with your project, please review the currently supported languagues (https://docs.gitlab.com/ee/topics/autodevops/#currently-supported-languages), adjust your project accordingly, and turn on the Auto DevOps pipeline within your CI/CD project settings (<%= project_settings_ci_cd_url(@project) %>). + +<% if @pipeline.user -%> + Pipeline #<%= @pipeline.id %> ( <%= pipeline_url(@pipeline) %> ) triggered by <%= @pipeline.user.name %> ( <%= user_url(@pipeline.user) %> ) +<% else -%> + Pipeline #<%= @pipeline.id %> ( <%= pipeline_url(@pipeline) %> ) triggered by API +<% end -%> +<% failed = @pipeline.statuses.latest.failed -%> +had <%= failed.size %> failed <%= 'build'.pluralize(failed.size) %>. + +<% failed.each do |build| -%> + <%= render "notify/links/#{build.to_partial_path}", pipeline: @pipeline, build: build %> + Stage: <%= build.stage %> + Name: <%= build.name %> + <% if build.has_trace? -%> + Trace: <%= build.trace.raw(last_lines: 10) %> + <% end -%> +<% end -%> diff --git a/app/views/notify/pipeline_failed_email.html.haml b/app/views/notify/pipeline_failed_email.html.haml index baafaa6e3a0..86dcca4a447 100644 --- a/app/views/notify/pipeline_failed_email.html.haml +++ b/app/views/notify/pipeline_failed_email.html.haml @@ -107,36 +107,5 @@ - else %td{ style: "font-family:'Menlo','Liberation Mono','Consolas','DejaVu Sans Mono','Ubuntu Mono','Courier New','andale mono','lucida console',monospace;font-size:14px;line-height:1.4;vertical-align:baseline;padding:0 5px;" } API -- failed = @pipeline.statuses.latest.failed -%tr - %td{ colspan: 2, style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;color:#333333;font-size:15px;font-weight:300;line-height:1.4;padding:15px 5px;text-align:center;" } - had - = failed.size - failed - #{'build'.pluralize(failed.size)}. -%tr.table-warning - %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;border:1px solid #ededed;border-bottom:0;border-radius:3px 3px 0 0;overflow:hidden;background-color:#fdf4f6;color:#d22852;font-size:14px;line-height:1.4;text-align:center;padding:8px 15px;" } - Logs may contain sensitive data. Please consider before forwarding this email. -%tr.section - %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;border-top:0;border-radius:0 0 3px 3px;" } - %table.builds{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;border-collapse:collapse;" } - %tbody - - failed.each do |build| - %tr.build-state - %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:20px 0;color:#8c8c8c;font-weight:500;font-size:15px;" } - %table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" } - %tbody - %tr - %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;color:#d22f57;font-weight:500;font-size:15px;vertical-align:middle;padding-right:5px;line-height:10px" } - %img{ alt: "✖", height: "10", src: image_url('mailers/ci_pipeline_notif_v1/icon-x-red.gif'), style: "display:block;", width: "10" }/ - %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;color:#8c8c8c;font-weight:500;font-size:15px;vertical-align:middle;" } - = build.stage - %td{ align: "right", style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:20px 0;color:#8c8c8c;font-weight:500;font-size:15px;" } - = render "notify/links/#{build.to_partial_path}", pipeline: @pipeline, build: build - %tr.build-log - - if build.has_trace? - %td{ colspan: "2", style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:0 0 15px;" } - %pre{ style: "font-family:Monaco,'Lucida Console','Courier New',Courier,monospace;background-color:#fafafa;border-radius:3px;overflow:hidden;white-space:pre-wrap;word-break:break-all;font-size:13px;line-height:1.4;padding:12px;color:#333333;margin:0;" } - = build.trace.html(last_lines: 10).html_safe - - else - %td{ colspan: "2" } + += render 'notify/failed_builds', pipeline: @pipeline, failed: @pipeline.statuses.latest.failed diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml index f95df7ecf03..ae9dc8d4857 100644 --- a/app/workers/all_queues.yml +++ b/app/workers/all_queues.yml @@ -1,4 +1,6 @@ --- +- auto_devops:auto_devops_disable + - cronjob:admin_email - cronjob:expire_build_artifacts - cronjob:gitlab_usage_ping diff --git a/app/workers/auto_devops/disable_worker.rb b/app/workers/auto_devops/disable_worker.rb new file mode 100644 index 00000000000..73ddc591505 --- /dev/null +++ b/app/workers/auto_devops/disable_worker.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module AutoDevops + class DisableWorker + include ApplicationWorker + include AutoDevopsQueue + + def perform(pipeline_id) + pipeline = Ci::Pipeline.find(pipeline_id) + project = pipeline.project + + send_notification_email(pipeline, project) if disable_service(project).execute + end + + private + + def disable_service(project) + Projects::AutoDevops::DisableService.new(project) + end + + def send_notification_email(pipeline, project) + recipients = email_receivers_for(pipeline, project) + + return unless recipients.any? + + NotificationService.new.autodevops_disabled(pipeline, recipients) + end + + def email_receivers_for(pipeline, project) + recipients = [pipeline.user&.email] + recipients << project.owner.email unless project.group + recipients.uniq.compact + end + end +end diff --git a/app/workers/concerns/auto_devops_queue.rb b/app/workers/concerns/auto_devops_queue.rb new file mode 100644 index 00000000000..aba928ccaab --- /dev/null +++ b/app/workers/concerns/auto_devops_queue.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true +# +module AutoDevopsQueue + extend ActiveSupport::Concern + + included do + queue_namespace :auto_devops + end +end |