gitlab_quality-test_tooling 1.3.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
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