module Dri class Report 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 = failure["title"] link = failure["web_url"] labels = failure["labels"] created_at = failure["created_at"] assignees = failure["assignees"] award_emoji_url = failure["_links"]["award_emoji"] 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 = description.empty? ? "No stack trace found" : description.split("### Stack trace").last.gsub(/\n|`|!|\[|\]/, '').squeeze(" ")[0...250] 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 = "" actions.concat actions_status_template(failure_type, assigned_status, actions_opts) actions.concat actions_fixes_template(related_mrs) @failures << [title, emojified_link, linked_pipelines, stack_trace, actions] end private def link_pipelines(iid, pipelines, description) linked = [] label_pipeline_map = { 'gitlab.com' => '/quality/production', 'canary.gitlab.com' => '/quality/canary', # 'canary.staging.gitlab.com' => '', '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 if !label_pipeline_map.has_key? pipeline pipeline_in_notes_found = false pipeline_link = '' pipeline_link_sanitized = '' pipeline_markdown = '' failure_notes.each do |note| if note["body"].include? label_pipeline_map.fetch(pipeline) pipeline_in_notes_found = true pipeline_link = URI.extract(note["body"], %w(https)) break end 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 if !pipeline_link.empty? pipeline_link_sanitized = pipeline_link.join.strip.chop pipeline_markdown = "[#{pipeline.gsub(/.gitlab.com/, '')}](#{pipeline_link_sanitized})" linked << pipeline_markdown end end linked.join(', ') end def actions_status_template(failure_type, assigned_status, actions_opts) notified_set = '' quarantined = '' reproduced = '' transient = '' notified_set = '
  • [x] notified SET
  • ' if actions_opts.include? 'pinged SET' quarantined = '
  • [x] quarantined
  • ' if actions_opts.include? 'quarantined' reproduced = '
  • [x] reproduced
  • ' if actions_opts.include? 'reproduced' transient = '
  • [x] transient
  • ' if actions_opts.include? 'transient' action_status = "Status: