Automatically disable Auto DevOps for project upon first pipeline failure
This commit is contained in:
parent
a286e20d01
commit
177d847cf5
|
|
@ -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
|
||||
|
|
@ -12,6 +12,7 @@ class Notify < BaseMailer
|
|||
include Emails::Profile
|
||||
include Emails::Pipelines
|
||||
include Emails::Members
|
||||
include Emails::AutoDevops
|
||||
|
||||
helper MergeRequestsHelper
|
||||
helper DiffHelper
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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" }
|
||||
|
|
@ -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
|
||||
|
|
@ -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 -%>
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
---
|
||||
- auto_devops:auto_devops_disable
|
||||
|
||||
- cronjob:admin_email
|
||||
- cronjob:expire_build_artifacts
|
||||
- cronjob:gitlab_usage_ping
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
#
|
||||
module AutoDevopsQueue
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
queue_namespace :auto_devops
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Disable Auto DevOps for project upon first pipeline failure
|
||||
merge_request: 21172
|
||||
author:
|
||||
type: added
|
||||
|
|
@ -78,3 +78,4 @@
|
|||
- [create_note_diff_file, 1]
|
||||
- [delete_diff_files, 1]
|
||||
- [detect_repository_languages, 1]
|
||||
- [auto_devops, 2]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddProjectConfigSourceStatusIndexToPipeline < ActiveRecord::Migration
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_index :ci_pipelines, [:project_id, :status, :config_source]
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index :ci_pipelines, [:project_id, :status, :config_source]
|
||||
end
|
||||
end
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20180826111825) do
|
||||
ActiveRecord::Schema.define(version: 20180901171833) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
|
@ -476,6 +476,7 @@ ActiveRecord::Schema.define(version: 20180826111825) do
|
|||
add_index "ci_pipelines", ["project_id", "iid"], name: "index_ci_pipelines_on_project_id_and_iid", unique: true, where: "(iid IS NOT NULL)", using: :btree
|
||||
add_index "ci_pipelines", ["project_id", "ref", "status", "id"], name: "index_ci_pipelines_on_project_id_and_ref_and_status_and_id", using: :btree
|
||||
add_index "ci_pipelines", ["project_id", "sha"], name: "index_ci_pipelines_on_project_id_and_sha", using: :btree
|
||||
add_index "ci_pipelines", ["project_id", "status", "config_source"], name: "index_ci_pipelines_on_project_id_and_status_and_config_source", using: :btree
|
||||
add_index "ci_pipelines", ["project_id"], name: "index_ci_pipelines_on_project_id", using: :btree
|
||||
add_index "ci_pipelines", ["status"], name: "index_ci_pipelines_on_status", using: :btree
|
||||
add_index "ci_pipelines", ["user_id"], name: "index_ci_pipelines_on_user_id", using: :btree
|
||||
|
|
|
|||
|
|
@ -77,6 +77,14 @@ FactoryBot.define do
|
|||
pipeline.builds << build(:ci_build, :test_reports, pipeline: pipeline, project: pipeline.project)
|
||||
end
|
||||
end
|
||||
|
||||
trait :auto_devops_source do
|
||||
config_source { Ci::Pipeline.config_sources[:auto_devops_source] }
|
||||
end
|
||||
|
||||
trait :repository_source do
|
||||
config_source { Ci::Pipeline.config_sources[:repository_source] }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -260,6 +260,10 @@ FactoryBot.define do
|
|||
trait(:repository_enabled) { repository_access_level ProjectFeature::ENABLED }
|
||||
trait(:repository_disabled) { repository_access_level ProjectFeature::DISABLED }
|
||||
trait(:repository_private) { repository_access_level ProjectFeature::PRIVATE }
|
||||
|
||||
trait :auto_devops do
|
||||
association :auto_devops, factory: :project_auto_devops
|
||||
end
|
||||
end
|
||||
|
||||
# Project with empty repository
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Emails::AutoDevops do
|
||||
include EmailSpec::Matchers
|
||||
|
||||
describe '#auto_devops_disabled_email' do
|
||||
let(:owner) { create(:user) }
|
||||
let(:namespace) { create(:namespace, owner: owner) }
|
||||
let(:project) { create(:project, :repository, :auto_devops) }
|
||||
let(:pipeline) { create(:ci_pipeline, :failed, project: project) }
|
||||
|
||||
subject { Notify.autodevops_disabled_email(pipeline, owner.email) }
|
||||
|
||||
it 'sents email with correct subject' do
|
||||
is_expected.to have_subject("#{project.name} | Auto DevOps pipeline was disabled for #{project.name}")
|
||||
end
|
||||
|
||||
it 'sents an email to the user' do
|
||||
recipient = subject.header[:to].addrs.map(&:address).first
|
||||
|
||||
expect(recipient).to eq(owner.email)
|
||||
end
|
||||
|
||||
it 'is sent as GitLab email' do
|
||||
sender = subject.header[:from].addrs[0].address
|
||||
|
||||
expect(sender).to match(/gitlab/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1941,4 +1941,28 @@ describe Ci::Pipeline, :mailer do
|
|||
expect(pipeline.total_size).to eq(5)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#status' do
|
||||
context 'when transitioning to failed' do
|
||||
context 'when pipeline has autodevops as source' do
|
||||
let(:pipeline) { create(:ci_pipeline, :running, :auto_devops_source) }
|
||||
|
||||
it 'calls autodevops disable service' do
|
||||
expect(AutoDevops::DisableWorker).to receive(:perform_async).with(pipeline.id)
|
||||
|
||||
pipeline.drop
|
||||
end
|
||||
end
|
||||
|
||||
context 'when pipeline has other source' do
|
||||
let(:pipeline) { create(:ci_pipeline, :running, :repository_source) }
|
||||
|
||||
it 'does not call auto devops disable service' do
|
||||
expect(AutoDevops::DisableWorker).not_to receive(:perform_async)
|
||||
|
||||
pipeline.drop
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1969,6 +1969,23 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
context 'Auto DevOps notifications' do
|
||||
describe '#autodevops_disabled' do
|
||||
let(:owner) { create(:user) }
|
||||
let(:namespace) { create(:namespace, owner: owner) }
|
||||
let(:project) { create(:project, :repository, :auto_devops, namespace: namespace) }
|
||||
let(:pipeline_user) { create(:user) }
|
||||
let(:pipeline) { create(:ci_pipeline, :failed, project: project, user: pipeline_user) }
|
||||
|
||||
it 'emails project owner and user that triggered the pipeline' do
|
||||
notification.autodevops_disabled(pipeline, [owner.email, pipeline_user.email])
|
||||
|
||||
should_email(owner)
|
||||
should_email(pipeline_user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def build_team(project)
|
||||
@u_watcher = create_global_setting_for(create(:user), :watch)
|
||||
@u_participating = create_global_setting_for(create(:user), :participating)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Projects::AutoDevops::DisableService, '#execute' do
|
||||
let(:project) { create(:project, :repository, :auto_devops) }
|
||||
let(:auto_devops) { project.auto_devops }
|
||||
|
||||
subject { described_class.new(project).execute }
|
||||
|
||||
context 'when Auto DevOps disabled at instance level' do
|
||||
before do
|
||||
stub_application_setting(auto_devops_enabled: false)
|
||||
end
|
||||
|
||||
it { is_expected.to be_falsy }
|
||||
end
|
||||
|
||||
context 'when Auto DevOps enabled at instance level' do
|
||||
before do
|
||||
stub_application_setting(auto_devops_enabled: true)
|
||||
end
|
||||
|
||||
context 'when Auto DevOps explicitly enabled on project' do
|
||||
before do
|
||||
auto_devops.update!(enabled: true)
|
||||
end
|
||||
|
||||
it { is_expected.to be_falsy }
|
||||
end
|
||||
|
||||
context 'when Auto DevOps explicitly disabled on project' do
|
||||
before do
|
||||
auto_devops.update!(enabled: false)
|
||||
end
|
||||
|
||||
it { is_expected.to be_falsy }
|
||||
end
|
||||
|
||||
context 'when Auto DevOps is implicitly enabled' do
|
||||
before do
|
||||
auto_devops.update!(enabled: nil)
|
||||
end
|
||||
|
||||
context 'when is the first pipeline failure' do
|
||||
before do
|
||||
create(:ci_pipeline, :failed, :auto_devops_source, project: project)
|
||||
end
|
||||
|
||||
it 'should disable Auto DevOps for project' do
|
||||
subject
|
||||
|
||||
expect(auto_devops.enabled).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is not the first pipeline failure' do
|
||||
before do
|
||||
create_list(:ci_pipeline, 2, :failed, :auto_devops_source, project: project)
|
||||
end
|
||||
|
||||
it 'should explicitly disable Auto DevOps for project' do
|
||||
subject
|
||||
|
||||
expect(auto_devops.reload.enabled).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when an Auto DevOps pipeline has succeeded before' do
|
||||
before do
|
||||
create(:ci_pipeline, :success, :auto_devops_source, project: project)
|
||||
end
|
||||
|
||||
it 'should not disable Auto DevOps for project' do
|
||||
subject
|
||||
|
||||
expect(auto_devops.reload.enabled).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when project does not have an Auto DevOps record related' do
|
||||
let(:project) { create(:project, :repository) }
|
||||
|
||||
before do
|
||||
create(:ci_pipeline, :failed, :auto_devops_source, project: project)
|
||||
end
|
||||
|
||||
it 'should disable Auto DevOps for project' do
|
||||
subject
|
||||
auto_devops = project.reload.auto_devops
|
||||
|
||||
expect(auto_devops.enabled).to eq(false)
|
||||
end
|
||||
|
||||
it 'should create a ProjectAutoDevops record' do
|
||||
expect { subject }.to change { ProjectAutoDevops.count }.from(0).to(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe AutoDevops::DisableWorker, '#perform' do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project, :repository, :auto_devops) }
|
||||
let(:auto_devops) { project.auto_devops }
|
||||
let(:pipeline) { create(:ci_pipeline, :failed, :auto_devops_source, project: project, user: user) }
|
||||
|
||||
subject { described_class.new }
|
||||
|
||||
before do
|
||||
stub_application_setting(auto_devops_enabled: true)
|
||||
auto_devops.update_attribute(:enabled, nil)
|
||||
end
|
||||
|
||||
it 'disables auto devops for project' do
|
||||
subject.perform(pipeline.id)
|
||||
|
||||
expect(auto_devops.reload.enabled).to eq(false)
|
||||
end
|
||||
|
||||
context 'when project owner is a user' do
|
||||
let(:owner) { create(:user) }
|
||||
let(:namespace) { create(:namespace, owner: owner) }
|
||||
let(:project) { create(:project, :repository, :auto_devops, namespace: namespace) }
|
||||
|
||||
it 'sends an email to pipeline user and project owner' do
|
||||
expect(NotificationService).to receive_message_chain(:new, :autodevops_disabled).with(pipeline, [user.email, owner.email])
|
||||
|
||||
subject.perform(pipeline.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when project does not have owner' do
|
||||
let(:group) { create(:group) }
|
||||
let(:project) { create(:project, :repository, :auto_devops, namespace: group) }
|
||||
|
||||
it 'sends an email to pipeline user' do
|
||||
expect(NotificationService).to receive_message_chain(:new, :autodevops_disabled).with(pipeline, [user.email])
|
||||
|
||||
subject.perform(pipeline.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when pipeline is not related to a user and project does not have owner' do
|
||||
let(:group) { create(:group) }
|
||||
let(:project) { create(:project, :repository, :auto_devops, namespace: group) }
|
||||
let(:pipeline) { create(:ci_pipeline, :failed, project: project) }
|
||||
|
||||
it 'does not send an email' do
|
||||
expect(NotificationService).not_to receive(:new)
|
||||
|
||||
subject.perform(pipeline.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue