gitlab_quality-test_tooling 2.10.0 → 2.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +3 -3
  3. data/README.md +22 -5
  4. data/exe/{feature-readiness-check → feature-readiness-checklist} +2 -2
  5. data/exe/feature-readiness-evaluation +62 -0
  6. data/exe/relate-failure-issue +5 -0
  7. data/lib/gitlab_quality/test_tooling/feature_readiness/analyzed_items/analyzed_epic.rb +94 -0
  8. data/lib/gitlab_quality/test_tooling/feature_readiness/analyzed_items/analyzed_issue.rb +92 -0
  9. data/lib/gitlab_quality/test_tooling/feature_readiness/analyzed_items/analyzed_merge_request.rb +139 -0
  10. data/lib/gitlab_quality/test_tooling/feature_readiness/concerns/work_item_concern.rb +26 -12
  11. data/lib/gitlab_quality/test_tooling/feature_readiness/evaluation.rb +82 -0
  12. data/lib/gitlab_quality/test_tooling/feature_readiness/operational_readiness_check.rb +4 -4
  13. data/lib/gitlab_quality/test_tooling/gitlab_client/issues_client.rb +7 -1
  14. data/lib/gitlab_quality/test_tooling/gitlab_client/merge_requests_client.rb +21 -0
  15. data/lib/gitlab_quality/test_tooling/gitlab_client/merge_requests_dry_client.rb +0 -10
  16. data/lib/gitlab_quality/test_tooling/gitlab_client/work_items_client.rb +71 -34
  17. data/lib/gitlab_quality/test_tooling/report/concerns/results_reporter.rb +1 -1
  18. data/lib/gitlab_quality/test_tooling/report/concerns/utils.rb +3 -3
  19. data/lib/gitlab_quality/test_tooling/report/feature_readiness/report_on_epic.rb +174 -0
  20. data/lib/gitlab_quality/test_tooling/report/flaky_test_issue.rb +1 -1
  21. data/lib/gitlab_quality/test_tooling/report/generate_test_session.rb +1 -1
  22. data/lib/gitlab_quality/test_tooling/report/group_issues/error_message_normalizer.rb +49 -0
  23. data/lib/gitlab_quality/test_tooling/report/group_issues/error_pattern_matcher.rb +36 -0
  24. data/lib/gitlab_quality/test_tooling/report/group_issues/failure_processor.rb +73 -0
  25. data/lib/gitlab_quality/test_tooling/report/group_issues/group_results_in_issues.rb +48 -0
  26. data/lib/gitlab_quality/test_tooling/report/group_issues/incident_checker.rb +61 -0
  27. data/lib/gitlab_quality/test_tooling/report/group_issues/issue_base.rb +48 -0
  28. data/lib/gitlab_quality/test_tooling/report/group_issues/issue_creator.rb +44 -0
  29. data/lib/gitlab_quality/test_tooling/report/group_issues/issue_finder.rb +79 -0
  30. data/lib/gitlab_quality/test_tooling/report/group_issues/issue_formatter.rb +83 -0
  31. data/lib/gitlab_quality/test_tooling/report/group_issues/issue_manager.rb +33 -0
  32. data/lib/gitlab_quality/test_tooling/report/group_issues/issue_updater.rb +87 -0
  33. data/lib/gitlab_quality/test_tooling/report/relate_failure_issue.rb +149 -12
  34. data/lib/gitlab_quality/test_tooling/runtime/env.rb +1 -1
  35. data/lib/gitlab_quality/test_tooling/test_meta/processor/add_to_blocking_processor.rb +1 -1
  36. data/lib/gitlab_quality/test_tooling/test_meta/processor/add_to_quarantine_processor.rb +1 -1
  37. data/lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb +38 -8
  38. data/lib/gitlab_quality/test_tooling/test_result/base_test_result.rb +17 -4
  39. data/lib/gitlab_quality/test_tooling/version.rb +1 -1
  40. data/lib/gitlab_quality/test_tooling.rb +2 -0
  41. metadata +34 -10
@@ -3,6 +3,10 @@
3
3
  require 'nokogiri'
4
4
  require 'rubygems/text'
5
5
 
6
+ require_relative 'group_issues/error_pattern_matcher'
7
+ require_relative 'group_issues/error_message_normalizer'
8
+ require_relative 'group_issues/group_results_in_issues'
9
+
6
10
  module GitlabQuality
7
11
  module TestTooling
8
12
  module Report
@@ -12,6 +16,7 @@ module GitlabQuality
12
16
  # - Takes a project where failure issues should be created
13
17
  # - Find issue by title (with test description or test file), then further filter by stack trace, then pick the better-matching one
14
18
  # - Add the failed job to the issue description, and update labels
19
+ # - Can group similar failures together when group_similar option is enabled
15
20
  class RelateFailureIssue < ReportAsIssue
16
21
  include TestTooling::Concerns::FindSetDri
17
22
  include Concerns::GroupAndCategoryLabels
@@ -23,16 +28,23 @@ module GitlabQuality
23
28
  FAILURE_STACKTRACE_REGEX = %r{(?:(?:.*Failure/Error:(?<stacktrace>.+))|(?<stacktrace>.+))}m
24
29
  ISSUE_STACKTRACE_REGEX = /### Stack trace\s*(```)#{FAILURE_STACKTRACE_REGEX}(```)\n*\n###/m
25
30
 
26
- NEW_ISSUE_LABELS = Set.new(%w[test failure::new priority::2 automation:bot-authored]).freeze
31
+ NEW_ISSUE_LABELS = Set.new(%w[test failure::new priority::2 automation:bot-authored type::maintenance]).freeze
27
32
  SCREENSHOT_IGNORED_ERRORS = ['500 Internal Server Error', 'fabricate_via_api!', 'Error Code 500'].freeze
28
-
33
+ FAILURE_ISSUE_GUIDE_URL = "https://handbook.gitlab.com/handbook/engineering/testing/guide-to-e2e-test-failure-issues/"
34
+ FAILURE_ISSUE_HANDBOOK_GUIDE = "**:rotating_light: [End-to-End Test Failure Issue Debugging Guide](#{FAILURE_ISSUE_GUIDE_URL}) :rotating_light:**\n".freeze
29
35
  # Map commits to security fork (gitlab-org/security/gitlab) for gitlab-org/gitlab since security patches exist
30
36
  # there before being released to the public repository
31
37
  DIFF_PROJECT_MAPPINGS = {
38
+ 'gitlab-org/quality/e2e-test-issues' => 'gitlab-org/security/gitlab',
32
39
  'gitlab-org/gitlab' => 'gitlab-org/security/gitlab',
33
40
  'gitlab-org/customers-gitlab-com' => 'gitlab-org/customers-gitlab-com'
34
41
  }.freeze
35
42
 
43
+ # Don't use the E2E test issues project for commit parent
44
+ COMMIT_PROJECT_MAPPINGS = {
45
+ 'gitlab-org/quality/e2e-test-issues' => 'gitlab-org/gitlab'
46
+ }.freeze
47
+
36
48
  # The project contains record of the deployments we use to determine the commit diff
37
49
  OPS_RELEASES_METADATA_PROJECT = 'gitlab-org/release/metadata'
38
50
 
@@ -56,6 +68,7 @@ module GitlabQuality
56
68
  base_issue_labels: nil,
57
69
  exclude_labels_for_search: nil,
58
70
  metrics_files: [],
71
+ group_similar: false,
59
72
  **kwargs)
60
73
  super
61
74
  @max_diff_ratio = max_diff_ratio.to_f
@@ -65,19 +78,106 @@ module GitlabQuality
65
78
  @issue_type = 'issue'
66
79
  @commented_issue_list = Set.new
67
80
  @metrics_files = Array(metrics_files)
81
+ @group_similar = group_similar
68
82
  end
69
83
 
70
84
  private
71
85
 
72
- attr_reader :max_diff_ratio, :system_logs, :base_issue_labels, :exclude_labels_for_search, :metrics_files, :ops_gitlab_client
86
+ attr_reader :max_diff_ratio, :system_logs, :base_issue_labels, :exclude_labels_for_search, :metrics_files, :ops_gitlab_client, :group_similar
73
87
 
74
88
  def run!
75
89
  puts "Reporting test failures in `#{files.join(',')}` as issues in project `#{project}` via the API at `#{Runtime::Env.gitlab_api_base}`."
76
90
 
