lib/release_tools/slack/coordinated_pipeline_notification.rb (136 lines of code) (raw):

# frozen_string_literal: true require 'release_tools/time_util' module ReleaseTools module Slack class CoordinatedPipelineNotification include ::SemanticLogger::Loggable include ReleaseTools::TimeUtil include Utilities # deploy_version - Deployer package # pipeline - GitLab response pipeline object # environment - gstg-ref, gstg-cny, gstg, gprd-cny, gprd def initialize(deploy_version:, pipeline:, environment:) @deploy_version = deploy_version @pipeline = pipeline @environment = environment end def execute logger.info('Sending slack notification', deploy_version: deploy_version, environment: environment, deployer_url: deployer_url) response = send_notification return response unless send_diffs_notification? send_threaded_diffs_notification(response['ts']) end private attr_reader :deploy_version, :pipeline, :environment def deployer_url pipeline&.web_url end def send_notification params = { channel: slack_channel[:id], message: fallback_text, blocks: slack_block } if thread_to_started_notification? params[:additional_options] = { thread_ts: started_notification_message['ts'], reply_broadcast: true } end ReleaseTools::Slack::Message.post(**params) end def slack_channel if environment == 'gstg-ref' { id: Slack::STAGING_REF_DEPLOYMENT, name: Slack::STAGING_REF_DEPLOYMENT_NAME } else { id: Slack::ANNOUNCEMENTS, name: Slack::ANNOUNCEMENTS_NAME } end end def thread_to_started_notification? # Thread "success" or "failed" notifications to the started notification. deployer_status != DEPLOYER_STATUS_STARTED && started_notification_message end def fallback_text "#{environment} #{deployer_status} #{deploy_version}" end def slack_block [ { type: 'section', text: ReleaseTools::Slack::Webhook.mrkdwn(section_block) }, { type: 'context', elements: context_elements } ] end def section_block [].tap do |text| text << environment_icon text << status_icon text << release_managers_mention if mention_release_managers? text << "*#{environment}*" text << deployer_status_link text << "`#{deploy_version}`" end.join(' ') end def deployer_status_link if pipeline "<#{deployer_url}|#{deployer_status}>" else "Downstream pipeline couldn't be found, check if `#{bridge_job_name}` job in <#{ENV.fetch('CI_PIPELINE_URL', nil)}|coordinated pipeline> has started." end end def bridge_job_name "deploy:#{environment}" end def context_elements [].tap do |elements| elements << clock_context_element elements << { type: 'mrkdwn', text: ":sentry: #{new_sentry_link}" } elements << { type: 'mrkdwn', text: ":timer_clock: #{wall_duration}" } if finished_or_failed? end end def new_sentry_link version = ReleaseTools::AutoDeploy::Version.new(deploy_version) "<https://new-sentry.gitlab.net/gitlab/gitlabcom/releases/#{version.rails_sha}/|View Sentry>" end def wall_duration duration(current_time - start_time).first end def start_time Time.parse(pipeline.created_at) end def finished_or_failed? [DEPLOYER_STATUS_SUCCESS, DEPLOYER_STATUS_FAILED].include?(deployer_status) end def send_diffs_notification? deployer_status == DEPLOYER_STATUS_STARTED end def send_threaded_diffs_notification(thread_ts) args = { deploy_version: deploy_version, environment: environment, thread_ts: thread_ts, channel: slack_channel[:id] } ReleaseTools::Slack::CoordinatedPipelineDiffsNotification.new(**args).execute end def started_notification_message return @started_notification_message if @started_notification_message results = ReleaseTools::Slack::Search.query( "#{environment} #{DEPLOYER_STATUS_STARTED} #{deploy_version}", channel: slack_channel[:name] ) deployment_started_notification_regex = /\*#{environment}\* <[^|]+\|#{DEPLOYER_STATUS_STARTED}> `#{deploy_version}`$/ @started_notification_message = results .detect do |m| m.dig('blocks', 0, 'text', 'text') =~ deployment_started_notification_regex end if @started_notification_message logger.info('Found deployment started notification', slack_msg: @started_notification_message['permalink'], deploy_version: deploy_version, environment: environment, deployer_url: deployer_url) else logger.warn('Could not find deployment started notification', deploy_version: deploy_version, environment: environment, deployer_url: deployer_url) end @started_notification_message end end end end