gitlab_quality-test_tooling 3.9.0 → 3.10.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: acd13e22b4fd23cb52365b1137833a0348af808f009a644e36a667c8f8fc0cb9
4
- data.tar.gz: eb62c1b5bcd4e763ed35d7425e04b7e19743f40fcaa1e3493b186806443ce517
3
+ metadata.gz: 6c49f987999c6124651b5f1f21de7d588d1940749b91f8527e21b9fcbbb1921b
4
+ data.tar.gz: 384d0765fb0d891e373777004ad20a5cecbc2df9b07cc74ca1b70ae30a080641
5
5
  SHA512:
6
- metadata.gz: 11c99a5294a20167082412d9aa89804b417c982cdf470a58bf9749cac9d1edc264bdfb6d4a580a3b0589a2ec7f97d38959c072504473bc495ef6418e9e1e0185
7
- data.tar.gz: f5c10bf74809af017c60b0533ab6f42afafa7c06f328b34856796faa02b65974865de40fb1597edb27af64a6eabd4846c34147d70061b42a13f3232a8a72c295
6
+ metadata.gz: 4ff2cc394058616512c5c00779772d244d08986e12762a49c17ca9e31065a4af6b79beaeb8ceb7ac35c290efb10410c5888aff363b183d4190bb9b863278a418
7
+ data.tar.gz: 8cc8717e64a9c260ca10474897aae319bae9565a1257815e3a83e931049d8d0c61c32fb38d9b66f13976f0f0e1ec4e7d3666f5c3311c5e64cae0c25940ff5da6
data/.rubocop_todo.yml CHANGED
@@ -59,9 +59,3 @@ Style/RedundantReturn:
59
59
  Exclude:
60
60
  - 'lib/gitlab_quality/test_tooling/runtime/env.rb'
61
61
 