91
+ if group_similar
92
+ run_with_grouping!
93
+ else
94
+ TestResults::Builder.new(token: token, project: project, file_glob: files).test_results_per_file do |test_results|
95
+ puts "=> Reporting #{test_results.count} tests in #{test_results.path}"
96
+ process_test_results(test_results)
97
+ end
98
+ end
99
+ end
100
+
101
+ def grouper
102
+ @grouper ||= GitlabQuality::TestTooling::Report::GroupIssues::GroupResultsInIssues.new(
103
+ gitlab: gitlab,
104
+ config: grouper_config
105
+ )
106
+ end
107
+
108
+ def run_with_grouping!
109
+ Runtime::Logger.info "=> Grouping similar failures where possible"
110
+
111
+ all_test_results = collect_all_test_results
112
+ return if all_test_results.empty?
113
+
114
+ Runtime::Logger.info "=> Processing #{all_test_results.count} failures with GroupResultsInIssues"
115
+
116
+ failure_data = convert_test_results_to_failure_data(all_test_results)
117
+
118
+ grouper.process_failures(failure_data)
119
+ grouper.process_issues
120
+ end
121
+
122
+ def collect_all_test_results
123
+ all_test_results = []
124
+
77
125
  TestResults::Builder.new(token: token, project: project, file_glob: files).test_results_per_file do |test_results|
78
- puts "=> Reporting #{test_results.count} tests in #{test_results.path}"
79
- process_test_results(test_results)
126
+ Runtime::Logger.info "=> Collecting #{test_results.count} tests from #{test_results.path}"
127
+ all_test_results.concat(test_results.select(&:failures?))
80
128
  end
129
+
130
+ all_test_results
131
+ end
132
+
133
+ def convert_test_results_to_failure_data(test_results)
134
+ test_results.map do |test|
135
+ {
136
+ description: test.name,
137
+ full_description: test.name,
138
+ file_path: test.relative_file,
139
+ line_number: extract_line_number(test),
140
+ exception: extract_exception_data(test),
141
+ ci_job_url: test.ci_job_url,
142
+ testcase: extract_test_id_or_name(test),
143
+ product_group: extract_product_group(test),
144
+ level: extract_level(test)
145
+ }
146
+ end
147
+ end
148
+
149
+ def extract_line_number(test)
150
+ test.respond_to?(:line_number) ? test.line_number : nil
151
+ end
152
+
153
+ def extract_exception_data(test)
154
+ {
155
+ 'message' => test.failures.first&.dig('message') || test.full_stacktrace || 'Unknown error'
156
+ }
157
+ end
158
+
159
+ def extract_product_group(test)
160
+ test.respond_to?(:product_group) ? test.product_group : nil
161
+ end
162
+
163
+ def extract_level(test)
164
+ test.respond_to?(:level) ? test.level : nil
165
+ end
166
+
167
+ def grouper_config
168
+ {
169
+ thresholds: {
170
+ min_failures_to_group: 2
171
+ }
172
+ }
173
+ end
174
+
175
+ def extract_test_id_or_name(test)
176
+ return test.example_id if test.respond_to?(:example_id)
177
+ return test.id if test.respond_to?(:id)
178
+ return test.name if test.respond_to?(:name)
179
+
180
+ "#{test.relative_file}:#{test.respond_to?(:line_number) ? test.line_number : 'unknown'}"
81
181
  end
82
182
 
83
183
  def new_issue_labels(test)
@@ -179,7 +279,9 @@ module GitlabQuality
179
279
  end
180
280
 
181
281
  created_issue = super
182
- test.failure_issue ||= created_issue.web_url
282
+
283
+ # On a dry run, created_issue may not be populated
284
+ test.failure_issue ||= created_issue&.web_url
183
285
 
184
286
  created_issue
185
287
  end
@@ -300,7 +402,7 @@ module GitlabQuality
300
402
  end
301
403
 
302
404
  def new_issue_description(test)
