gitlab_quality-test_tooling 1.3.0 → 1.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8faeb526c0c3996945e423ca2c2d944f57bda93b1941beac376e9d4478bf8230
4
- data.tar.gz: '09a401ff0c2c60effc2a9c55466ed266dceb7eed8b3c83aa1970c31837ec36dd'
3
+ metadata.gz: 7ac9e211aa370a7163c4173c7a1dec921cbf237fc406d28e1c3c5cfe296e9750
4
+ data.tar.gz: 99a599cdb8f65c74a489210004f9b34918f03c0d3eb54cd47e3e2dc5a1ee01a1
5
5
  SHA512:
6
- metadata.gz: e7ba58f29fb1d459a82e5bc078791ecd08b5e06737530b09f52facd3813e1f7de699b7227748e58a788ef16099c3a9e6aef8a97607a5b0ccb0adc7bc96a59ab0
7
- data.tar.gz: 88f89b94c695450d2f0716e4927e11865dd5e9c3d356f1f6c106ece8ff86ab5797db88459dd7285acf8ee0b7b37952c829bc681ee1b5678f42f35643cc51aeb9
6
+ metadata.gz: '009549cacd5c20ec47ecc157801f272e00a4681decfa5fbf5ae62e252127f8482313857ad328cda1a68327ae7047c771ec7f6d39cfb0fa835834f9b1a53b519a'
7
+ data.tar.gz: 4bc8d5f83edf2c193ff2fadbc4ae525210a9d9c817dfc48ce35bfa9efcabdecd7801e59165e761a10c2a46d382bc276e1567d45e3ba64905649ce8abab530703
data/Gemfile.lock CHANGED
@@ -1,8 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab_quality-test_tooling (1.3.0)
4
+ gitlab_quality-test_tooling (1.5.0)
5
5
  activesupport (>= 6.1, < 7.2)
6
+ amatch (~> 0.4.1)
6
7
  gitlab (~> 4.19)
7
8
  http (~> 5.0)
8
9
  nokogiri (~> 1.10)
@@ -22,6 +23,9 @@ GEM
22
23
  zeitwerk (~> 2.3)
23
24
  addressable (2.8.4)
24
25
  public_suffix (>= 2.0.2, < 6.0)
26
+ amatch (0.4.1)
27
+ mize
28
+ tins (~> 1.0)
25
29
  ast (2.4.2)
26
30
  backport (1.2.0)
27
31
  benchmark (0.2.1)
@@ -132,6 +136,8 @@ GEM
132
136
  mini_mime (1.1.2)
133
137
  mini_portile2 (2.8.1)
134
138
  minitest (5.18.0)
139
+ mize (0.4.1)
140
+ protocol (~> 2.0)
135
141
  multi_xml (0.6.0)
136
142
  nap (1.1.0)
137
143
  nenv (0.3.0)
@@ -149,6 +155,8 @@ GEM
149
155
  parallel (1.23.0)
150
156
  parser (3.2.2.1)
151
157
  ast (~> 2.4.1)
158
+ protocol (2.0.0)
159
+ ruby_parser (~> 3.0)
152
160
  pry (0.14.2)
153
161
  coderay (~> 1.1)
154
162
  method_source (~> 1.0)
@@ -207,9 +215,12 @@ GEM
207
215
  rubocop-capybara (~> 2.17)
208
216
  ruby-progressbar (1.13.0)
209
217
  ruby2_keywords (0.0.5)
218
+ ruby_parser (3.20.3)
219
+ sexp_processor (~> 4.16)
210
220
  sawyer (0.9.2)
211
221
  addressable (>= 2.3.5)
212
222
  faraday (>= 0.17.3, < 3)
223
+ sexp_processor (4.17.0)
213
224
  shellany (0.0.1)
214
225
  simplecov (0.22.0)
215
226
  docile (~> 1.1)
@@ -236,12 +247,15 @@ GEM
236
247
  thor (~> 1.0)
237
248
  tilt (~> 2.0)
238
249
  yard (~> 0.9, >= 0.9.24)
250
+ sync (0.5.0)
239
251
  table_print (1.5.7)
240
252
  terminal-table (3.0.2)
241
253
  unicode-display_width (>= 1.1.1, < 3)
242
254
  thor (1.2.1)
243
255
  tilt (2.1.0)
244
256
  timecop (0.9.6)
257
+ tins (1.32.1)
258
+ sync
245
259
  tzinfo (2.0.6)
246
260
  concurrent-ruby (~> 1.0)
247
261
  unf (0.1.4)
data/README.md CHANGED
@@ -26,7 +26,7 @@ $ gem install gitlab_quality-test_tooling
26
26
 
27
27
  The gem provides the following executables.
28
28
 
29
- ### `generate-test-session`
29
+ ### `exe/generate-test-session`
30
30
 
31
31
  ```shell
32
32
  Purpose: Generate test session report based on RSpec report files (JSON or JUnit XML)
@@ -38,15 +38,15 @@ Usage: exe/generate-test-session [options]
38
38
  --ci-project-token
39
39
  -f ISSUE_URL_FILE, Output the created test session issue URL
40
40
  --issue-url-file
41
+ --confidential Makes test session issue confidential
41
42
  --dry-run Perform a dry-run (don't create or update issues or test cases)
42
43
  -v, --version Show the version
43
44
  -h, --help Show the usage
44
45
  ```
45
46
 
46
- ### `post-to-slack`
47
+ ### `exe/post-to-slack`
47
48
 
48
49
  ```shell
49
- $ exe/post-to-slack -h
50
50
  Purpose: Post a message to Slack, and optionally add a test summary table based on RSpec report files (JUnit XML)
51
51
  Usage: exe/post-to-slack [options]
52
52
  -w SLACK_WEBHOOK_URL, Slack webhook URL
@@ -61,10 +61,9 @@ Usage: exe/post-to-slack [options]
61
61
  -h, --help Show the usage
62
62
  ```
63
63
 
64
- ### `prepare-stage-reports`
64
+ ### `exe/prepare-stage-reports`
65
65
 
66
66
  ```shell
67
- $ exe/prepare-stage-reports -h
68
67
  Purpose: Prepare separate reports for each DevOps stage from the provided RSpec report files (JUnit XML)
69
68
  Usage: exe/prepare-stage-reports [options]
70
69
  -i, --input-files INPUT_FILES RSpec report files (JUnit XML)
@@ -72,10 +71,9 @@ Usage: exe/prepare-stage-reports [options]
72
71
  -h, --help Show the usage
73
72
  ```
74
73
 
75
- ### `relate-failure-issue`
74
+ ### `exe/relate-failure-issue`
76
75
 
77
76
  ```shell
78
- $ exe/relate-failure-issue -h
79
77
  Purpose: Relate test failures to failure issues from RSpec report files (JSON or JUnit XML)
80
78
  Usage: exe/relate-failure-issue [options]
81
79
  -i, --input-files INPUT_FILES RSpec report files (JSON or JUnit XML)
@@ -93,10 +91,9 @@ Usage: exe/relate-failure-issue [options]
93
91
  -h, --help Show the usage
94
92
  ```
95
93
 
96
- ### `report-results`
94
+ ### `exe/report-results`
97
95
 
98
96
  ```shell
99
- $ exe/report-results -h
100
97
  Purpose: Report test results from RSpec report files (JSON or JUnit XML) in GitLab test cases and result issues
101
98
  Usage: exe/report-results [options]
102
99
  -i, --input-files INPUT_FILES RSpec report files (JSON or JUnit XML)
@@ -113,10 +110,9 @@ Usage: exe/report-results [options]
113
110
  -h, --help Show the usage
114
111
  ```
115
112
 
116
- ### `update-screenshot-paths`
113
+ ### `exe/update-screenshot-paths`
117
114
 
118
115
  ```shell
119
- $ exe/update-screenshot-paths -h
120
116
  Purpose: Update the path to screenshots to container's host from RSpec report files (JSON or JUnit XML)
121
117
  Usage: exe/update-screenshot-paths [options]
122
118
  -i, --input-files INPUT_FILES RSpec report files (JSON or JUnit XML)
@@ -124,7 +120,7 @@ Usage: exe/update-screenshot-paths [options]
124
120
  -h, --help Show the usage
125
121
  ```
126
122
 
127
- ### `slow-test-issues`
123
+ ### `exe/slow-test-issues`
128
124
 
129
125
  ```shell
130
126
  Purpose: Create slow test issues from JSON RSpec report files
@@ -137,10 +133,9 @@ Usage: exe/slow-test-issue [options]
137
133
  -h, --help Show the usage
138
134
  ```
139
135
 
140
- ### `slow-test-merge-request-report-note`
136
+ ### `exe/slow-test-merge-request-report-note`
141
137
 
142
138
  ```shell
143
- $ exe/slow-test-merge-request-report-note -h
144
139
  Purpose: Create slow test note on merge requests from JSON RSpec report files
145
140
  Usage: exe/slow-test-merge-request-report-note [options]
146
141
  -i, --input-files INPUT_FILES JSON RSpec report files JSON
@@ -31,6 +31,10 @@ options = OptionParser.new do |opts|
31
31
  params[:issue_url_file] = issue_url_file
32
32
  end
33
33
 
34
+ opts.on('--confidential', "Makes test session issue confidential") do
35
+ params[:confidential] = true
36
+ end
37
+
34
38
  opts.on('--dry-run', "Perform a dry-run (don't create or update issues or test cases)") do
35
39
  params[:dry_run] = true
36
40
  end
@@ -27,6 +27,10 @@ options = OptionParser.new do |opts|
27
27
  params[:token] = token
28
28
  end
29
29
 
30
+ opts.on('-r', '--related-issues-file RELATED_ISSUES_FILE', String, 'The file path for the related issues') do |related_issues_file|
31
+ params[:related_issues_file] = related_issues_file
32
+ end
33
+
30
34
  opts.on('--system-log-files SYSTEM_LOG_FILES', String,
31
35
  'Include errors from system logs in failure issues') do |system_log_files|
32
36
  params[:system_logs] = system_log_files
data/exe/slow-test-issues CHANGED
@@ -23,6 +23,10 @@ options = OptionParser.new do |opts|
23
23
  params[:token] = token
24
24
  end
25
25
 
26
+ opts.on('-r', '--related-issues-file RELATED_ISSUES_FILE', String, 'The file path for the related issues') do |related_issues_file|
27
+ params[:related_issues_file] = related_issues_file
28
+ end
29
+
26
30
  opts.on('--dry-run', "Perform a dry-run (don't create issues)") do
27
31
  params[:dry_run] = true
28
32
  end
@@ -3,8 +3,8 @@
3
3
  module GitlabQuality
4
4
  module TestTooling
5
5
  class GitlabIssueDryClient < GitlabIssueClient
6
- def create_issue(title:, description:, labels:, issue_type: 'issue')
7
- attrs = { description: description, labels: labels }
6
+ def create_issue(title:, description:, labels:, issue_type: 'issue', confidential: false)
7
+ attrs = { description: description, labels: labels, confidential: confidential }
8
8
 
9
9
  puts "The following #{issue_type} would have been created:"
10
10
  puts "project: #{project}, title: #{title}, attrs: #{attrs}"
@@ -20,7 +20,10 @@ module GitlabQuality
20
20
  end
21
21
 
22
22
  def partial_file_path(path)
23
- path.match(%r{((?:spec|ee|api|browser_ui)/.*)}i)[1]
23
+ matched = path&.match(%r{(?<partial_path>(?:spec|ee|api|browser_ui)/.*)}i)
24
+ return matched[:partial_path] if matched
25
+
26
+ path
24
27
  end
25
28
 
26
29
  def search_safe(value)
@@ -30,7 +30,8 @@ module GitlabQuality
30
30
  issue = gitlab.create_issue(
31
31
  title: "#{Time.now.strftime('%Y-%m-%d')} Test session report | #{Runtime::Env.qa_run_type}",
32
32
  description: generate_description(tests),
33
- labels: ['Quality', 'QA', 'triage report', pipeline_name_label]
33
+ labels: ['Quality', 'QA', 'triage report', pipeline_name_label],
34
+ confidential: confidential
34
35
  )
35
36
 
36
37
  # Workaround for https://gitlab.com/gitlab-org/gitlab/-/issues/295493
@@ -137,6 +138,8 @@ module GitlabQuality
137
138
  growth
138
139
  fulfillment
139
140
  enablement
141
+ self-managed
142
+ saas
140
143
  ]
141
144
 
142
145
  tests.sort_by do |test|
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GitlabQuality
4
+ module TestTooling
5
+ module Report
6
+ class IssueLogger
7
+ def initialize(file_path:)
8
+ @file_path = file_path
9
+ @data = File.exist?(file_path) ? JSON.parse(File.read(file_path)) : Hash.new { |h, k| h[k] = [] }
10
+ end
11
+
12
+ def collect(test, issues)
13
+ data[test.ci_job_url] += Array(issues).map(&:web_url)
14
+ data[test.ci_job_url].uniq!
15
+ end
16
+
17
+ def write
18
+ dirname = File.dirname(file_path)
19
+
20
+ FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
21
+
22
+ File.write(file_path, JSON.pretty_generate(data))
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :file_path, :data
28
+ end
29
+ end
30
+ end
31
+ end
@@ -4,6 +4,7 @@ require 'nokogiri'
4
4
  require 'active_support/core_ext/enumerable'
5
5
  require 'rubygems/text'
6
6
  require 'active_support/core_ext/integer/time'
7
+ require 'amatch'
7
8
 
8
9
  module GitlabQuality
9
10
  module TestTooling
@@ -17,6 +18,7 @@ module GitlabQuality
17
18
  class RelateFailureIssue < ReportAsIssue
18
19
  include Concerns::FindSetDri
19
20
  include Concerns::GroupAndCategoryLabels
21
+ include Amatch
20
22
 
21
23
  DEFAULT_MAX_DIFF_RATIO_FOR_DETECTION = 0.15
22
24
  SYSTEMIC_EXCEPTIONS_THRESHOLD = 10
@@ -53,15 +55,20 @@ module GitlabQuality
53
55
 
54
56
  TestResults::Builder.new(files).test_results_per_file do |test_results|
55
57
  puts "=> Reporting #{test_results.count} tests in #{test_results.path}"
58
+ process_test_results(test_results)
59
+ end
56
60
 
57
- systemic_failures = systemic_failures_for_test_results(test_results)
61
+ write_issues_log_file
62
+ end
58
63
 
59
- test_results.each do |test|
60
- relate_failure_to_issue(test) if should_report?(test, systemic_failures)
61
- end
64
+ def process_test_results(test_results)
65
+ systemic_failures = systemic_failures_for_test_results(test_results)
62
66
 
63
- test_results.write
67
+ test_results.each do |test|
68
+ collect_issues(test, relate_failure_to_issue(test)) if should_report?(test, systemic_failures)
64
69
  end
70
+
71
+ test_results.write
65
72
  end
66
73
 
67
74
  def systemic_failures_for_test_results(test_results)
@@ -177,9 +184,12 @@ module GitlabQuality
177
184
 
178
185
  def full_stacktrace(test)
179
186
  test.failures.each do |failure|
180
- next if IGNORED_FAILURES.any? { |e| failure['message'].include?(e) }
187
+ message = failure['message'] || ""
188
+ message_lines = failure['message_lines'] || []
189
+
190
+ next if IGNORED_FAILURES.any? { |e| message.include?(e) }
181
191
 
182
- return failure['message_lines'].empty? ? failure['message'] : failure['message_lines'].join("\n")
192
+ return message_lines.empty? ? message : message_lines.join("\n")
183
193
  end
184
194
  end
185
195
 
@@ -201,8 +211,7 @@ module GitlabQuality
201
211
  end
202
212
 
203
213
  def calculate_diff_ratio(stack_trace_first, stack_trace_second)
204
- ld = Class.new.extend(Gem::Text).method(:levenshtein_distance)
205
- distance = ld.call(stack_trace_first, stack_trace_second)
214
+ distance = Levenshtein.new(stack_trace_first).match(stack_trace_second)
206
215
  distance.zero? ? 0.0 : (distance.to_f / stack_trace_first.size).round(3)
207
216
  end
208
217
 
@@ -8,11 +8,12 @@ module GitlabQuality
8
8
  class ReportAsIssue
9
9
  include Concerns::Utils
10
10
 
11
- def initialize(token:, input_files:, project: nil, confidential: false, dry_run: false, **_kwargs)
11
+ def initialize(token:, input_files:, related_issues_file: nil, project: nil, confidential: false, dry_run: false, **_kwargs)
12
12
  @project = project
13
13
  @gitlab = (dry_run ? GitlabIssueDryClient : GitlabIssueClient).new(token: token, project: project)
14
14
  @files = Array(input_files)
15
15
  @confidential = confidential
16
+ @issue_logger = IssueLogger.new(file_path: related_issues_file) if related_issues_file.present?
16
17
  end
17
18
 
18
19
  def invoke!
@@ -23,14 +24,22 @@ module GitlabQuality
23
24
 
24
25
  private
25
26
 
26
- attr_reader :gitlab, :files, :project, :issue_type, :confidential
27
+ attr_reader :gitlab, :files, :project, :issue_type, :confidential, :issue_logger
27
28
 
28
29
  def run!
29
30
  raise NotImplementedError
30
31
  end
31
32
 
33
+ def collect_issues(test, issues)
34
+ issue_logger.collect(test, issues) if issue_logger.present?
35
+ end
36
+
37
+ def write_issues_log_file
38
+ issue_logger.write if issue_logger.present?
39
+ end
40
+
32
41
  def test_hash(test)
33
- OpenSSL::Digest::SHA256.hexdigest(test.file + test.name)
42
+ OpenSSL::Digest.hexdigest('SHA256', "#{test.file}#{test.name}")
34
43
  end
35
44
 
36
45
  def new_issue_description(test)
@@ -131,7 +140,8 @@ module GitlabQuality
131
140
 
132
141
  gitlab.find_issues(options: search_options).find_all do |issue|
133
142
  issue_title = issue.title.strip
134
- issue_title.include?(test.name) || issue_title.include?(partial_file_path(test.file))
143
+ test_file_path_found = !test.file.to_s.empty? && issue_title.include?(partial_file_path(test.file))
144
+ issue_title.include?(test.name) || test_file_path_found
135
145
  end
136
146
  end
137
147
 
@@ -30,6 +30,8 @@ module GitlabQuality
30
30
  create_slow_issue(test) if test.slow_test?
31
31
  end
32
32
  end
33
+
34
+ write_issues_log_file
33
35
  end
34
36
 
35
37
  def new_issue_title(test)
@@ -51,11 +53,15 @@ module GitlabQuality
51
53
 
52
54
  issues = find_issues(test, SEARCH_LABELS, state: 'opened')
53
55
 
54
- issues.each do |issue|
55
- puts " => Existing issue link #{issue['web_url']}"
56
+ if issues.blank?
57
+ issues << create_issue(test)
58
+ else
59
+ issues.each do |issue|
60
+ puts " => Existing issue link #{issue['web_url']}"
61
+ end
56
62
  end
57
63
 
58
- create_issue(test) unless issues.any?
64
+ collect_issues(test, issues)
59
65
  rescue MultipleIssuesFound => e
60
66
  warn(e.message)
61
67
  end
@@ -50,7 +50,7 @@ module GitlabQuality
50
50
  end
51
51
 
52
52
  def pipeline_from_project_name
53
- ci_project_name.to_s.start_with?('gitlab') ? default_branch : ci_project_name
53
+ %w[gitlab gitaly].any? { |str| ci_project_name.to_s.start_with?(str) } ? default_branch : ci_project_name
54
54
  end
55
55
 
56
56
  def run_id
@@ -88,6 +88,10 @@ module GitlabQuality
88
88
  "#{ci_project_name}-#{test_subset}"
89
89
  end
90
90
 
91
+ def file_base_url
92
+ env_var_value_if_defined('FILE_BASE_URL') || "https://gitlab.com/gitlab-org/gitlab/-/blob/master/"
93
+ end
94
+
91
95
  private
92
96
 
93
97
  def enabled?(value, default: true)
@@ -11,7 +11,7 @@ module GitlabQuality
11
11
  end
12
12
 
13
13
  def stage
14
- @stage ||= file[%r{(?:api|browser_ui)/(?:(?:\d+_)?(\w+))}, 1]
14
+ @stage ||= file[%r{(?:api|browser_ui)/(?:(?:\d+_)?(\w+))}, 1] || category
15
15
  end
16
16
 
17
17
  def name
@@ -22,6 +22,10 @@ module GitlabQuality
22
22
  raise NotImplementedError
23
23
  end
24
24
 
25
+ def category
26
+ raise NotImplementedError
27
+ end
28
+
25
29
  def skipped?
26
30
  raise NotImplementedError
27
31
  end
@@ -29,6 +33,10 @@ module GitlabQuality
29
33
  def failures
30
34
  raise NotImplementedError
31
35
  end
36
+
37
+ def failures?
38
+ failures.any?
39
+ end
32
40
  end
33
41
  end
34
42
  end
@@ -11,7 +11,7 @@ module GitlabQuality
11
11
  end
12
12
 
13
13
  def file
14
- report['file'].delete_prefix('./')
14
+ report['file']&.delete_prefix('./')
15
15
  end
16
16
 
17
17
  def skipped?
@@ -25,17 +25,85 @@ module GitlabQuality
25
25
  failures.map do |exception|
26
26
  trace = exception.content.split("\n").map(&:strip)
27
27
  spec_file_first_index = trace.rindex do |line|
28
- line.include?(File.basename(report['file']))
28
+ report['file'] && line.include?(File.basename(report['file']))
29
29
  end
30
30
 
31
31
  exception['message'].gsub!(/(private_token=)[\w-]+/, '********')
32
-
32
+ exception.content = exception.content.gsub(/(private_token=)[\w-]+/, '********')
33
33
  {
34
34
  'message' => "#{exception['type']}: #{exception['message']}",
35
- 'stacktrace' => trace.slice(0..spec_file_first_index).join("\n")
35
+ 'stacktrace' => trace.slice(0..spec_file_first_index).join("\n"),
36
+ 'message_lines' => trace.slice(0..spec_file_first_index)
36
37
  }
37
38
  end
38
39
  end
40
+
41
+ def quarantine
42
+ !report['quarantine'].nil?
43
+ end
44
+
45
+ def quarantine?
46
+ # The value for 'quarantine' could be nil, a hash, a string,
47
+ # or true (if the test just has the :quarantine tag)
48
+ # But any non-nil or false value should means the test is in quarantine
49
+ !!quarantine
50
+ end
51
+
52
+ def line_number
53
+ report['line_number']
54
+ end
55
+
56
+ def level
57
+ report['level']
58
+ end
59
+
60
+ def run_time
61
+ report['run_time'].to_f.round(2)
62
+ end
63
+
64
+ def screenshot
65
+ report['screenshot']
66
+ end
67
+
68
+ def screenshot?
69
+ !!screenshot
70
+ end
71
+
72
+ def max_duration_for_test
73
+ ""
74
+ end
75
+
76
+ def ci_job_url
77
+ ENV.fetch('CI_JOB_URL', '')
78
+ end
79
+
80
+ def product_group
81
+ report['product_group'].to_s
82
+ end
83
+
84
+ def product_group?
85
+ product_group != ''
86
+ end
87
+
88
+ def feature_category
89
+ report['feature_category']
90
+ end
91
+
92
+ def failure_issue
93
+ report['failure_issue']
94
+ end
95
+
96
+ def failure_issue=(new_failure_issue)
97
+ report['failure_issue'] = new_failure_issue
98
+ end
99
+
100
+ def test_file_link
101
+ return "" if file.nil?
102
+
103
+ path_prefix = file.start_with?('qa/') ? 'qa/' : ''
104
+
105
+ "[`#{path_prefix}#{file}#L#{line_number}`](#{Runtime::Env.file_base_url}#{path_prefix}#{file}#L#{line_number})"
106
+ end
39
107
  end
40
108
  end
41
109
  end
@@ -4,8 +4,6 @@ module GitlabQuality
4
4
  module TestTooling
5
5
  module TestResult
6
6
  class JsonTestResult < BaseTestResult
7
- FILE_BASE_URL = "https://gitlab.com/gitlab-org/gitlab/-/blob/master/"
8
-
9
7
  PRIVATE_TOKEN_REGEX = /(private_token=)[\w-]+/
10
8
 
11
9
  OTHER_TESTS_MAX_DURATION = 45.40 # seconds
@@ -90,6 +88,10 @@ module GitlabQuality
90
88
  report['feature_category']
91
89
  end
92
90
 
91
+ def category
92
+ report['category']
93
+ end
94
+
93
95
  def run_time
94
96
  report['run_time'].to_f.round(2)
95
97
  end
@@ -132,10 +134,6 @@ module GitlabQuality
132
134
  end
133
135
  end
134
136
 
135
- def failures?
136
- failures.any?
137
- end
138
-
139
137
  def allowed_to_be_slow?
140
138
  !!report['allowed_to_be_slow']
141
139
  end
@@ -156,7 +154,7 @@ module GitlabQuality
156
154
  def test_file_link
157
155
  path_prefix = file.start_with?('qa/') ? 'qa/' : ''
158
156
 
159
- "[`#{path_prefix}#{file}#L#{line_number}`](#{FILE_BASE_URL}#{path_prefix}#{file}#L#{line_number})"
157
+ "[`#{path_prefix}#{file}#L#{line_number}`](#{Runtime::Env.file_base_url}#{path_prefix}#{file}#L#{line_number})"
160
158
  end
161
159
 
162
160
  private
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GitlabQuality
4
4
  module TestTooling
5
- VERSION = "1.3.0"
5
+ VERSION = "1.5.0"
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: 1.3.0
4
+ version: 1.5.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: 2023-10-09 00:00:00.000000000 Z
11
+ date: 2023-11-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control
@@ -198,6 +198,20 @@ dependencies:
198
198
  - - "<"
199
199
  - !ruby/object:Gem::Version
200
200
  version: '7.2'
201
+ - !ruby/object:Gem::Dependency
202
+ name: amatch
203
+ requirement: !ruby/object:Gem::Requirement
204
+ requirements:
205
+ - - "~>"
206
+ - !ruby/object:Gem::Version
207
+ version: 0.4.1
208
+ type: :runtime
209
+ prerelease: false
210
+ version_requirements: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - "~>"
213
+ - !ruby/object:Gem::Version
214
+ version: 0.4.1
201
215
  - !ruby/object:Gem::Dependency
202
216
  name: gitlab
203
217
  requirement: !ruby/object:Gem::Requirement
@@ -363,6 +377,7 @@ files:
363
377
  - lib/gitlab_quality/test_tooling/report/concerns/results_reporter.rb
364
378
  - lib/gitlab_quality/test_tooling/report/concerns/utils.rb
365
379
  - lib/gitlab_quality/test_tooling/report/generate_test_session.rb
380
+ - lib/gitlab_quality/test_tooling/report/issue_logger.rb
366
381
  - lib/gitlab_quality/test_tooling/report/merge_request_slow_tests_report.rb
367
382
  - lib/gitlab_quality/test_tooling/report/prepare_stage_reports.rb
368
383
  - lib/gitlab_quality/test_tooling/report/relate_failure_issue.rb