# frozen_string_literal: true module GitlabQuality module TestTooling module TestMeta module Processor class AddToQuarantineProcessor < MetaProcessor QUARANTINE_METADATA = <<~META , %{indentation}quarantine: { %{indentation} issue: '%{issue_url}', %{indentation} type: %{quarantine_type} %{indentation}}%{suffix} META BRANCH_PREFIX = 'quarantine' class << self # Creates the merge requests to quarantine E2E tests # # @param [TestMetaUpdater] context instance of TestMetaUpdater def create_merge_requests(context) @context = context context.processed_commits.each_value do |record| branch, devops_stage, product_group, file = extract_data_from_record(record) mr_title = format("%{prefix} %{file}", prefix: '[E2E] QUARANTINE:', file: file).truncate(72, omission: '') gitlab_bot_user_id = context.user_id_for_username(Runtime::Env.gitlab_bot_username) merge_request = context.create_merge_request(mr_title, branch, gitlab_bot_user_id) do merge_request_description(record, devops_stage, product_group) end if merge_request Runtime::Logger.info(" Created MR for quarantine: #{merge_request.web_url}") record[:merge_request] = merge_request end end end # Performs post processing. Posts a list of MRs in a note on report_issue and Slack. # Also posts note on failure issues for un-quarantining of the quarantined # # @param [TestMetaUpdater] context instance of TestMetaUpdater def post_process(context) @context = context web_urls = context.processed_commits.values.map { |value| "- #{value[:merge_request].web_url}\n" }.join return if web_urls.empty? context.post_note_on_issue(mrs_created_note_for_report_issue(web_urls), context.report_issue) context.post_message_on_slack(mrs_created_message_for_slack(web_urls)) post_unquarantine_note_on_failure_issue end private attr_reader :context, :file_path, :file_contents, :failure_issue_url, :example_name, :mr_title, :failure_issue, :changed_line_no # Checks if the failure issue is closed or if there is already an MR open # # @return [Boolean] def proceed_with_commit? if context.issue_is_closed?(failure_issue) Runtime::Logger.info(" Failure issue '#{failure_issue_url}' is closed. Will not proceed with creating MR.") return false elsif context.commit_processed?(file_path, changed_line_no) Runtime::Logger.info(" Record already processed for #{file_path}:#{changed_line_no}. Will not proceed with creating MR.") return false elsif failure_is_related_to_test_environment? Runtime::Logger.info(" Failure issue '#{failure_issue_url}' is environment related. Will not proceed with creating MR.") return false end true end def failure_is_related_to_test_environment? context.issue_scoped_label(failure_issue, 'failure')&.split('::')&.last == 'test-environment' end def extract_data_from_record(record) first_spec = record[:commits].values.first [record[:branch], first_spec["stage"], first_spec["product_group"], first_spec["file"]] end # Posts note on failure issue to un-quarantine the test # def post_unquarantine_note_on_failure_issue context.processed_commits.each_value do |record| merge_request = record[:merge_request] next unless merge_request record[:commits].each_value do |spec| devops_stage = spec["stage"] product_group = spec["product_group"] failure_issue = spec["failure_issue"] next unless failure_issue note = context.post_note_on_issue(unquarantine_note_for_failure(spec, product_group, devops_stage, merge_request), failure_issue) Runtime::Logger.info(" Posted note on failure issue for un-quarantine: #{failure_issue}") if note end end end def merge_request_description(record, devops_stage, product_group) <<~MARKDOWN ## What does this MR do? Quarantines the following e2e tests: #{spec_details_from_commits(record[:commits])} This MR was created based on data from reliable e2e test report: #{context.report_issue} ### Check-list - [ ] General code guidelines check-list - [ ] [Code review guidelines](https://docs.gitlab.com/ee/development/code_review.html) - [ ] [Style guides](https://docs.gitlab.com/ee/development/contributing/style_guides.html) - [ ] Quarantine test check-list - [ ] Follow the [Quarantining Tests guide](https://about.gitlab.com/handbook/engineering/infrastructure/test-platform/debugging-qa-test-failures/#quarantining-tests). - [ ] Confirm the test has a [`quarantine:` tag with the specified quarantine type](https://about.gitlab.com/handbook/engineering/infrastructure/test-platform/debugging-qa-test-failures/#quarantined-test-types). - [ ] Note if the test should be [quarantined for a specific environment](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/execution_context_selection.html#quarantine-a-test-for-a-specific-environment). - [ ] (Optionally) In case of an emergency (e.g. blocked deployments), consider adding labels to pick into auto-deploy (~"Pick into auto-deploy" ~"priority::1" ~"severity::1"). - [ ] To ensure a faster turnaround, ask in the `#quality_maintainers` Slack channel for someone to review and merge the merge request, rather than assigning it directly. /label ~"Quality" ~"QA" ~"type::maintenance" ~"maintenance::pipelines" /label ~"devops::#{devops_stage}" #{context.label_from_product_group(product_group)}