303
- super + [
405
+ FAILURE_ISSUE_HANDBOOK_GUIDE + super + [
304
406
  "\n#{commit_diff_section}",
305
407
  "### Stack trace",
306
408
  "```\n#{test.full_stacktrace}\n```",
@@ -318,10 +420,10 @@ module GitlabQuality
318
420
  initialize_gitlab_ops_client
319
421
 
320
422
  if Runtime::Env.ci_pipeline_url.include?('ops.gitlab.net')
321
- pipeline = ops_gitlab_client.find_pipeline(project, Runtime::Env.ci_pipeline_id.to_i)
423
+ pipeline = ops_gitlab_client.find_pipeline(Runtime::Env.ci_project_path, Runtime::Env.ci_pipeline_id.to_i)
322
424
  generate_ops_gitlab_diff(pipeline)
323
425
  else
324
- pipeline = gitlab.find_pipeline(project, Runtime::Env.ci_pipeline_id.to_i)
426
+ pipeline = gitlab.find_pipeline(Runtime::Env.ci_project_path, Runtime::Env.ci_pipeline_id.to_i)
325
427
  generate_gitlab_diff(pipeline)
326
428
  end
327
429
  end
@@ -342,6 +444,8 @@ module GitlabQuality
342
444
  end
343
445
 
344
446
  def fetch_deployment_info(pipeline)
447
+ return 'No pipeline name set.' unless Runtime::Env.ci_pipeline_name
448
+
345
449
  pipeline_deploy_version = Runtime::Env.ci_pipeline_name.match(/(\d+\.\d+\.\d+)(?:-|$)/)&.captures&.first
346
450
  deployments = fetch_deployments(ops_gitlab_client, pipeline)
347
451
  found_deployment = find_matching_deployment(pipeline_deploy_version, deployments)
@@ -427,7 +531,8 @@ module GitlabQuality
427
531
 
428
532
  def generate_gitlab_diff(pipeline)
429
533
  pipeline_sha = pipeline.sha
430
- parent_sha = gitlab.find_commit_parent(project, pipeline_sha)
534
+ commit_project = COMMIT_PROJECT_MAPPINGS.fetch(project, project)
535
+ parent_sha = gitlab.find_commit_parent(commit_project, pipeline_sha)
431
536
  diff_project = if DIFF_PROJECT_MAPPINGS.key?(project)
432
537
  DIFF_PROJECT_MAPPINGS[project]
433
538
  else
@@ -457,10 +562,40 @@ module GitlabQuality
457
562
  end
458
563
 
459
564
  def new_issue_assignee_id(test)
460
- return unless test.product_group?
565
+ assignee_id = try_feature_category_assignment(test)
566
+ return assignee_id if assignee_id
567
+
568
+ try_product_group_assignment(test)
569
+ end
570
+
571
+ def try_feature_category_assignment(test)
572
+ unless test.respond_to?(:feature_category) && test.feature_category?
573
+ Runtime::Logger.info("No feature_category found for DRI assignment")
574
+ return
575
+ end
576
+
577
+ labels_inference = GitlabQuality::TestTooling::LabelsInference.new
578
+ product_group = labels_inference.product_group_from_feature_category(test.feature_category)
579
+
580
+ unless product_group
581
+ Runtime::Logger.warn("Could not map feature_category '#{test.feature_category}' to product_group")
582
+ return
583
+ end
584
+
585
+ dri = test_dri(product_group, test.stage, test.section)
586
+ Runtime::Logger.info("Assigning #{dri} as DRI for the issue (via feature_category).")
587
+
588
+ gitlab.find_user_id(username: dri)
589
+ end
590
+
591
+ def try_product_group_assignment(test)
592
+ unless test.respond_to?(:product_group) && test.product_group?
593
+ Runtime::Logger.info("No product_group found for DRI assignment")
594
+ return
595
+ end
461
596
 
462
597
  dri = test_dri(test.product_group, test.stage, test.section)
463
- puts " => Assigning #{dri} as DRI for the issue."
598
+ Runtime::Logger.info("Assigning #{dri} as DRI for the issue (via product_group).")
464
599
 
465
600
  gitlab.find_user_id(username: dri)
466
601
  end
@@ -542,6 +677,8 @@ module GitlabQuality
542
677
  end
543
678
 
544
679
  def screenshot_artifact_url(test)
680
+ return "" unless test.screenshot_image
681
+
545
682
  ci_job_url = test.ci_job_url
546
683
  screenshot_path = test.screenshot_image[%r{qa/.*$}]
547
684
 
@@ -46,7 +46,7 @@ module GitlabQuality
46
46
  end
47
47
 
48
48
  def default_branch
49
- env_var_value_if_defined('QA_DEFAULT_BRANCH') || 'main'
49
+ 'master'
50
50
  end
51
51
 
52
52
  def ci_api_v4_url
@@ -97,7 +97,7 @@ module GitlabQuality
97
97
 
98
98
  This MR was created based on data from reliable e2e test report: #{context.report_issue}
99
99
 
100
- /label ~"Quality" ~"QA" ~"type::maintenance"
100
+ /label ~"E2E" ~"type::maintenance"
101
101
  /label ~"devops::#{devops_stage}"
102
102
  #{context.label_from_product_group(product_group)}
103
103
 
@@ -137,7 +137,7 @@ module GitlabQuality
137
137
  - [ ] 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.
138
138
 
139
139
  <!-- Base labels. -->
140
- /label ~"Quality" ~"QA" ~"type::maintenance" ~"maintenance::pipelines"
140
+ /label ~"E2E" ~"type::maintenance" ~"maintenance::pipelines"
141
141
 
142
142
  <!--
143
143
  Choose the stage that appears in the test path, e.g. ~"devops::create" for
@@ -8,7 +8,7 @@ module GitlabQuality
8
8
  class TestMetaUpdater
9
9
  include TestTooling::Concerns::FindSetDri
10
10
 
11
- attr_reader :project, :ref, :report_issue, :processed_commits
11
+ attr_reader :project, :ref, :report_issue, :processed_commits, :token, :specs_file, :dry_run, :processor
12
12
 
13
13
  TEST_PLATFORM_MAINTAINERS_SLACK_CHANNEL_ID = 'C0437FV9KBN' # test-platform-maintainers
14
14
 
@@ -269,12 +269,15 @@ module GitlabQuality
269
269
  # Fetch the id for the dri of the product group and stage
270
270
  # The first item returned is the id of the assignee and the second item is the handle
271
271
  #
272
- # @param [String] product_group
272
+ # @param [Hash] test object
273
273
  # @param [String] devops_stage
274
+ # @param [String] section
274
275
  # @return [Array<Integer, String>]
275
- def fetch_dri_id(product_group, devops_stage, section)
276
- assignee_handle = ENV.fetch('QA_TEST_DRI_HANDLE', nil) || test_dri(product_group, devops_stage, section)
276
+ def fetch_dri_id(test, devops_stage, section)
277
+ product_group = determine_product_group(test)
278
+ return unless product_group
277
279
 
280
+ assignee_handle = ENV.fetch('QA_TEST_DRI_HANDLE', nil) || test_dri(product_group, devops_stage, section)
278
281
  [user_id_for_username(assignee_handle), assignee_handle]
279
282
  end
280
283
 
@@ -335,6 +338,16 @@ module GitlabQuality
335
338
  label ? %(/label ~"#{label}") : ''
336
339
  end
337
340
 
341
+ # Infers the group label from the provided feature category
342
+ #
343
+ # @param [String] feature_category feature category
344
+ # @return [String]
345
+ def label_from_feature_category(feature_category)
346
+ labels = labels_inference.infer_labels_from_feature_category(feature_category)
347
+ group_label = labels.find { |label| label.start_with?('group::') }
348
+ group_label ? %(/label ~"#{group_label}") : ''
349
+ end
350
+
338
351
  # Returns the link to the Grafana dashboard for single spec metrics
339
352
  #
340
353
  # @param [String] example_name the full example name
@@ -344,10 +357,6 @@ module GitlabQuality
344
357
  base_url + CGI.escape(example_name)
345
358
  end
346
359
 
347
- private
348
-
349
- attr_reader :token, :specs_file, :dry_run, :processor
350
-
351
360
  # Returns any test description string within single or double quotes
352
361
  #
353
362
  # @param [String] line the line to check for any quoted string
@@ -380,6 +389,27 @@ module GitlabQuality
380
389
  def labels_inference
381
390
  @labels_inference ||= GitlabQuality::TestTooling::LabelsInference.new
382
391
  end
392
+
393
+ private
394
+
395
+ def determine_product_group(test)
396
+ return map_feature_category_to_product_group(test) if has_feature_category?(test)
397
+ return test.product_group if has_product_group?(test)
398
+
399
+ nil
400
+ end
401
+
402
+ def has_feature_category?(test)
403
+ test.respond_to?(:feature_category) && test.feature_category?
404
+ end
405
+
406
+ def has_product_group?(test)
407
+ test.respond_to?(:product_group) && test.product_group?
408
+ end
409
+
410
+ def map_feature_category_to_product_group(test)
411
+ labels_inference.product_group_from_feature_category(test.feature_category)
412
+ end
383
413
  end
384
414
  end
385
415
  end
@@ -14,7 +14,8 @@ module GitlabQuality
14
14
  "Error reference number: 502",
15
15
  "(502): `GitLab is not responding`",
16
16
  "<head><title>502 Bad Gateway</title></head>",
17
- "14:connections to all backends failing"
17
+ "14:connections to all backends failing",
18
+ "gitlab_canary=true cookie was set in browser but 'Next' badge was not shown on UI"
18
19
  ].freeze
19
20
 
20
21
  SHARED_EXAMPLES_CALLERS = %w[include_examples it_behaves_like].freeze
@@ -72,6 +73,10 @@ module GitlabQuality
72
73
  product_group != ''
73
74
  end
74
75
 
76
+ def feature_category?
77
+ feature_category && !feature_category.empty?
78
+ end
79
+
75
80
  def failure_issue
76
81
  report['failure_issue']
77
82
  end
@@ -114,7 +119,7 @@ module GitlabQuality
114
119
  end
115
120
 
116
121
  def file_base_url
117
- @file_base_url ||= "https://gitlab.com/#{project}/-/blob/#{ref}/"
122
+ @file_base_url ||= "https://gitlab.com/#{project == 'gitlab-org/quality/e2e-test-issues' ? 'gitlab-org/gitlab' : project}/-/blob/#{ref}/"
118
123
  end
119
124
 
120
125
  def test_file_link
@@ -143,15 +148,23 @@ module GitlabQuality
143
148
  def files_client
144
149
  @files_client ||= GitlabClient::RepositoryFilesClient.new(
145
150
  token: token,
146
- project: project,
151
+ project: mapped_project,
147
152
  file_path: file,
148
- ref: ref)
153
+ ref: ref.nil? || ref.empty? ? 'master' : ref)
149
154
  end
