lib/release_tools/promotion/production_status.rb (77 lines of code) (raw):
# frozen_string_literal: true
module ReleaseTools
module Promotion
# Perform production checks and report on their statuses
#
# There is a default group of checks that are always queried. Additional
# checks can be included by passing them to the initializer:
#
# # Additionally include `MyCustomCheck` and `ConditionalCheck`
# ProductionStatus.new(:my_custom_check, :conditional_check)
class ProductionStatus
include ::SemanticLogger::Loggable
include Check
# Raised when attempting to include an unknown `Check` class
class InvalidCheckError < StandardError
def initialize(name)
super("Unknown check `#{name}`")
end
end
# List of checks that are always included for any production status check
ALL_CHECKS = %i[
active_incidents
change_requests
gitlab_deployment_health
orchestrator_status
].freeze
attr_reader :checks, :scope
def initialize(*extra_checks, scope: :deployment)
@scope = scope
@checks = [*ALL_CHECKS, *extra_checks].uniq.map do |check_name|
instance_of_check(check_name)
end
end
# @see Check#fine?
def fine?
checks.all?(&:fine?)
end
# @return <Array(Class)> Array of checks that failed.
def failed_checks
checks.reject(&:fine?)
end
# @see Check#to_issue_body
def to_issue_body
text = StringIO.new
overall_status = if fine?
"#{ok_icon} Production checks pass."
else
"#{failure_icon} Production checks fail!"
end
text.puts(overall_status)
checks.each do |check|
text.puts("\n---")
text.puts(check.to_issue_body)
end
text.string
end
# @see Check#to_slack_blocks
def to_slack_blocks
overall_status = if fine?
"#{ok_icon} Production checks pass. :shipit: :fine:"
else
"#{failure_icon} Production checks fail!"
end
if fine?
[to_slack_block(overall_status)]
else
[to_slack_block(overall_status)] + checks.reject(&:fine?).map(&:to_slack_blocks).flatten
end
end
private
def to_slack_block(status)
{
type: 'section',
text: mrkdwn(status)
}
end
def args_for(check_name)
if %i[active_incidents change_requests].include?(check_name)
{ scope: scope }
else
{}
end
end
def instance_of_check(check_name)
Checks.const_get(check_name.to_s.camelize).new(**args_for(check_name))
rescue NameError => ex
raise InvalidCheckError, ex.name
end
end
end
end