gitlab_quality-test_tooling 1.3.0 → 1.4.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: 7237e27f052e0d9934df2a8ad8d8d413cb1db81b4bc30fd334458cd05ee23494
4
+ data.tar.gz: 1775470edd1236836c8f4a2f729d40d642d6e9fde2c40630b79925f84c821e8c
5
5
  SHA512:
6
- metadata.gz: e7ba58f29fb1d459a82e5bc078791ecd08b5e06737530b09f52facd3813e1f7de699b7227748e58a788ef16099c3a9e6aef8a97607a5b0ccb0adc7bc96a59ab0
7
- data.tar.gz: 88f89b94c695450d2f0716e4927e11865dd5e9c3d356f1f6c106ece8ff86ab5797db88459dd7285acf8ee0b7b37952c829bc681ee1b5678f42f35643cc51aeb9
6
+ metadata.gz: 0d77a24b7561c7d1b194a68290d0334d46e2c10120b3457f0288b53f161421bedccb6ff6c638e519d1a8c788e300b4b7ba543b7b5c45ad59b314ec05867e1be4
7
+ data.tar.gz: c384fda5b0c98647804c19880d581c0ccdf233dccd82c52b0f1aaf83fd56c729b3fdd33628433b9b278f48073a0e446ced610c5ee04408717dfbe919e9d3e77b
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.4.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
@@ -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
@@ -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
@@ -177,9 +179,12 @@ module GitlabQuality
177
179
 
178
180
  def full_stacktrace(test)
179
181
  test.failures.each do |failure|
180
- next if IGNORED_FAILURES.any? { |e| failure['message'].include?(e) }
182
+ message = failure['message'] || ""
183
+ message_lines = failure['message_lines'] || []
181
184
 
182
- return failure['message_lines'].empty? ? failure['message'] : failure['message_lines'].join("\n")
185
+ next if IGNORED_FAILURES.any? { |e| message.include?(e) }
186
+
187
+ return message_lines.empty? ? message : message_lines.join("\n")
183
188
  end
184
189
  end
185
190
 
@@ -201,8 +206,7 @@ module GitlabQuality
201
206
  end
202
207
 
203
208
  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)
209
+ distance = Levenshtein.new(stack_trace_first).match(stack_trace_second)
206
210
  distance.zero? ? 0.0 : (distance.to_f / stack_trace_first.size).round(3)
207
211
  end
208
212
 
@@ -30,7 +30,7 @@ module GitlabQuality
30
30
  end
31
31
 
32
32
  def test_hash(test)
33
- OpenSSL::Digest::SHA256.hexdigest(test.file + test.name)
33
+ OpenSSL::Digest.hexdigest('SHA256', "#{test.file}#{test.name}")
34
34
  end
35
35
 
36
36
  def new_issue_description(test)
@@ -131,7 +131,8 @@ module GitlabQuality
131
131
 
132
132
  gitlab.find_issues(options: search_options).find_all do |issue|
133
133
  issue_title = issue.title.strip
134
- issue_title.include?(test.name) || issue_title.include?(partial_file_path(test.file))
134
+ test_file_path_found = !test.file.to_s.empty? && issue_title.include?(partial_file_path(test.file))
135
+ issue_title.include?(test.name) || test_file_path_found
135
136
  end
136
137
  end
137
138
 
@@ -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)
@@ -29,6 +29,10 @@ module GitlabQuality
29
29
  def failures
30
30
  raise NotImplementedError
31
31
  end
32
+
33
+ def failures?
34
+ failures.any?
35
+ end
32
36
  end
33
37
  end
34
38
  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
@@ -132,10 +130,6 @@ module GitlabQuality
132
130
  end
133
131
  end
134
132
 
135
- def failures?
136
- failures.any?
137
- end
138
-
139
133
  def allowed_to_be_slow?
140
134
  !!report['allowed_to_be_slow']
141
135
  end
@@ -156,7 +150,7 @@ module GitlabQuality
156
150
  def test_file_link
157
151
  path_prefix = file.start_with?('qa/') ? 'qa/' : ''
158
152
 
159
- "[`#{path_prefix}#{file}#L#{line_number}`](#{FILE_BASE_URL}#{path_prefix}#{file}#L#{line_number})"
153
+ "[`#{path_prefix}#{file}#L#{line_number}`](#{Runtime::Env.file_base_url}#{path_prefix}#{file}#L#{line_number})"
160
154
  end
161
155
 
162
156
  private
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GitlabQuality
4
4
  module TestTooling
5
- VERSION = "1.3.0"
5
+ VERSION = "1.4.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.4.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-10-27 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