150
155
 
151
156
  private
152
157
 
153
158
  attr_reader :token, :project, :ref
154
159
 
160
+ def mapped_project
161
+ if project == 'gitlab-org/quality/e2e-test-issues'
162
+ 'gitlab-org/gitlab'
163
+ else
164
+ project
165
+ end
166
+ end
167
+
155
168
  def screenshot
156
169
  report.fetch('screenshot', nil)
157
170
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GitlabQuality
4
4
  module TestTooling
5
- VERSION = "2.10.0"
5
+ VERSION = "2.18.0"
6
6
  end
7
7
  end
@@ -7,6 +7,8 @@ module GitlabQuality
7
7
  module TestTooling
8
8
  Error = Class.new(StandardError)
9
9
  loader = Zeitwerk::Loader.new
10
+ loader.push_dir(__dir__.to_s, namespace: GitlabQuality)
11
+ loader.ignore("#{__dir__}/test_tooling.rb")
10
12
  loader.push_dir("#{__dir__}/test_tooling", namespace: GitlabQuality::TestTooling)
11
13
  loader.ignore("#{__dir__}/test_tooling/version.rb")
12
14
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab_quality-test_tooling
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.10.0
4
+ version: 2.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab Quality
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-04-23 00:00:00.000000000 Z
11
+ date: 2025-08-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control
@@ -263,7 +263,7 @@ dependencies:
263
263
  version: '4.19'
