gitlab_quality-test_tooling 1.3.0 → 1.4.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: 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