62
- # Offense count: 1
63
- # This cop supports unsafe autocorrection (--autocorrect-all).
64
- # Configuration parameters: AllowedMethods, AllowedPatterns.
65
- Style/ReturnNilInPredicateMethodDefinition:
66
- Exclude:
67
- - 'lib/gitlab_quality/test_tooling/knapsack_reports/spec_run_time.rb'
data/AGENTS.md ADDED
@@ -0,0 +1,95 @@
1
+ # gitlab_quality-test_tooling
2
+
3
+ Ruby gem providing test tooling for GitLab CI — metrics export, test quarantine, failure reporting, flaky test tracking, and code coverage analysis.
4
+
5
+ ## Tech Stack
6
+
7
+ - Ruby (see `.ruby-version` and gemspec for version), gem published to RubyGems
8
+ - RSpec for testing, RuboCop (`gitlab-styles` base) for linting
9
+ - Lefthook for pre-push hooks (rspec, rubocop, changelog trailer check)
10
+
11
+ ## Testing
12
+
13
+ ```bash
14
+ bundle exec rspec
15
+ bundle exec rubocop
16
+ ```
17
+
18
+ ## Commit Conventions
19
+
20
+ Every branch must have a `Changelog:` git trailer on its **first commit** (relative to `origin/main`).
21
+
22
+ Valid values: `added`, `fixed`, `changed`, `deprecated`, `removed`, `security`, `performance`, `other`
23
+
24
+ Example:
25
+
26
+ ```
27
+ Fix failure_exception for MultipleExceptionError
28
+
29
+ Description of the change.
30
+
31
+ Changelog: fixed
32
+ ```
33
+
34
+ ### Enforcement
35
+
36
+ - **lefthook pre-push hook** checks the first commit on the branch
37
+ - **gitlab-dangerfiles** checks in CI (Danger bot comments on MRs)
38
+ - `--no-verify` bypasses lefthook locally, but CI will still fail without the trailer
39
+
40
+ ### Choosing the right value
41
+
42
+ | Value | When to use |
43
+ |-------|-------------|
44
+ | `added` | New feature or capability |
45
+ | `fixed` | Bug fix |
46
+ | `changed` | Non-breaking change to existing behavior |
47
+ | `deprecated` | Feature marked for removal |
48
+ | `removed` | Feature removed |
49
+ | `security` | Security fix |
50
+ | `performance` | Performance improvement |
51
+ | `other` | Refactoring, docs, CI changes |
52
+
53
+ Reference: https://docs.gitlab.com/ee/development/changelog.html
54
+
55
+ ### Commit Message Format
56
+
57
+ - Present tense ("Fix bug" not "Fixed bug")
58
+ - First line under 72 characters
59
+ - Blank line between subject and body
60
+ - `Changelog:` trailer at the end of the first commit's message, after a blank line
61
+
62
+ ## Project Structure
63
+
64
+ | Directory | Purpose |
65
+ |-----------|---------|
66
+ | `lib/gitlab_quality/test_tooling/` | Main gem code |
67
+ | `exe/` | CLI executables |
68
+ | `spec/` | RSpec tests |
69
+ | `.gitlab/changelog_config.yml` | Changelog category mapping |
70
+
71
+ ## Key Modules
72
+
73
+ - **TestMetricsExporter** — Serializes RSpec results to ClickHouse (exception classes, failure messages, CI metadata)
74
+ - **Report** — Creates/updates GitLab issues for test failures, flaky tests, slow tests
75
+ - **TestQuarantine** — RSpec formatter that skips quarantined tests
76
+ - **CodeCoverage** — Coverage analysis and responsibility patterns
77
+ - **ClickHouse::Client** — Batch HTTP client for pushing metrics
78
+
79
+ ## Release Process
80
+
81
+ The [automated gem release process](https://gitlab.com/gitlab-org/quality/pipeline-common#release-process) publishes new versions via CI. It will:
82
+
83
+ - Publish the gem to https://rubygems.org/gems/gitlab_quality-test_tooling
84
+ - Create a release at https://gitlab.com/gitlab-org/ruby/gems/gitlab_quality-test_tooling/-/releases
85
+ - Populate release notes from changelog entries
86
+
87
+ ### Steps to release
88
+
89
+ 1. Create a branch (e.g., `bump-version-X-Y-Z`)
90
+ 2. Update `lib/gitlab_quality/test_tooling/version.rb` with the new version
91
+ 3. Run `bundle install` to update `Gemfile.lock`
92
+ 4. Commit with message like `Update gem version to X.Y.Z` and trailer `Changelog: changed`
93
+ 5. Create an MR using the **Release** MR template (`.gitlab/merge_request_templates/Release.md`)
94
+ 6. Fill in the template: update the diff link, check release notes, verify SemVer
95
+ 7. Get the MR merged by a maintainer — CI will publish the gem automatically
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab_quality-test_tooling (3.9.0)
4
+ gitlab_quality-test_tooling (3.10.1)
5
5
  activesupport (>= 7.0)
6
6
  amatch (~> 0.4.1)
7
7
  fog-google (~> 1.24, >= 1.24.1)
data/README.md CHANGED
@@ -141,21 +141,6 @@ Usage: exe/slow-test-issues [options]
141
141
  -h, --help Show the usage
142
142
  ```
143
143
 
144
- ### `exe/knapsack-report-issues`
145
-
146
- ```shell
147
- Purpose: Create spec run time issue when a spec file almost caused job timeout because it ran significantly longer than what Knapsack expected.
148
- Usage: exe/knapsack-report-issues [options]
149
- -i, --input-file INPUT_FILE Knapsack actual run time report file path glob
150
- -e EXPECTED_REPORT, Knapsack expected report file path
151
- --expected-report
152
- -p, --project PROJECT Can be an integer or a group/project string
153
- -t, --token TOKEN A valid access token with `api` scope and Maintainer permission in PROJECT
154
- --dry-run Perform a dry-run (don't create issues)
155
- -v, --version Show the version
156
- -h, --help Show the usage
157
- ```
158
-
159
144
  ### `exe/failed-test-issues`
160
145
 
161
146
  ```shell
@@ -161,14 +161,23 @@ module GitlabQuality
161
161
  exception.all_exceptions.flatten
162
162
  end
163
163
 
164
- # Truncated exception stacktrace
164
+ # Truncated exception message
165
+ #
166
+ # For MultipleExceptionError, returns the first wrapped exception's message
167
+ # instead of the unhelpful wrapper class name.
165
168
  #
166
169
  # @return [String]
167
170
  def failure_exception
168
171
  exception = example.execution_result.exception
169
172
  return unless exception
170
173
 
171
- exception.to_s.tr("\n", " ").slice(0, 1000)
174
+ source = if exception.respond_to?(:all_exceptions)
175
+ exception.all_exceptions.flatten.first || exception
176
+ else
177
+ exception
178
+ end
179
+
180
+ source.to_s.tr("\n", " ").slice(0, 1000)
172
181
  end
173
182
 
174
183
  # Test run type | suite name
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GitlabQuality
4
4
  module TestTooling
5
- VERSION = "3.9.0"
5
+ VERSION = "3.10.1"
6
6
  end
7
7
  end
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: 3.9.0
4
+ version: 3.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab Quality
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-03-04 00:00:00.000000000 Z
11
+ date: 2026-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control
@@ -420,7 +420,6 @@ executables:
420
420
  - feature-readiness-checklist
421
421
  - feature-readiness-evaluation
422
422
  - flaky-test-issues
423
- - knapsack-report-issues
424
423
  - post-to-slack
425
424
  - prepare-stage-reports
426
425
  - relate-failure-issue
@@ -439,6 +438,7 @@ files:
439
438
  - ".rubocop_todo.yml"
440
439
  - ".ruby-version"
441
440
  - ".tool-versions"
441
+ - AGENTS.md
442
442
  - CODE_OF_CONDUCT.md
443
443
  - CONTRIBUTING.md
444
444
  - Dangerfile
@@ -454,7 +454,6 @@ files:
454
454
  - exe/feature-readiness-checklist
455
455
  - exe/feature-readiness-evaluation
456
456
  - exe/flaky-test-issues
457
- - exe/knapsack-report-issues
458
457
  - exe/post-to-slack
459
458
  - exe/prepare-stage-reports
460
459
  - exe/relate-failure-issue
@@ -514,8 +513,6 @@ files:
514
513
  - lib/gitlab_quality/test_tooling/gitlab_client/work_items_client.rb
515
514
  - lib/gitlab_quality/test_tooling/gitlab_client/work_items_dry_client.rb
516
515
  - lib/gitlab_quality/test_tooling/job_trace_analyzer.rb
517
- - lib/gitlab_quality/test_tooling/knapsack_reports/spec_run_time.rb
518
- - lib/gitlab_quality/test_tooling/knapsack_reports/spec_run_time_report.rb
519
516
  - lib/gitlab_quality/test_tooling/labels_inference.rb
520
517
  - lib/gitlab_quality/test_tooling/report/concerns/group_and_category_labels.rb
521
518
  - lib/gitlab_quality/test_tooling/report/concerns/issue_reports.rb
@@ -537,7 +534,6 @@ files:
537
534
  - lib/gitlab_quality/test_tooling/report/group_issues/issue_updater.rb
538
535
  - lib/gitlab_quality/test_tooling/report/health_problem_reporter.rb
539
536
  - lib/gitlab_quality/test_tooling/report/issue_logger.rb
540
- - lib/gitlab_quality/test_tooling/report/knapsack_report_issue.rb
541
537
  - lib/gitlab_quality/test_tooling/report/merge_request_slow_tests_report.rb
542
538
  - lib/gitlab_quality/test_tooling/report/prepare_stage_reports.rb
543
539
  - lib/gitlab_quality/test_tooling/report/relate_failure_issue.rb
@@ -1,54 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require "bundler/setup"
5
- require "optparse"
6
-
7
- require_relative "../lib/gitlab_quality/test_tooling"
8
-
9
- params = {}
10
-
11
- options = OptionParser.new do |opts|
12
- opts.banner = "Usage: #{$PROGRAM_NAME} [options]"
13
-
14
- opts.on("-i", "--input-file INPUT_FILE", String, "Knapsack actual run time report file path glob") do |input_file|
15
- params[:input_files] = input_file
16
- end
17
-
18
- opts.on("-e", "--expected-report EXPECTED_REPORT", String, "Knapsack expected report file path") do |report_path|
19
- params[:expected_report] = report_path.strip
20
- end
21
-
22
- opts.on('-p', '--project PROJECT', String, 'Can be an integer or a group/project string') do |project|
23
- params[:project] = project
24
- end
25
-
26
- opts.on('-t', '--token TOKEN', String, 'A valid access token with `api` scope and Maintainer permission in PROJECT') do |token|
27
- params[:token] = token
28
- end
29
-
30
- opts.on('--dry-run', "Perform a dry-run (don't create issues)") do
31
- params[:dry_run] = true
32
- end
33
-
34
- opts.on_tail('-v', '--version', 'Show the version') do
35
- require_relative "../lib/gitlab_quality/test_tooling/version"
36
- puts "#{$PROGRAM_NAME} : #{GitlabQuality::TestTooling::VERSION}"
37
- exit
38
- end
39
-
40
- opts.on_tail('-h', '--help', 'Show the usage') do
41
- puts "Purpose: Create spec run time issue when a spec file almost caused job timeout because it ran significantly longer than what Knapsack expected."
42
- puts opts
43
- exit
44
- end
45
-
46
- opts.parse(ARGV)
47
- end
48
-
49
- if params.any?
50
- GitlabQuality::TestTooling::Report::KnapsackReportIssue.new(**params).invoke!
51
- else
52
- puts options
53
- exit 1
54
- end
@@ -1,120 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module GitlabQuality
4
- module TestTooling
5
- module KnapsackReports
6
- class SpecRunTime
7
- attr_reader :file, :expected, :actual, :expected_suite_duration, :actual_suite_duration, :project, :ref
8
-
9
- ACTUAL_TO_EXPECTED_SPEC_RUN_TIME_RATIO_THRESHOLD = 1.5 # actual run time is longer than expected by 50% +
10
- SPEC_WEIGHT_PERCENTAGE_TRESHOLD = 15 # a spec file takes 15%+ of the total test suite run time
11
- SUITE_DURATION_THRESHOLD = 70 * 60 # if test suite takes more than 70 minutes, job risks timing out
12
- FEATURE_CATEGORY_METADATA_REGEX = /(?<=feature_category: :)(?<feature_category>\w+)/
13
-
14
- def initialize(
15
- file:,
16
- expected:,
17
- actual:,
18
- expected_suite_duration:,
19
- actual_suite_duration:,
20
- token: '',
21
- project: Runtime::Env.ci_project_path,
22
- ref: Runtime::Env.ci_commit_ref_name)
23
- @file = file
24
- @expected = expected.to_f
25
- @actual = actual.to_f
26
- @expected_suite_duration = expected_suite_duration.to_f
27
- @actual_suite_duration = actual_suite_duration.to_f
28
- @token = token
29
- @project = project
30
- @ref = ref
31
- end
32
-
33
- def feature_category
34
- file_lines.each do |line|
35
- match = FEATURE_CATEGORY_METADATA_REGEX.match(line)
36
- next unless match
37
-
38
- break match[:feature_category]
39
- end
40
- end
41
-
42
- def should_report?
43
- # guideline proposed in https://gitlab.com/gitlab-org/quality/engineering-productivity/team/-/issues/354
44
- exceed_actual_to_expected_ratio_threshold? && test_suite_bottleneck?
45
- end
46
-
47
- def ci_pipeline_url_markdown
48
- "[#{ci_pipeline_id}](#{ci_pipeline_url})"
49
- end
50
-
51
- def ci_pipeline_created_at
52
- ENV.fetch('CI_PIPELINE_CREATED_AT', nil)
53
- end
54
-
55
- def ci_job_link_markdown
56
- "[#{ci_job_name}](#{ci_job_url})"
57
- end
58
-
59
- def file_link_markdown
60
- "[#{file}](#{file_link})"
61
- end
62
-
63
- def actual_percentage
64
- (actual / actual_suite_duration * 100).round(2)
65
- end
66
-
67
- def name
68
- nil
69
- end
70
-
71
- private
72
-
73
- attr_reader :token
74
-
75
- def exceed_actual_to_expected_ratio_threshold?
76
- actual / expected >= ACTUAL_TO_EXPECTED_SPEC_RUN_TIME_RATIO_THRESHOLD
77
- end
78
-
79
- def test_suite_bottleneck?
80
- # now we only report bottlenecks when they risk causing job timeouts
81
- return unless actual_suite_duration > SUITE_DURATION_THRESHOLD
82
-
83
- actual_percentage > SPEC_WEIGHT_PERCENTAGE_TRESHOLD
84
- end
85
-
86
- def ci_job_url
87
- ENV.fetch('CI_JOB_URL', nil)
88
- end
89
-
90
- def ci_job_name
91
- ENV.fetch('CI_JOB_NAME_SLUG', nil)
92
- end
93
-
94
- def ci_pipeline_id
95
- ENV.fetch('CI_PIPELINE_IID', nil)
96
- end
97
-
98
- def ci_pipeline_url
99
- ENV.fetch('CI_PIPELINE_URL', nil)
100
- end
101
-
102
- def file_link
103
- "https://gitlab.com/#{project}/-/blob/#{Runtime::Env.ci_commit_ref_name}/#{file}"
104
- end
105
-
106
- def file_lines
107
- files_client.file_contents.lines(chomp: true)
108
- end
109
-
110
- def files_client
111
- @files_client ||= GitlabClient::RepositoryFilesClient.new(
112
- token: token,
113
- project: project,
114
- file_path: file,
115
- ref: ref)
116
- end
117
- end
118
- end
119
- end
120
- end
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'json'
4
-
5
- module GitlabQuality
6
- module TestTooling
7
- module KnapsackReports
8
- class SpecRunTimeReport
9
- attr_reader :project, :expected_report, :actual_report
10
-
11
- def initialize(project:, expected_report_path:, actual_report_path:, token: '')
12
- @project = project
13
- @expected_report = parse(expected_report_path)
14
- @actual_report = parse(actual_report_path)
15
- @token = token
16
- end
17
-
18
- def filtered_report
19
- @filtered_report = actual_report.keys.filter_map do |spec_file|
20
- expected_run_time = expected_report[spec_file]
21
- actual_run_time = actual_report[spec_file]
22
-
23
- if expected_run_time.nil?
24
- puts "#{spec_file} missing from the expected Knapsack report, skipping."
25
- next
26
- end
27
-
28
- spec_run_time = SpecRunTime.new(
29
- token: token,
30
- project: project,
31
- file: spec_file,
32
- expected: expected_run_time,
33
- actual: actual_run_time,
34
- expected_suite_duration: expected_test_suite_run_time_total,
35
- actual_suite_duration: actual_test_suite_run_time_total
36
- )
37
-
38
- spec_run_time if spec_run_time.should_report?
39
- end
40
- end
41
-
42
- private
43
-
44
- attr_reader :token
45
-
46
- def parse(report_path)
47
- JSON.parse(File.read(report_path))
48
- end
49
-
50
- def expected_test_suite_run_time_total
51
- @expected_test_suite_run_time_total ||=
52
- expected_report.reduce(0) do |total_run_time, (_spec_file, run_time)|
53
- total_run_time + run_time
54
- end
55
- end
56
-
57
- def actual_test_suite_run_time_total
58
- @actual_test_suite_run_time_total ||=
59
- actual_report.reduce(0) do |total_run_time, (_spec_file, run_time)|
60
- total_run_time + run_time
61
- end
62
- end
63
- end
64
- end
65
- end
66
- end
@@ -1,150 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module GitlabQuality
4
- module TestTooling
5
- module Report
6
- # Uses the API to create GitLab issues for spec run time exceeding Knapsack expectation
7
- #
8
- # - Takes the expected and actual Knapsack JSON reports from the knapsack output
9
- # - Takes a project where issues should be created
10
- # - For every test file reported with unexpectedly long run time:
11
- # - Find issue by test file name, and if found:
12
- # - Reopen issue if it already exists, but is closed
13
- # - Update the issue with the new run time data
14
- # - If not found:
15
- # - Create a new issue with the run time data
16
- class KnapsackReportIssue < ReportAsIssue
17
- include Concerns::GroupAndCategoryLabels
18
-
19
- NEW_ISSUE_LABELS = Set.new([
20
- 'test', 'automation:bot-authored', 'type::maintenance', 'maintenance::performance',
21
- 'priority::3', 'severity::3', 'knapsack_report', 'suppress-contributor-links'
22
- ]).freeze
23
- SEARCH_LABELS = %w[test maintenance::performance knapsack_report].freeze
24
- JOB_TIMEOUT_EPIC_URL = 'https://gitlab.com/groups/gitlab-org/quality/engineering-productivity/-/epics/19'
25
-
26
- def initialize(token:, input_files:, expected_report:, project: nil, dry_run: false)
27
- super
28
-
29
- @expected_report = expected_report
30
- end
31
-
32
- private
33
-
34
- attr_reader :expected_report
35
-
36
- def run!
37
- puts "Reporting spec file exceeding Knapsack expectaton issues in project `#{project}` via the API at `#{Runtime::Env.gitlab_api_base}`."
38
-
39
- search_and_create_issue
40
- end
41
-
42
- def new_issue_labels(test)
43
- up_to_date_labels(test: test, new_labels: NEW_ISSUE_LABELS + group_and_category_labels_for_test(test))
44
- end
45
-
46
- def search_and_create_issue
47
- filtered_report = KnapsackReports::SpecRunTimeReport.new(
48
- token: token,
49
- project: project,
50
- expected_report_path: expected_report_path,
51
- actual_report_path: actual_report_path
52
- ).filtered_report
53
-
54
- puts "=> Reporting #{filtered_report.count} spec files exceeding Knapsack expectation."
55
-
56
- filtered_report.each do |spec_with_run_time|
57
- existing_issues = find_issues_for_test(spec_with_run_time, labels: SEARCH_LABELS)
58
-
59
- if existing_issues.empty?
60
- puts "Creating issue for #{spec_with_run_time.file}"
61
- create_issue(spec_with_run_time)
62
- else
63
- update_issue(issue: existing_issues.last, spec_run_time: spec_with_run_time)
64
- end
65
- end
66
- end
67
-
68
- def expected_report_path
69
- return if expected_report.nil? || !File.exist?(expected_report)
70
-
71
- expected_report
72
- end
73
-
74
- def actual_report_path
75
- return if files.nil? || !File.exist?(files.first)
76
-
77
- files.first
78
- end
79
-
80
- def new_issue_title(spec_run_time)
81
- "Job timeout risk: #{spec_run_time.file} ran much longer than expected"
82
- end
83
-
84
- def new_issue_description(spec_run_time)
85
- <<~MARKDOWN.chomp
86
- /epic #{JOB_TIMEOUT_EPIC_URL}
87
-
88
- ### Why was this issue created?
89
-
90
- #{spec_run_time.file_link_markdown} was reported to have:
91
-
92
- 1. exceeded Knapsack's expected runtime by at least 50%, and
93
- 2. been identified as a notable pipeline bottleneck and a job timeout risk
94
-
95
- ### Suggested steps for investigation
96
-
97
- 1. To reproduce in CI by running test files in the same order, you can follow the steps listed [here](https://docs.gitlab.com/ee/development/testing_guide/flaky_tests.html#recreate-job-failure-in-ci-by-forcing-the-job-to-run-the-same-set-of-test-files).
98
- 1. Identify if a specific test case is stalling the run time. Hint: You can search the job's log for `Starting example group #{spec_run_time.file}` and view the elapsed time after each test case in the proceeding lines starting with `[RSpecRunTime]`.
99
- 1. If the test file is large, consider refactoring it into multiple files to allow better test parallelization across runners.
100
- 1. If the run time cannot be fixed in time, consider quarantine the spec(s) to restore performance.
101
-
102
- ### Run time details
103
-
104
- #{run_time_detail(spec_run_time)}
105
- MARKDOWN
106
- end
107
-
108
- def update_issue(issue:, spec_run_time:)
109
- updated_description = <<~MARKDOWN.chomp
110
- #{issue.description}
111
-
112
- #{run_time_detail(spec_run_time)}
113
- MARKDOWN
114
-
115
- issue_attrs = {
116
- description: updated_description
117
- }
118
-
119
- # We reopen closed issues to not lose any history
120
- state_event = issue.state == 'closed' ? 'reopen' : nil
121
- issue_attrs[:state_event] = state_event if state_event
122
-
123
- gitlab.edit_issue(iid: issue.iid, options: issue_attrs)
124
- puts " => Added a report in #{issue.web_url}!"
125
- end
126
-
127
- def run_time_detail(spec_run_time)
128
- <<~MARKDOWN.chomp
129
- - Reported from pipeline #{spec_run_time.ci_pipeline_url_markdown} created at `#{spec_run_time.ci_pipeline_created_at}`
130
-
131
- | Field | Value |
132
- | ------ | ------ |
133
- | Job URL| #{spec_run_time.ci_job_link_markdown} |
134
- | Job total RSpec suite run time | expected: `#{readable_duration(spec_run_time.expected_suite_duration)}`, actual: `#{readable_duration(spec_run_time.actual_suite_duration)}` |
135
- | Spec file run time | expected: `#{readable_duration(spec_run_time.expected)}`, actual: `#{readable_duration(spec_run_time.actual)}` |
136
- | Spec file weight | `#{spec_run_time.actual_percentage}%` of total suite run time |
137
- MARKDOWN
138
- end
139
-
140
- def assert_input_files!(_files)
141
- missing_expected_report_msg = "Missing a valid expected Knapsack report."
142
- missing_actual_report_msg = "Missing a valid actual Knapsack report."
143
-
144
- abort missing_expected_report_msg if expected_report_path.nil?
145
- abort missing_actual_report_msg if actual_report_path.nil?
146
- end
147
- end
148
- end
149
- end
150
- end