gitlab_quality-test_tooling 1.39.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +50 -11
- data/.ruby-version +1 -1
- data/.tool-versions +2 -1
- data/Gemfile.lock +124 -116
- data/README.md +14 -0
- data/exe/existing-test-health-issue +59 -0
- data/lib/gitlab_quality/test_tooling/report/failed_test_issue.rb +84 -6
- data/lib/gitlab_quality/test_tooling/report/flaky_test_issue.rb +1 -1
- data/lib/gitlab_quality/test_tooling/report/health_problem_reporter.rb +27 -77
- data/lib/gitlab_quality/test_tooling/report/slow_test_issue.rb +1 -1
- data/lib/gitlab_quality/test_tooling/report/test_health_issue_finder.rb +79 -0
- data/lib/gitlab_quality/test_tooling/version.rb +1 -1
- metadata +30 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 69b4478a8c7af86d2dae63c79d0924037feb673486f1ae6f15d5617121a0b9f4
|
4
|
+
data.tar.gz: 9a7f797d54687a515d834cfe0585bca7b87f5a28cd33000d5c06ebea292de56e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 50206a9f212b2d78ab38b8433ffb5f22864e8a322b6065b6492a9023104e2caf0097042c8935c913f7d16de982fd3fb04a8438d294865f61caac84eee60d943e
|
7
|
+
data.tar.gz: 1267891667d8bf81617843d65ea6cd9bee2aef24007a2dc53ba92d970529f771dcbf8b8209aba7d59531f40ffac2e2c549444441dcae123c8e70bac1c0d417e7
|
data/.rubocop_todo.yml
CHANGED
@@ -1,17 +1,11 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on
|
3
|
+
# on 2024-10-10 06:12:01 UTC using RuboCop version 1.62.1.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
8
8
|
|
9
|
-
# Offense count: 1
|
10
|
-
# This cop supports safe autocorrection (--autocorrect).
|
11
|
-
Cop/CustomErrorClass:
|
12
|
-
Exclude:
|
13
|
-
- 'lib/gitlab_quality/test_tooling.rb'
|
14
|
-
|
15
9
|
# Offense count: 1
|
16
10
|
# This cop supports safe autocorrection (--autocorrect).
|
17
11
|
# Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include.
|
@@ -20,9 +14,54 @@ Gemspec/OrderedDependencies:
|
|
20
14
|
Exclude:
|
21
15
|
- 'gitlab_quality-test_tooling.gemspec'
|
22
16
|
|
17
|
+
# Offense count: 3
|
18
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
19
|
+
# Configuration parameters: Categories, ExpectedOrder.
|
20
|
+
# ExpectedOrder: module_inclusion, constants, public_class_methods, initializer, public_methods, protected_methods, private_methods
|
21
|
+
Layout/ClassStructure:
|
22
|
+
Exclude:
|
23
|
+
- 'lib/gitlab_quality/test_tooling/labels_inference.rb'
|
24
|
+
- 'lib/gitlab_quality/test_tooling/report/concerns/issue_reports.rb'
|
25
|
+
- 'lib/gitlab_quality/test_tooling/report/update_screenshot_path.rb'
|
26
|
+
|
27
|
+
# Offense count: 6
|
28
|
+
# This cop supports safe autocorrection (--autocorrect).
|
29
|
+
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
30
|
+
# SupportedStyles: aligned, indented
|
31
|
+
Layout/LineEndStringConcatenationIndentation:
|
32
|
+
Exclude:
|
33
|
+
- 'lib/gitlab_quality/test_tooling/gitlab_client/merge_requests_dry_client.rb'
|
34
|
+
- 'lib/gitlab_quality/test_tooling/report/report_results.rb'
|
35
|
+
- 'spec/gitlab_quality/test_tooling/gitlab_client/issues_client_spec.rb'
|
36
|
+
- 'spec/gitlab_quality/test_tooling/report/failed_test_issue_spec.rb'
|
37
|
+
- 'spec/gitlab_quality/test_tooling/report/slow_test_issue_spec.rb'
|
38
|
+
|
39
|
+
# Offense count: 200
|
40
|
+
# Configuration parameters: EnforcedStyle, IgnoreSharedExamples.
|
41
|
+
# SupportedStyles: always, named_only
|
42
|
+
RSpec/NamedSubject:
|
43
|
+
Enabled: false
|
44
|
+
|
45
|
+
# Offense count: 2
|
46
|
+
# This cop supports safe autocorrection (--autocorrect).
|
47
|
+
# Configuration parameters: AllowOnlyRestArgument, UseAnonymousForwarding, RedundantRestArgumentNames, RedundantKeywordRestArgumentNames, RedundantBlockArgumentNames.
|
48
|
+
# RedundantRestArgumentNames: args, arguments
|
49
|
+
# RedundantKeywordRestArgumentNames: kwargs, options, opts
|
50
|
+
# RedundantBlockArgumentNames: blk, block, proc
|
51
|
+
Style/ArgumentsForwarding:
|
52
|
+
Exclude:
|
53
|
+
- 'lib/gitlab_quality/test_tooling/test_results/base_test_results.rb'
|
54
|
+
|
55
|
+
# Offense count: 2
|
56
|
+
# This cop supports safe autocorrection (--autocorrect).
|
57
|
+
# Configuration parameters: AllowMultipleReturnValues.
|
58
|
+
Style/RedundantReturn:
|
59
|
+
Exclude:
|
60
|
+
- 'lib/gitlab_quality/test_tooling/runtime/env.rb'
|
61
|
+
|
23
62
|
# Offense count: 1
|
24
|
-
#
|
25
|
-
#
|
26
|
-
|
63
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
64
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
65
|
+
Style/ReturnNilInPredicateMethodDefinition:
|
27
66
|
Exclude:
|
28
|
-
- 'gitlab_quality
|
67
|
+
- 'lib/gitlab_quality/test_tooling/knapsack_reports/spec_run_time.rb'
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.2.
|
1
|
+
3.2.5
|
data/.tool-versions
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
ruby 3.
|
1
|
+
ruby 3.2.5
|
2
|
+
lefthook 1.7.14
|
data/Gemfile.lock
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
gitlab_quality-test_tooling (1.
|
4
|
+
gitlab_quality-test_tooling (2.1.0)
|
5
5
|
activesupport (>= 7.0, < 7.2)
|
6
6
|
amatch (~> 0.4.1)
|
7
7
|
fog-google (~> 1.24, >= 1.24.1)
|
8
|
-
gitlab (
|
8
|
+
gitlab (>= 4.19, < 6.0)
|
9
9
|
http (~> 5.0)
|
10
10
|
influxdb-client (~> 3.1)
|
11
11
|
nokogiri (~> 1.10)
|
@@ -18,7 +18,7 @@ PATH
|
|
18
18
|
GEM
|
19
19
|
remote: https://rubygems.org/
|
20
20
|
specs:
|
21
|
-
activesupport (7.1.
|
21
|
+
activesupport (7.1.4)
|
22
22
|
base64
|
23
23
|
bigdecimal
|
24
24
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
@@ -28,8 +28,8 @@ GEM
|
|
28
28
|
minitest (>= 5.1)
|
29
29
|
mutex_m
|
30
30
|
tzinfo (~> 2.0)
|
31
|
-
addressable (2.8.
|
32
|
-
public_suffix (>= 2.0.2, <
|
31
|
+
addressable (2.8.7)
|
32
|
+
public_suffix (>= 2.0.2, < 7.0)
|
33
33
|
amatch (0.4.1)
|
34
34
|
mize
|
35
35
|
tins (~> 1.0)
|
@@ -38,8 +38,8 @@ GEM
|
|
38
38
|
base64 (0.2.0)
|
39
39
|
benchmark (0.3.0)
|
40
40
|
bigdecimal (3.1.8)
|
41
|
-
binding_of_caller (1.0.
|
42
|
-
debug_inspector (>=
|
41
|
+
binding_of_caller (1.0.1)
|
42
|
+
debug_inspector (>= 1.2.0)
|
43
43
|
builder (3.3.0)
|
44
44
|
byebug (11.1.3)
|
45
45
|
claide (1.1.0)
|
@@ -50,13 +50,15 @@ GEM
|
|
50
50
|
climate_control (1.2.0)
|
51
51
|
coderay (1.1.3)
|
52
52
|
colored2 (3.1.2)
|
53
|
-
concurrent-ruby (1.
|
53
|
+
concurrent-ruby (1.3.4)
|
54
54
|
connection_pool (2.4.1)
|
55
55
|
cork (0.3.0)
|
56
56
|
colored2 (~> 3.1)
|
57
|
-
crack (0.
|
57
|
+
crack (1.0.0)
|
58
|
+
bigdecimal
|
58
59
|
rexml
|
59
|
-
|
60
|
+
csv (3.3.0)
|
61
|
+
danger (9.5.0)
|
60
62
|
claide (~> 1.0)
|
61
63
|
claide-plugins (>= 0.9.2)
|
62
64
|
colored2 (~> 3.1)
|
@@ -66,29 +68,30 @@ GEM
|
|
66
68
|
git (~> 1.13)
|
67
69
|
kramdown (~> 2.3)
|
68
70
|
kramdown-parser-gfm (~> 1.0)
|
69
|
-
no_proxy_fix
|
70
71
|
octokit (>= 4.0)
|
71
72
|
terminal-table (>= 1, < 4)
|
72
|
-
danger-gitlab (
|
73
|
+
danger-gitlab (9.0.0)
|
73
74
|
danger
|
74
|
-
gitlab (~>
|
75
|
+
gitlab (~> 5.0)
|
75
76
|
debug_inspector (1.2.0)
|
76
77
|
declarative (0.0.20)
|
77
|
-
diff-lcs (1.5.
|
78
|
-
docile (1.4.
|
78
|
+
diff-lcs (1.5.1)
|
79
|
+
docile (1.4.1)
|
79
80
|
domain_name (0.6.20240107)
|
80
81
|
drb (2.2.1)
|
81
82
|
e2mmap (0.1.0)
|
82
|
-
excon (0.
|
83
|
-
faraday (2.
|
84
|
-
faraday-net_http (>= 2.0, < 3.
|
83
|
+
excon (0.112.0)
|
84
|
+
faraday (2.12.0)
|
85
|
+
faraday-net_http (>= 2.0, < 3.4)
|
86
|
+
json
|
87
|
+
logger
|
85
88
|
faraday-http-cache (2.5.1)
|
86
89
|
faraday (>= 0.8)
|
87
|
-
faraday-net_http (3.
|
90
|
+
faraday-net_http (3.3.0)
|
88
91
|
net-http
|
89
|
-
ffi (1.
|
90
|
-
ffi-compiler (1.
|
91
|
-
ffi (>= 1.
|
92
|
+
ffi (1.17.0)
|
93
|
+
ffi-compiler (1.3.2)
|
94
|
+
ffi (>= 1.15.5)
|
92
95
|
rake
|
93
96
|
fog-core (2.4.0)
|
94
97
|
builder
|
@@ -118,44 +121,45 @@ GEM
|
|
118
121
|
git (1.19.1)
|
119
122
|
addressable (~> 2.8)
|
120
123
|
rchardet (~> 1.8)
|
121
|
-
gitlab (
|
124
|
+
gitlab (5.0.0)
|
122
125
|
httparty (~> 0.20)
|
123
126
|
terminal-table (>= 1.5.1)
|
124
127
|
gitlab-dangerfiles (3.13.0)
|
125
128
|
danger (>= 8.4.5)
|
126
129
|
danger-gitlab (>= 8.0.0)
|
127
130
|
rake
|
128
|
-
gitlab-styles (
|
129
|
-
rubocop (~> 1.
|
130
|
-
rubocop-
|
131
|
-
rubocop-
|
132
|
-
rubocop-
|
133
|
-
rubocop-
|
134
|
-
|
131
|
+
gitlab-styles (12.0.1)
|
132
|
+
rubocop (~> 1.62.1)
|
133
|
+
rubocop-factory_bot (~> 2.25.1)
|
134
|
+
rubocop-graphql (~> 1.5.0)
|
135
|
+
rubocop-performance (~> 1.20.2)
|
136
|
+
rubocop-rails (~> 2.24.0)
|
137
|
+
rubocop-rspec (~> 2.27.1)
|
138
|
+
google-apis-compute_v1 (0.108.0)
|
135
139
|
google-apis-core (>= 0.15.0, < 2.a)
|
136
|
-
google-apis-core (0.15.
|
140
|
+
google-apis-core (0.15.1)
|
137
141
|
addressable (~> 2.5, >= 2.5.1)
|
138
142
|
googleauth (~> 1.9)
|
139
|
-
httpclient (>= 2.8.
|
143
|
+
httpclient (>= 2.8.3, < 3.a)
|
140
144
|
mini_mime (~> 1.0)
|
145
|
+
mutex_m
|
141
146
|
representable (~> 3.0)
|
142
147
|
retriable (>= 2.0, < 4.a)
|
143
|
-
rexml
|
144
148
|
google-apis-dns_v1 (0.44.0)
|
145
149
|
google-apis-core (>= 0.15.0, < 2.a)
|
146
150
|
google-apis-iamcredentials_v1 (0.21.0)
|
147
151
|
google-apis-core (>= 0.15.0, < 2.a)
|
148
|
-
google-apis-monitoring_v3 (0.
|
152
|
+
google-apis-monitoring_v3 (0.69.0)
|
149
153
|
google-apis-core (>= 0.15.0, < 2.a)
|
150
|
-
google-apis-pubsub_v1 (0.
|
154
|
+
google-apis-pubsub_v1 (0.56.0)
|
151
155
|
google-apis-core (>= 0.15.0, < 2.a)
|
152
156
|
google-apis-sqladmin_v1beta4 (0.74.0)
|
153
157
|
google-apis-core (>= 0.15.0, < 2.a)
|
154
|
-
google-apis-storage_v1 (0.
|
158
|
+
google-apis-storage_v1 (0.46.0)
|
155
159
|
google-apis-core (>= 0.15.0, < 2.a)
|
156
|
-
google-cloud-env (2.
|
160
|
+
google-cloud-env (2.2.1)
|
157
161
|
faraday (>= 1.0, < 3.a)
|
158
|
-
googleauth (1.11.
|
162
|
+
googleauth (1.11.1)
|
159
163
|
faraday (>= 1.0, < 3.a)
|
160
164
|
google-cloud-env (~> 2.1)
|
161
165
|
jwt (>= 1.4, < 3.0)
|
@@ -176,93 +180,95 @@ GEM
|
|
176
180
|
guard (~> 2.1)
|
177
181
|
guard-compat (~> 1.1)
|
178
182
|
rspec (>= 2.99.0, < 4.0)
|
179
|
-
hashdiff (1.1.
|
180
|
-
http (5.
|
183
|
+
hashdiff (1.1.1)
|
184
|
+
http (5.2.0)
|
181
185
|
addressable (~> 2.8)
|
186
|
+
base64 (~> 0.1)
|
182
187
|
http-cookie (~> 1.0)
|
183
188
|
http-form_data (~> 2.2)
|
184
|
-
llhttp-ffi (~> 0.
|
185
|
-
http-cookie (1.0.
|
189
|
+
llhttp-ffi (~> 0.5.0)
|
190
|
+
http-cookie (1.0.7)
|
186
191
|
domain_name (~> 0.5)
|
187
192
|
http-form_data (2.3.0)
|
188
|
-
httparty (0.
|
193
|
+
httparty (0.22.0)
|
194
|
+
csv
|
189
195
|
mini_mime (>= 1.0.0)
|
190
196
|
multi_xml (>= 0.5.2)
|
191
197
|
httpclient (2.8.3)
|
192
|
-
i18n (1.14.
|
198
|
+
i18n (1.14.6)
|
193
199
|
concurrent-ruby (~> 1.0)
|
194
200
|
influxdb-client (3.1.0)
|
195
|
-
jaro_winkler (1.
|
196
|
-
json (2.7.
|
197
|
-
jwt (2.
|
201
|
+
jaro_winkler (1.6.0)
|
202
|
+
json (2.7.2)
|
203
|
+
jwt (2.9.3)
|
198
204
|
base64
|
199
205
|
kramdown (2.4.0)
|
200
206
|
rexml
|
201
207
|
kramdown-parser-gfm (1.1.0)
|
202
208
|
kramdown (~> 2.0)
|
203
|
-
|
204
|
-
|
209
|
+
language_server-protocol (3.17.0.3)
|
210
|
+
lefthook (1.7.18)
|
211
|
+
listen (3.9.0)
|
205
212
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
206
213
|
rb-inotify (~> 0.9, >= 0.9.10)
|
207
|
-
llhttp-ffi (0.
|
214
|
+
llhttp-ffi (0.5.0)
|
208
215
|
ffi-compiler (~> 1.0)
|
209
216
|
rake (~> 13.0)
|
217
|
+
logger (1.6.1)
|
210
218
|
lumberjack (1.2.10)
|
211
|
-
method_source (1.
|
212
|
-
mime-types (3.
|
219
|
+
method_source (1.1.0)
|
220
|
+
mime-types (3.6.0)
|
221
|
+
logger
|
213
222
|
mime-types-data (~> 3.2015)
|
214
|
-
mime-types-data (3.2024.
|
223
|
+
mime-types-data (3.2024.1001)
|
215
224
|
mini_mime (1.1.5)
|
216
|
-
mini_portile2 (2.8.
|
217
|
-
minitest (5.
|
218
|
-
mize (0.
|
219
|
-
protocol (~> 2.0)
|
225
|
+
mini_portile2 (2.8.7)
|
226
|
+
minitest (5.25.1)
|
227
|
+
mize (0.6.0)
|
220
228
|
multi_json (1.15.0)
|
221
|
-
multi_xml (0.
|
229
|
+
multi_xml (0.7.1)
|
230
|
+
bigdecimal (~> 3.1)
|
222
231
|
mutex_m (0.2.0)
|
223
232
|
nap (1.1.0)
|
224
233
|
nenv (0.3.0)
|
225
234
|
net-http (0.4.1)
|
226
235
|
uri
|
227
|
-
|
228
|
-
nokogiri (1.16.0)
|
236
|
+
nokogiri (1.16.7)
|
229
237
|
mini_portile2 (~> 2.8.2)
|
230
238
|
racc (~> 1.4)
|
231
239
|
notiffany (0.1.3)
|
232
240
|
nenv (~> 0.1)
|
233
241
|
shellany (~> 0.0)
|
234
|
-
octokit (
|
242
|
+
octokit (9.1.0)
|
235
243
|
faraday (>= 1, < 3)
|
236
244
|
sawyer (~> 0.9)
|
237
245
|
open4 (1.3.4)
|
238
246
|
os (1.1.4)
|
239
|
-
parallel (1.
|
240
|
-
parser (3.3.0
|
247
|
+
parallel (1.26.3)
|
248
|
+
parser (3.3.5.0)
|
241
249
|
ast (~> 2.4.1)
|
242
250
|
racc
|
243
|
-
proc_to_ast (0.
|
244
|
-
coderay
|
251
|
+
proc_to_ast (0.2.0)
|
245
252
|
parser
|
253
|
+
rouge
|
246
254
|
unparser
|
247
|
-
protocol (2.0.0)
|
248
|
-
ruby_parser (~> 3.0)
|
249
255
|
pry (0.14.2)
|
250
256
|
coderay (~> 1.1)
|
251
257
|
method_source (~> 1.0)
|
252
258
|
pry-byebug (3.10.1)
|
253
259
|
byebug (~> 11.0)
|
254
260
|
pry (>= 0.13, < 0.15)
|
255
|
-
public_suffix (
|
256
|
-
racc (1.
|
257
|
-
rack (3.
|
261
|
+
public_suffix (6.0.1)
|
262
|
+
racc (1.8.1)
|
263
|
+
rack (3.1.7)
|
258
264
|
rainbow (3.1.1)
|
259
|
-
rake (13.1
|
265
|
+
rake (13.2.1)
|
260
266
|
rb-fsevent (0.11.2)
|
261
|
-
rb-inotify (0.
|
267
|
+
rb-inotify (0.11.1)
|
262
268
|
ffi (~> 1.0)
|
263
269
|
rbs (2.8.4)
|
264
270
|
rchardet (1.8.0)
|
265
|
-
regexp_parser (2.9.
|
271
|
+
regexp_parser (2.9.2)
|
266
272
|
representable (3.2.0)
|
267
273
|
declarative (< 0.1.0)
|
268
274
|
trailblazer-option (>= 0.1.1, < 0.2.0)
|
@@ -270,69 +276,69 @@ GEM
|
|
270
276
|
retriable (3.1.2)
|
271
277
|
reverse_markdown (2.1.1)
|
272
278
|
nokogiri
|
273
|
-
rexml (3.
|
274
|
-
|
275
|
-
|
276
|
-
rspec-
|
277
|
-
rspec-
|
278
|
-
|
279
|
-
|
280
|
-
|
279
|
+
rexml (3.3.8)
|
280
|
+
rouge (4.4.0)
|
281
|
+
rspec (3.13.0)
|
282
|
+
rspec-core (~> 3.13.0)
|
283
|
+
rspec-expectations (~> 3.13.0)
|
284
|
+
rspec-mocks (~> 3.13.0)
|
285
|
+
rspec-core (3.13.1)
|
286
|
+
rspec-support (~> 3.13.0)
|
287
|
+
rspec-expectations (3.13.3)
|
281
288
|
diff-lcs (>= 1.2.0, < 2.0)
|
282
|
-
rspec-support (~> 3.
|
283
|
-
rspec-mocks (3.
|
289
|
+
rspec-support (~> 3.13.0)
|
290
|
+
rspec-mocks (3.13.2)
|
284
291
|
diff-lcs (>= 1.2.0, < 2.0)
|
285
|
-
rspec-support (~> 3.
|
286
|
-
rspec-parameterized (1.0.
|
292
|
+
rspec-support (~> 3.13.0)
|
293
|
+
rspec-parameterized (1.0.2)
|
287
294
|
rspec-parameterized-core (< 2)
|
288
295
|
rspec-parameterized-table_syntax (< 2)
|
289
|
-
rspec-parameterized-core (1.0.
|
296
|
+
rspec-parameterized-core (1.0.1)
|
290
297
|
parser
|
291
|
-
proc_to_ast
|
298
|
+
proc_to_ast (>= 0.2.0)
|
292
299
|
rspec (>= 2.13, < 4)
|
293
300
|
unparser
|
294
301
|
rspec-parameterized-table_syntax (1.0.1)
|
295
302
|
binding_of_caller
|
296
303
|
rspec-parameterized-core (< 2)
|
297
|
-
rspec-support (3.
|
298
|
-
|
304
|
+
rspec-support (3.13.1)
|
305
|
+
rspec_junit_formatter (0.6.0)
|
306
|
+
rspec-core (>= 2, < 4, != 2.12.0)
|
307
|
+
rubocop (1.62.1)
|
299
308
|
json (~> 2.3)
|
309
|
+
language_server-protocol (>= 3.17.0)
|
300
310
|
parallel (~> 1.10)
|
301
|
-
parser (>= 3.
|
311
|
+
parser (>= 3.3.0.2)
|
302
312
|
rainbow (>= 2.2.2, < 4.0)
|
303
313
|
regexp_parser (>= 1.8, < 3.0)
|
304
314
|
rexml (>= 3.2.5, < 4.0)
|
305
|
-
rubocop-ast (>= 1.
|
315
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
306
316
|
ruby-progressbar (~> 1.7)
|
307
317
|
unicode-display_width (>= 2.4.0, < 3.0)
|
308
|
-
rubocop-ast (1.
|
309
|
-
parser (>= 3.
|
310
|
-
rubocop-capybara (2.
|
318
|
+
rubocop-ast (1.32.3)
|
319
|
+
parser (>= 3.3.1.0)
|
320
|
+
rubocop-capybara (2.21.0)
|
311
321
|
rubocop (~> 1.41)
|
312
322
|
rubocop-factory_bot (2.25.1)
|
313
323
|
rubocop (~> 1.41)
|
314
|
-
rubocop-graphql (
|
315
|
-
rubocop (>=
|
324
|
+
rubocop-graphql (1.5.4)
|
325
|
+
rubocop (>= 1.50, < 2)
|
316
326
|
rubocop-performance (1.20.2)
|
317
327
|
rubocop (>= 1.48.1, < 2.0)
|
318
328
|
rubocop-ast (>= 1.30.0, < 2.0)
|
319
|
-
rubocop-rails (2.
|
329
|
+
rubocop-rails (2.24.1)
|
320
330
|
activesupport (>= 4.2.0)
|
321
331
|
rack (>= 1.1)
|
322
332
|
rubocop (>= 1.33.0, < 2.0)
|
323
|
-
rubocop-ast (>= 1.
|
324
|
-
rubocop-rspec (2.
|
333
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
334
|
+
rubocop-rspec (2.27.1)
|
325
335
|
rubocop (~> 1.40)
|
326
336
|
rubocop-capybara (~> 2.17)
|
327
337
|
rubocop-factory_bot (~> 2.22)
|
328
338
|
ruby-progressbar (1.13.0)
|
329
|
-
ruby_parser (3.21.0)
|
330
|
-
racc (~> 1.5)
|
331
|
-
sexp_processor (~> 4.16)
|
332
339
|
sawyer (0.9.2)
|
333
340
|
addressable (>= 2.3.5)
|
334
341
|
faraday (>= 0.17.3, < 3)
|
335
|
-
sexp_processor (4.17.1)
|
336
342
|
shellany (0.0.1)
|
337
343
|
signet (0.19.0)
|
338
344
|
addressable (~> 2.8)
|
@@ -346,7 +352,7 @@ GEM
|
|
346
352
|
simplecov-cobertura (2.1.0)
|
347
353
|
rexml
|
348
354
|
simplecov (~> 0.19)
|
349
|
-
simplecov-html (0.
|
355
|
+
simplecov-html (0.13.1)
|
350
356
|
simplecov_json_formatter (0.1.4)
|
351
357
|
solargraph (0.50.0)
|
352
358
|
backport (~> 1.2)
|
@@ -368,26 +374,27 @@ GEM
|
|
368
374
|
table_print (1.5.7)
|
369
375
|
terminal-table (3.0.2)
|
370
376
|
unicode-display_width (>= 1.1.1, < 3)
|
371
|
-
thor (1.3.
|
372
|
-
tilt (2.
|
373
|
-
timecop (0.9.
|
374
|
-
tins (1.
|
377
|
+
thor (1.3.2)
|
378
|
+
tilt (2.4.0)
|
379
|
+
timecop (0.9.10)
|
380
|
+
tins (1.34.0)
|
381
|
+
bigdecimal
|
375
382
|
sync
|
376
383
|
trailblazer-option (0.1.2)
|
377
384
|
tzinfo (2.0.6)
|
378
385
|
concurrent-ruby (~> 1.0)
|
379
386
|
uber (0.1.0)
|
380
|
-
unicode-display_width (2.
|
381
|
-
unparser (0.6.
|
387
|
+
unicode-display_width (2.6.0)
|
388
|
+
unparser (0.6.15)
|
382
389
|
diff-lcs (~> 1.3)
|
383
|
-
parser (>= 3.
|
384
|
-
uri (0.13.
|
390
|
+
parser (>= 3.3.0)
|
391
|
+
uri (0.13.1)
|
385
392
|
webmock (3.7.0)
|
386
393
|
addressable (>= 2.3.6)
|
387
394
|
crack (>= 0.3.2)
|
388
395
|
hashdiff (>= 0.4.0, < 2.0.0)
|
389
|
-
yard (0.9.
|
390
|
-
zeitwerk (2.6.
|
396
|
+
yard (0.9.37)
|
397
|
+
zeitwerk (2.6.18)
|
391
398
|
|
392
399
|
PLATFORMS
|
393
400
|
ruby
|
@@ -395,13 +402,14 @@ PLATFORMS
|
|
395
402
|
DEPENDENCIES
|
396
403
|
climate_control (~> 1.2)
|
397
404
|
gitlab-dangerfiles (~> 3.8)
|
398
|
-
gitlab-styles (~>
|
405
|
+
gitlab-styles (~> 12.0)
|
399
406
|
gitlab_quality-test_tooling!
|
400
407
|
guard-rspec (~> 4.7)
|
401
408
|
lefthook (~> 1.3)
|
402
409
|
pry-byebug (= 3.10.1)
|
403
410
|
rake (~> 13.0)
|
404
411
|
rspec (~> 3.12)
|
412
|
+
rspec_junit_formatter (~> 0.6.0)
|
405
413
|
simplecov (~> 0.22)
|
406
414
|
simplecov-cobertura (~> 2.1)
|
407
415
|
solargraph (~> 0.41)
|
@@ -409,4 +417,4 @@ DEPENDENCIES
|
|
409
417
|
webmock (= 3.7.0)
|
410
418
|
|
411
419
|
BUNDLED WITH
|
412
|
-
2.5.
|
420
|
+
2.5.19
|
data/README.md
CHANGED
@@ -177,6 +177,20 @@ Usage: exe/failed-test-issues [options]
|
|
177
177
|
-h, --help Show the usage
|
178
178
|
```
|
179
179
|
|
180
|
+
### `exe/existing-test-health-issue`
|
181
|
+
|
182
|
+
```shell
|
183
|
+
Purpose: Checks whether tests coming from the rspec JSON report files has an existing test health issue opened.
|
184
|
+
Usage: exe/existing-test-health-issue [options]
|
185
|
+
-i, --input-files INPUT_FILES JSON rspec-retry report files
|
186
|
+
-p, --project PROJECT Can be an integer or a group/project string
|
187
|
+
-t, --token TOKEN A valid access token with `api` scope and Maintainer permission in PROJECT
|
188
|
+
--health-problem-type PROBLEM_TYPE
|
189
|
+
Look for the given health problem type (failures, pass-after-retry, slow)
|
190
|
+
-v, --version Show the version
|
191
|
+
-h, --help Show the usage
|
192
|
+
```
|
193
|
+
|
180
194
|
### `exe/flaky-test-issues`
|
181
195
|
|
182
196
|
```shell
|
@@ -0,0 +1,59 @@
|
|
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
|
+
HEALTH_PROBLEM_TYPES = GitlabQuality::TestTooling::Report::TestHealthIssueFinder::HEALTH_PROBLEM_TYPE_TO_LABEL.keys
|
11
|
+
|
12
|
+
options = OptionParser.new do |opts|
|
13
|
+
opts.banner = "Usage: #{$PROGRAM_NAME} [options]"
|
14
|
+
|
15
|
+
opts.on('-i', '--input-files INPUT_FILES', String, 'JSON rspec-retry report files') do |input_files|
|
16
|
+
params[:input_files] = input_files
|
17
|
+
end
|
18
|
+
|
19
|
+
opts.on('-p', '--project PROJECT', String, 'Can be an integer or a group/project string') do |project|
|
20
|
+
params[:project] = project
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.on('-t', '--token TOKEN', String, 'A valid access token with `api` scope and Maintainer permission in PROJECT') do |token|
|
24
|
+
params[:token] = token
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("--health-problem-type PROBLEM_TYPE", String, "Look for the given health problem type (#{HEALTH_PROBLEM_TYPES.join(', ')})") do |value|
|
28
|
+
raise ArgumentError, "Invalid health problem type: #{value}. Valid options are: #{HEALTH_PROBLEM_TYPES.join(', ')}" unless HEALTH_PROBLEM_TYPES.include?(value)
|
29
|
+
|
30
|
+
params[:health_problem_type] = value
|
31
|
+
end
|
32
|
+
|
33
|
+
opts.on_tail('-v', '--version', 'Show the version') do
|
34
|
+
require_relative "../lib/gitlab_quality/test_tooling/version"
|
35
|
+
puts "#{$PROGRAM_NAME} : #{GitlabQuality::TestTooling::VERSION}"
|
36
|
+
exit
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on_tail('-h', '--help', 'Show the usage') do
|
40
|
+
puts "Purpose: Checks whether tests coming from the rspec JSON report files has an existing test health issue opened."
|
41
|
+
puts opts
|
42
|
+
exit
|
43
|
+
end
|
44
|
+
|
45
|
+
opts.parse(ARGV)
|
46
|
+
end
|
47
|
+
|
48
|
+
if params.any?
|
49
|
+
raise ArgumentError, "No health problem type given. Valid options are: #{HEALTH_PROBLEM_TYPES.join(', ')}" unless params.key?(:health_problem_type)
|
50
|
+
|
51
|
+
if GitlabQuality::TestTooling::Report::TestHealthIssueFinder.new(**params).found_existing_unhealthy_test_issue?
|
52
|
+
exit 0
|
53
|
+
else
|
54
|
+
exit 1
|
55
|
+
end
|
56
|
+
else
|
57
|
+
puts options
|
58
|
+
exit 1
|
59
|
+
end
|
@@ -29,6 +29,17 @@ module GitlabQuality
|
|
29
29
|
@max_diff_ratio = max_diff_ratio.to_f
|
30
30
|
end
|
31
31
|
|
32
|
+
def most_recent_report_date_for_issue(issue_iid:)
|
33
|
+
reports_discussion = existing_reports_discussion(issue_iid: issue_iid)
|
34
|
+
return unless reports_discussion
|
35
|
+
|
36
|
+
# We're skipping the first note of the discussion as this is the "non-collapsible note", aka
|
37
|
+
# the "header note", which doesn't contain any stack trace.
|
38
|
+
reports_discussion.notes[1..].filter_map do |reports_note|
|
39
|
+
most_recent_report_from_reports_note(reports_note)&.report_date
|
40
|
+
end.max
|
41
|
+
end
|
42
|
+
|
32
43
|
private
|
33
44
|
|
34
45
|
attr_reader :base_issue_labels, :max_diff_ratio
|
@@ -37,12 +48,57 @@ module GitlabQuality
|
|
37
48
|
'failed'
|
38
49
|
end
|
39
50
|
|
40
|
-
|
41
|
-
|
51
|
+
# We redefine this method, because we are reporting failed tests in a discussion instead of a comment.
|
52
|
+
#
|
53
|
+
# We do this because a test could fail for many different reasons, so we report
|
54
|
+
# different test failures in the same discussion, under different threads.
|
55
|
+
def add_report_to_issue(issue:, test:, related_issues:)
|
56
|
+
reports_discussion = find_or_create_reports_discussion(issue_iid: issue.iid)
|
57
|
+
current_reports_note = find_failure_discussion_note(issue: issue, test: test, reports_discussion: reports_discussion)
|
58
|
+
|
59
|
+
new_reports_list = new_reports_list(current_reports_note: current_reports_note, test: test)
|
60
|
+
note_body = new_note_body(
|
61
|
+
new_reports_list: new_reports_list,
|
62
|
+
related_issues: related_issues,
|
63
|
+
options: {
|
64
|
+
reports_discussion: reports_discussion,
|
65
|
+
test: test
|
66
|
+
}
|
67
|
+
)
|
68
|
+
|
69
|
+
if current_reports_note
|
70
|
+
gitlab.edit_issue_note(
|
71
|
+
issue_iid: issue.iid,
|
72
|
+
note_id: current_reports_note.id,
|
73
|
+
note: note_body
|
74
|
+
)
|
75
|
+
else
|
76
|
+
gitlab.add_note_to_issue_discussion_as_thread(
|
77
|
+
iid: issue.iid,
|
78
|
+
discussion_id: reports_discussion.id,
|
79
|
+
note: note_body
|
80
|
+
)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def find_or_create_reports_discussion(issue_iid:)
|
85
|
+
reports_discussion = existing_reports_discussion(issue_iid: issue_iid)
|
86
|
+
return reports_discussion if reports_discussion
|
87
|
+
|
88
|
+
gitlab.create_issue_discussion(iid: issue_iid, note: report_section_header)
|
42
89
|
end
|
43
90
|
|
44
|
-
def
|
45
|
-
|
91
|
+
def existing_reports_discussion(issue_iid:)
|
92
|
+
gitlab.find_issue_discussions(iid: issue_iid).find do |discussion|
|
93
|
+
next if discussion.individual_note
|
94
|
+
next unless discussion.notes.first
|
95
|
+
|
96
|
+
discussion.notes.first.body.start_with?(report_section_header)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_is_applicable?(test)
|
101
|
+
test.status == 'failed'
|
46
102
|
end
|
47
103
|
|
48
104
|
def identity_labels
|
@@ -57,8 +113,30 @@ module GitlabQuality
|
|
57
113
|
"##### Stack trace\n\n```\n#{test.full_stacktrace}\n```"
|
58
114
|
end
|
59
115
|
|
60
|
-
def health_problem_status_label_quick_action(reports_list)
|
61
|
-
|
116
|
+
def health_problem_status_label_quick_action(reports_list, options: {})
|
117
|
+
quick_actions = []
|
118
|
+
quick_actions << '/label ~"priority::1" ~"severity::1"' if reports_list.spiked_in_short_period?
|
119
|
+
|
120
|
+
# We can have several kinds of failures for a single test.
|
121
|
+
# We want to count all the failures that are reported for a test.
|
122
|
+
reports_notes = options[:reports_discussion].notes[1..] || []
|
123
|
+
all_reports_count = reports_notes.sum do |report_note|
|
124
|
+
new_reports_list(current_reports_note: report_note, test: options[:test]).reports_count
|
125
|
+
end
|
126
|
+
|
127
|
+
quick_actions <<
|
128
|
+
case all_reports_count
|
129
|
+
when 149..Float::INFINITY
|
130
|
+
'/label ~"failed-tests::1"'
|
131
|
+
when 137..148
|
132
|
+
'/label ~"failed-tests::2"'
|
133
|
+
when 130..136
|
134
|
+
'/label ~"failed-tests::3"'
|
135
|
+
else
|
136
|
+
'/label ~"failed-tests::4"'
|
137
|
+
end
|
138
|
+
|
139
|
+
quick_actions.join("\n")
|
62
140
|
end
|
63
141
|
|
64
142
|
def up_to_date_labels(test:, issue: nil, new_labels: Set.new)
|
@@ -52,7 +52,7 @@ module GitlabQuality
|
|
52
52
|
REPORTS_DOCUMENTATION
|
53
53
|
end
|
54
54
|
|
55
|
-
def health_problem_status_label_quick_action(reports_list)
|
55
|
+
def health_problem_status_label_quick_action(reports_list, **)
|
56
56
|
case reports_list.reports_count
|
57
57
|
when 399..Float::INFINITY
|
58
58
|
'/label ~"flakiness::1"'
|
@@ -11,7 +11,7 @@ module GitlabQuality
|
|
11
11
|
# - Takes a project where flaky test issues should be created
|
12
12
|
# - For every passed test in the report:
|
13
13
|
# - Find issue by test hash or create a new issue if no issue was found
|
14
|
-
# - Add a
|
14
|
+
# - Add a Failures/Flakiness/Slowness/... report in the "<Failures/Flakiness/Slowness/...> reports" note
|
15
15
|
class HealthProblemReporter < ReportAsIssue
|
16
16
|
include Concerns::GroupAndCategoryLabels
|
17
17
|
include Concerns::IssueReports
|
@@ -25,11 +25,10 @@ module GitlabQuality
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def most_recent_report_date_for_issue(issue_iid:)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
28
|
+
reports_note = existing_reports_note(issue_iid: issue_iid)
|
29
|
+
return unless reports_note
|
30
|
+
|
31
|
+
most_recent_report_from_reports_note(reports_note)&.report_date
|
33
32
|
end
|
34
33
|
|
35
34
|
private
|
@@ -42,10 +41,6 @@ module GitlabQuality
|
|
42
41
|
false
|
43
42
|
end
|
44
43
|
|
45
|
-
def report_in_discussion?
|
46
|
-
false
|
47
|
-
end
|
48
|
-
|
49
44
|
def identity_labels
|
50
45
|
[]
|
51
46
|
end
|
@@ -58,15 +53,11 @@ module GitlabQuality
|
|
58
53
|
''
|
59
54
|
end
|
60
55
|
|
61
|
-
def find_failure_discussion_note(_issue:, _test:, _reports_discussion:)
|
62
|
-
nil
|
63
|
-
end
|
64
|
-
|
65
56
|
def reports_extra_content(_test)
|
66
57
|
''
|
67
58
|
end
|
68
59
|
|
69
|
-
def health_problem_status_label_quick_action(
|
60
|
+
def health_problem_status_label_quick_action(*)
|
70
61
|
''
|
71
62
|
end
|
72
63
|
|
@@ -74,24 +65,6 @@ module GitlabQuality
|
|
74
65
|
found_label
|
75
66
|
end
|
76
67
|
|
77
|
-
def most_recent_report_from_discussion(issue_iid:)
|
78
|
-
reports_discussion = existing_reports_discussion(issue_iid: issue_iid)
|
79
|
-
return unless reports_discussion
|
80
|
-
|
81
|
-
# We're skipping the first note of the discussion as this is the "non-collapsible note", aka
|
82
|
-
# the "header note", which doesn't contain any stack trace.
|
83
|
-
reports_discussion.notes[1..].filter_map do |reports_note|
|
84
|
-
most_recent_report_from_reports_note(reports_note)&.report_date
|
85
|
-
end.max
|
86
|
-
end
|
87
|
-
|
88
|
-
def most_recent_report_from_note(issue_iid:)
|
89
|
-
reports_note = existing_reports_note(issue_iid: issue_iid)
|
90
|
-
return unless reports_note
|
91
|
-
|
92
|
-
most_recent_report_from_reports_note(reports_note)&.report_date
|
93
|
-
end
|
94
|
-
|
95
68
|
def most_recent_report_from_reports_note(reports_note)
|
96
69
|
@most_recent_report_from_reports_note ||= report_lines(reports_note&.body.to_s).first
|
97
70
|
end
|
@@ -138,24 +111,11 @@ module GitlabQuality
|
|
138
111
|
end
|
139
112
|
end
|
140
113
|
|
141
|
-
def add_report_to_issue(issue:, test:, related_issues:)
|
142
|
-
current_reports_note =
|
143
|
-
if report_in_discussion?
|
144
|
-
reports_discussion = find_or_create_reports_discussion(issue_iid: issue.iid)
|
145
|
-
|
146
|
-
find_failure_discussion_note(issue: issue, test: test, reports_discussion: reports_discussion)
|
147
|
-
else
|
148
|
-
existing_reports_note(issue_iid: issue.iid)
|
149
|
-
end
|
114
|
+
def add_report_to_issue(issue:, test:, related_issues:)
|
115
|
+
current_reports_note = existing_reports_note(issue_iid: issue.iid)
|
150
116
|
|
151
|
-
new_reports_list =
|
152
|
-
|
153
|
-
note_body = [
|
154
|
-
new_reports_list.to_s,
|
155
|
-
health_problem_status_label_quick_action(new_reports_list),
|
156
|
-
identity_labels_quick_action,
|
157
|
-
relate_issues_quick_actions(related_issues)
|
158
|
-
].join("\n")
|
117
|
+
new_reports_list = new_reports_list(current_reports_note: current_reports_note, test: test)
|
118
|
+
note_body = new_note_body(new_reports_list: new_reports_list, related_issues: related_issues)
|
159
119
|
|
160
120
|
if current_reports_note
|
161
121
|
gitlab.edit_issue_note(
|
@@ -163,31 +123,31 @@ module GitlabQuality
|
|
163
123
|
note_id: current_reports_note.id,
|
164
124
|
note: note_body
|
165
125
|
)
|
166
|
-
elsif report_in_discussion?
|
167
|
-
gitlab.add_note_to_issue_discussion_as_thread(
|
168
|
-
iid: issue.iid,
|
169
|
-
discussion_id: reports_discussion.id,
|
170
|
-
note: note_body
|
171
|
-
)
|
172
126
|
else
|
173
127
|
gitlab.create_issue_note(iid: issue.iid, note: note_body)
|
174
128
|
end
|
175
129
|
end
|
176
130
|
|
177
|
-
def
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
131
|
+
def new_reports_list(current_reports_note:, test:)
|
132
|
+
increment_reports(
|
133
|
+
current_reports_content: current_reports_note&.body.to_s,
|
134
|
+
test: test,
|
135
|
+
reports_section_header: report_section_header,
|
136
|
+
item_extra_content: item_extra_content(test),
|
137
|
+
reports_extra_content: reports_extra_content(test)
|
138
|
+
)
|
182
139
|
end
|
183
140
|
|
184
|
-
def
|
185
|
-
|
186
|
-
next if discussion.individual_note
|
187
|
-
next unless discussion.notes.first
|
141
|
+
def new_note_body(new_reports_list:, related_issues:, options: {})
|
142
|
+
report = new_reports_list
|
188
143
|
|
189
|
-
|
190
|
-
|
144
|
+
quick_actions = [
|
145
|
+
health_problem_status_label_quick_action(new_reports_list, options: options),
|
146
|
+
identity_labels_quick_action,
|
147
|
+
relate_issues_quick_actions(related_issues)
|
148
|
+
]
|
149
|
+
|
150
|
+
quick_actions.unshift(report).join("\n")
|
191
151
|
end
|
192
152
|
|
193
153
|
def existing_reports_note(issue_iid:)
|
@@ -196,16 +156,6 @@ module GitlabQuality
|
|
196
156
|
end
|
197
157
|
end
|
198
158
|
|
199
|
-
def add_report_for_test(current_reports_content:, test:)
|
200
|
-
increment_reports(
|
201
|
-
current_reports_content: current_reports_content,
|
202
|
-
test: test,
|
203
|
-
reports_section_header: report_section_header,
|
204
|
-
item_extra_content: item_extra_content(test),
|
205
|
-
reports_extra_content: reports_extra_content(test)
|
206
|
-
)
|
207
|
-
end
|
208
|
-
|
209
159
|
def found_label
|
210
160
|
if ENV.key?('CI_MERGE_REQUEST_IID')
|
211
161
|
FOUND_IN_MR_LABEL
|
@@ -42,7 +42,7 @@ module GitlabQuality
|
|
42
42
|
REPORTS_DOCUMENTATION
|
43
43
|
end
|
44
44
|
|
45
|
-
def health_problem_status_label_quick_action(reports_list)
|
45
|
+
def health_problem_status_label_quick_action(reports_list, **)
|
46
46
|
case reports_list.reports_count
|
47
47
|
when 6099..Float::INFINITY
|
48
48
|
'/label ~"slowness::1"'
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'http'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module GitlabQuality
|
7
|
+
module TestTooling
|
8
|
+
module Report
|
9
|
+
class TestHealthIssueFinder < ReportAsIssue
|
10
|
+
HEALTH_PROBLEM_TYPE_TO_LABEL = {
|
11
|
+
'pass-after-retry' => 'test-health:pass-after-retry',
|
12
|
+
'slow' => 'test-health:slow',
|
13
|
+
'failures' => 'test-health:failures'
|
14
|
+
}.freeze
|
15
|
+
|
16
|
+
def initialize(health_problem_type: [], **kwargs)
|
17
|
+
super(**kwargs)
|
18
|
+
|
19
|
+
@health_problem_type = health_problem_type
|
20
|
+
end
|
21
|
+
|
22
|
+
def found_existing_unhealthy_test_issue?
|
23
|
+
issue_url = invoke!
|
24
|
+
|
25
|
+
!issue_url.nil? && !issue_url.empty?
|
26
|
+
end
|
27
|
+
|
28
|
+
def run!
|
29
|
+
existing_issue_found = nil
|
30
|
+
|
31
|
+
applicable_tests.each do |test|
|
32
|
+
issues = find_issues_by_hash(test_hash(test), state: 'opened', labels: search_labels)
|
33
|
+
next if issues.empty?
|
34
|
+
|
35
|
+
existing_issue_found = issues.first.web_url
|
36
|
+
puts "Found an existing test health issue of type #{health_problem_type} for test #{test.file}:#{test.line_number}: #{existing_issue_found}."
|
37
|
+
break
|
38
|
+
end
|
39
|
+
|
40
|
+
puts "Did not find an existing test health issue of type #{health_problem_type}." unless existing_issue_found
|
41
|
+
|
42
|
+
existing_issue_found
|
43
|
+
end
|
44
|
+
|
45
|
+
def applicable_tests
|
46
|
+
applicable_tests = []
|
47
|
+
|
48
|
+
TestResults::Builder.new(file_glob: files, token: token, project: project).test_results_per_file do |test_results|
|
49
|
+
applicable_tests = test_results.select { |test| test_is_applicable?(test) }
|
50
|
+
end
|
51
|
+
|
52
|
+
applicable_tests
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
attr_reader :health_problem_type
|
58
|
+
|
59
|
+
# Be mindful about the number of tests this method would return,
|
60
|
+
# as we will make at least one API request per test.
|
61
|
+
def test_is_applicable?(test)
|
62
|
+
expected_test_status =
|
63
|
+
case health_problem_type
|
64
|
+
when 'failures'
|
65
|
+
'failed'
|
66
|
+
else
|
67
|
+
'passed'
|
68
|
+
end
|
69
|
+
|
70
|
+
test.status == expected_test_status
|
71
|
+
end
|
72
|
+
|
73
|
+
def search_labels
|
74
|
+
['test', HEALTH_PROBLEM_TYPE_TO_LABEL[health_problem_type]]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
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.
|
4
|
+
version: 2.1.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: 2024-10-
|
11
|
+
date: 2024-10-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: climate_control
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '12.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '12.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: guard-rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -192,6 +192,20 @@ dependencies:
|
|
192
192
|
- - '='
|
193
193
|
- !ruby/object:Gem::Version
|
194
194
|
version: 3.7.0
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: rspec_junit_formatter
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - "~>"
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: 0.6.0
|
202
|
+
type: :development
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - "~>"
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: 0.6.0
|
195
209
|
- !ruby/object:Gem::Dependency
|
196
210
|
name: activesupport
|
197
211
|
requirement: !ruby/object:Gem::Requirement
|
@@ -230,16 +244,22 @@ dependencies:
|
|
230
244
|
name: gitlab
|
231
245
|
requirement: !ruby/object:Gem::Requirement
|
232
246
|
requirements:
|
233
|
-
- - "
|
247
|
+
- - ">="
|
234
248
|
- !ruby/object:Gem::Version
|
235
249
|
version: '4.19'
|
250
|
+
- - "<"
|
251
|
+
- !ruby/object:Gem::Version
|
252
|
+
version: '6.0'
|
236
253
|
type: :runtime
|
237
254
|
prerelease: false
|
238
255
|
version_requirements: !ruby/object:Gem::Requirement
|
239
256
|
requirements:
|
240
|
-
- - "
|
257
|
+
- - ">="
|
241
258
|
- !ruby/object:Gem::Version
|
242
259
|
version: '4.19'
|
260
|
+
- - "<"
|
261
|
+
- !ruby/object:Gem::Version
|
262
|
+
version: '6.0'
|
243
263
|
- !ruby/object:Gem::Dependency
|
244
264
|
name: http
|
245
265
|
requirement: !ruby/object:Gem::Requirement
|
@@ -394,6 +414,7 @@ description: A collection of test-related tools.
|
|
394
414
|
email:
|
395
415
|
- quality@gitlab.com
|
396
416
|
executables:
|
417
|
+
- existing-test-health-issue
|
397
418
|
- failed-test-issues
|
398
419
|
- flaky-test-issues
|
399
420
|
- generate-test-session
|
@@ -423,6 +444,7 @@ files:
|
|
423
444
|
- LICENSE.txt
|
424
445
|
- README.md
|
425
446
|
- Rakefile
|
447
|
+
- exe/existing-test-health-issue
|
426
448
|
- exe/failed-test-issues
|
427
449
|
- exe/flaky-test-issues
|
428
450
|
- exe/generate-test-session
|
@@ -471,6 +493,7 @@ files:
|
|
471
493
|
- lib/gitlab_quality/test_tooling/report/results_in_issues.rb
|
472
494
|
- lib/gitlab_quality/test_tooling/report/results_in_test_cases.rb
|
473
495
|
- lib/gitlab_quality/test_tooling/report/slow_test_issue.rb
|
496
|
+
- lib/gitlab_quality/test_tooling/report/test_health_issue_finder.rb
|
474
497
|
- lib/gitlab_quality/test_tooling/report/update_screenshot_path.rb
|
475
498
|
- lib/gitlab_quality/test_tooling/runtime/env.rb
|
476
499
|
- lib/gitlab_quality/test_tooling/runtime/logger.rb
|
@@ -527,7 +550,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
527
550
|
requirements:
|
528
551
|
- - ">="
|
529
552
|
- !ruby/object:Gem::Version
|
530
|
-
version:
|
553
|
+
version: 3.1.0
|
531
554
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
532
555
|
requirements:
|
533
556
|
- - ">="
|