# frozen_string_literal: true module Dri class Report # rubocop:disable Metrics/ClassLength using Refinements attr_reader :header, :failures, :labels def initialize(config) @labels = ['Title', 'Issue', 'Pipelines', 'Stack Trace', 'Actions'] @failures = [] @date = Date.today @today = Date.today.strftime("%Y-%m-%d") @weekday = Date.today.strftime("%A") @header = nil @api_client = ApiClient.new(config) end def set_header(timezone, username) @header = "# #{timezone}, #{@weekday} - #{@date}\n posted by: @#{username}" end def add_failure(failure, actions_opts = []) iid = failure["iid"] title = format_title(failure["title"]) link = failure["web_url"] labels = failure["labels"] created_at = failure["created_at"] assignees = failure["assignees"] description = failure["description"] related_mrs = @api_client.fetch_related_mrs(issue_iid: iid) emoji = classify_failure_emoji(created_at) emojified_link = "#{emoji} #{link}" stack_blob = if description.empty? "No stack trace found" else description.split("### Stack trace").last.gsub(/\n|`|!|\[|\]/, '').squeeze(" ")[0...250] end stack_trace = ":link:[`#{stack_blob}...`](#{link}#stack-trace)" failure_type = filter_failure_type_labels(labels) assigned_status = assigned?(assignees) pipelines = filter_pipeline_labels(labels) linked_pipelines = link_pipelines(iid, pipelines, description) actions_status = actions_status_template(failure_type, assigned_status, actions_opts) actions_fixes = actions_fixes_template(related_mrs) @failures << [title, emojified_link, linked_pipelines, stack_trace, "#{actions_status}#{actions_fixes}"] end private def link_pipelines(iid, pipelines, description) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength linked = [] label_pipeline_map = { 'gitlab.com' => '/quality/production', 'canary.gitlab.com' => '/quality/canary', 'canary.staging.gitlab.com' => '/quality/staging-canary', 'main' => '/gitlab-org/gitlab-qa-mirror', 'master' => '/gitlab-org/gitlab-qa-mirror', 'nightly' => '/quality/nightly', 'pre.gitlab.com' => '/quality/preprod', 'staging-ref' => '/quality/staging-ref', 'staging.gitlab.com' => '/quality/staging', 'release' => '/quality/release' } failure_notes = @api_client.fetch_failure_notes(issue_iid: iid) return if pipelines.empty? pipelines.each do |pipeline| next unless label_pipeline_map.has_key?(pipeline) pipeline_in_notes_found = false pipeline_link = '' pipeline_markdown = pipeline.gsub(/.gitlab.com/, '') failure_notes.each do |note| next unless note["body"].include?(label_pipeline_map.fetch(pipeline)) pipeline_in_notes_found = true pipeline_link = URI.extract(note["body"], %w[https]) end unless pipeline_in_notes_found links_description = URI.extract(description, %w[https]) pipeline_link = links_description.select { |link| link.include? label_pipeline_map.fetch(pipeline) } end unless pipeline_link.empty? pipeline_link_sanitized = pipeline_link.join.strip.chop pipeline_markdown = "[#{pipeline_markdown}](#{pipeline_link_sanitized})" end linked << pipeline_markdown end linked.join(', ') end def actions_status_template(failure_type, assigned_status, actions_opts) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity/MethodLength quarantined = '' reproduced = '' transient = '' active_investigation = '' blocking_pipelines = '' wait_for_fix = '' notified_team = '' feature_flag = '' notified_set = '