264
264
  - - "<"
265
265
  - !ruby/object:Gem::Version
266
- version: '6.0'
266
+ version: '7.0'
267
267
  type: :runtime
268
268
  prerelease: false
269
269
  version_requirements: !ruby/object:Gem::Requirement
@@ -273,7 +273,7 @@ dependencies:
273
273
  version: '4.19'
274
274
  - - "<"
275
275
  - !ruby/object:Gem::Version
276
- version: '6.0'
276
+ version: '7.0'
277
277
  - !ruby/object:Gem::Dependency
278
278
  name: http
279
279
  requirement: !ruby/object:Gem::Requirement
@@ -380,16 +380,22 @@ dependencies:
380
380
  name: rspec-parameterized
381
381
  requirement: !ruby/object:Gem::Requirement
382
382
  requirements:
383
- - - "~>"
383
+ - - ">="
384
+ - !ruby/object:Gem::Version
385
+ version: '1.0'
386
+ - - "<"
384
387
  - !ruby/object:Gem::Version
385
- version: 1.0.0
388
+ version: '3.0'
386
389
  type: :runtime
387
390
  prerelease: false
388
391
  version_requirements: !ruby/object:Gem::Requirement
389
392
  requirements:
390
- - - "~>"
393
+ - - ">="
394
+ - !ruby/object:Gem::Version
395
+ version: '1.0'
396
+ - - "<"
391
397
  - !ruby/object:Gem::Version
392
- version: 1.0.0
398
+ version: '3.0'
393
399
  - !ruby/object:Gem::Dependency
394
400
  name: table_print
395
401
  requirement: !ruby/object:Gem::Requirement
@@ -431,7 +437,8 @@ executables:
431
437
  - detect-infrastructure-failures
432
438
  - existing-test-health-issue
433
439
  - failed-test-issues
434
- - feature-readiness-check
440
+ - feature-readiness-checklist
441
+ - feature-readiness-evaluation
435
442
  - flaky-test-issues
436
443
  - generate-test-session
437
444
  - knapsack-report-issues
@@ -463,7 +470,8 @@ files:
463
470
  - exe/detect-infrastructure-failures
464
471
  - exe/existing-test-health-issue
465
472
  - exe/failed-test-issues
466
- - exe/feature-readiness-check
473
+ - exe/feature-readiness-checklist
474
+ - exe/feature-readiness-evaluation
467
475
  - exe/flaky-test-issues
468
476
  - exe/generate-test-session
469
477
  - exe/knapsack-report-issues
@@ -479,8 +487,12 @@ files:
479
487
  - lib/gitlab_quality/test_tooling.rb
480
488
  - lib/gitlab_quality/test_tooling/concerns/find_set_dri.rb
481
489
  - lib/gitlab_quality/test_tooling/failed_jobs_table.rb
490
+ - lib/gitlab_quality/test_tooling/feature_readiness/analyzed_items/analyzed_epic.rb
491
+ - lib/gitlab_quality/test_tooling/feature_readiness/analyzed_items/analyzed_issue.rb
492
+ - lib/gitlab_quality/test_tooling/feature_readiness/analyzed_items/analyzed_merge_request.rb
482
493
  - lib/gitlab_quality/test_tooling/feature_readiness/concerns/issue_concern.rb
483
494
  - lib/gitlab_quality/test_tooling/feature_readiness/concerns/work_item_concern.rb
495
+ - lib/gitlab_quality/test_tooling/feature_readiness/evaluation.rb
484
496
  - lib/gitlab_quality/test_tooling/feature_readiness/operational_readiness_check.rb
485
497
  - lib/gitlab_quality/test_tooling/gitlab_client/branches_client.rb
486
498
  - lib/gitlab_quality/test_tooling/gitlab_client/branches_dry_client.rb
@@ -507,8 +519,20 @@ files:
507
519
  - lib/gitlab_quality/test_tooling/report/concerns/results_reporter.rb
508
520
  - lib/gitlab_quality/test_tooling/report/concerns/utils.rb
509
521
  - lib/gitlab_quality/test_tooling/report/failed_test_issue.rb
522
+ - lib/gitlab_quality/test_tooling/report/feature_readiness/report_on_epic.rb
510
523
  - lib/gitlab_quality/test_tooling/report/flaky_test_issue.rb
511
524
  - lib/gitlab_quality/test_tooling/report/generate_test_session.rb
525
+ - lib/gitlab_quality/test_tooling/report/group_issues/error_message_normalizer.rb
526
+ - lib/gitlab_quality/test_tooling/report/group_issues/error_pattern_matcher.rb
527
+ - lib/gitlab_quality/test_tooling/report/group_issues/failure_processor.rb
528
+ - lib/gitlab_quality/test_tooling/report/group_issues/group_results_in_issues.rb
529
+ - lib/gitlab_quality/test_tooling/report/group_issues/incident_checker.rb
530
+ - lib/gitlab_quality/test_tooling/report/group_issues/issue_base.rb
531
+ - lib/gitlab_quality/test_tooling/report/group_issues/issue_creator.rb
532
+ - lib/gitlab_quality/test_tooling/report/group_issues/issue_finder.rb
533
+ - lib/gitlab_quality/test_tooling/report/group_issues/issue_formatter.rb
534
+ - lib/gitlab_quality/test_tooling/report/group_issues/issue_manager.rb
535
+ - lib/gitlab_quality/test_tooling/report/group_issues/issue_updater.rb
512
536
  - lib/gitlab_quality/test_tooling/report/health_problem_reporter.rb
513
537
  - lib/gitlab_quality/test_tooling/report/issue_logger.rb
514
538
  - lib/gitlab_quality/test_tooling/report/knapsack_report_issue.rb