gitlab_quality-test_tooling 1.14.0 → 1.17.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +73 -70
- data/exe/flaky-test-issues +4 -4
- data/lefthook.yml +13 -0
- data/lib/gitlab_quality/test_tooling/gitlab_client/branches_client.rb +1 -1
- data/lib/gitlab_quality/test_tooling/gitlab_client/commits_client.rb +6 -4
- data/lib/gitlab_quality/test_tooling/gitlab_client/gitlab_client.rb +12 -13
- data/lib/gitlab_quality/test_tooling/gitlab_client/issues_client.rb +6 -6
- data/lib/gitlab_quality/test_tooling/gitlab_client/merge_requests_client.rb +6 -3
- data/lib/gitlab_quality/test_tooling/gitlab_client/merge_requests_dry_client.rb +4 -2
- data/lib/gitlab_quality/test_tooling/report/concerns/issue_reports.rb +41 -28
- data/lib/gitlab_quality/test_tooling/report/concerns/utils.rb +1 -1
- data/lib/gitlab_quality/test_tooling/report/flaky_test_issue.rb +78 -43
- data/lib/gitlab_quality/test_tooling/report/generate_test_session.rb +1 -4
- data/lib/gitlab_quality/test_tooling/report/knapsack_report_issue.rb +0 -3
- data/lib/gitlab_quality/test_tooling/report/relate_failure_issue.rb +4 -8
- data/lib/gitlab_quality/test_tooling/report/report_as_issue.rb +5 -3
- data/lib/gitlab_quality/test_tooling/report/slow_test_issue.rb +71 -78
- data/lib/gitlab_quality/test_tooling/runtime/env.rb +5 -1
- data/lib/gitlab_quality/test_tooling/test_meta/processor/add_to_blocking_processor.rb +33 -16
- data/lib/gitlab_quality/test_tooling/test_meta/processor/add_to_quarantine_processor.rb +34 -19
- data/lib/gitlab_quality/test_tooling/test_meta/processor/meta_processor.rb +21 -0
- data/lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb +70 -9
- data/lib/gitlab_quality/test_tooling/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b8709476aafe6dc96d2b49d1d74b18b2e3dbf6c37cb8ebb0acd631d05dbfe2ac
|
4
|
+
data.tar.gz: 26d4d54613a522014b5f3b93f38c0cb62027c2e209573727265a5c2b630a6d9d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 194294ffed245e88a96e35480485f98c1748a8417766cdca1cf737ece2b090a4e29efc444fa449f5f569e292333ba50954f7c07a72fbb2f9225c9195c4b6f411
|
7
|
+
data.tar.gz: 30cc7f3a5da1c15b5c3508e0850c007bddf9f22a85c9ec1361821be7bc330afd3869cd9fe74d3b424afc2d0ad2d180c4c0649b5f502f4740ca68f1b2c8119933
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
gitlab_quality-test_tooling (1.
|
5
|
-
activesupport (>= 6.1, < 7.
|
4
|
+
gitlab_quality-test_tooling (1.17.0)
|
5
|
+
activesupport (>= 6.1, < 7.1)
|
6
6
|
amatch (~> 0.4.1)
|
7
7
|
gitlab (~> 4.19)
|
8
8
|
http (~> 5.0)
|
@@ -21,15 +21,14 @@ GEM
|
|
21
21
|
i18n (>= 1.6, < 2)
|
22
22
|
minitest (>= 5.1)
|
23
23
|
tzinfo (~> 2.0)
|
24
|
-
|
25
|
-
addressable (2.8.4)
|
24
|
+
addressable (2.8.6)
|
26
25
|
public_suffix (>= 2.0.2, < 6.0)
|
27
26
|
amatch (0.4.1)
|
28
27
|
mize
|
29
28
|
tins (~> 1.0)
|
30
29
|
ast (2.4.2)
|
31
30
|
backport (1.2.0)
|
32
|
-
benchmark (0.
|
31
|
+
benchmark (0.3.0)
|
33
32
|
binding_of_caller (1.0.0)
|
34
33
|
debug_inspector (>= 0.0.1)
|
35
34
|
byebug (11.1.3)
|
@@ -41,23 +40,23 @@ GEM
|
|
41
40
|
climate_control (1.2.0)
|
42
41
|
coderay (1.1.3)
|
43
42
|
colored2 (3.1.2)
|
44
|
-
concurrent-ruby (1.2.
|
43
|
+
concurrent-ruby (1.2.3)
|
45
44
|
cork (0.3.0)
|
46
45
|
colored2 (~> 3.1)
|
47
46
|
crack (0.4.5)
|
48
47
|
rexml
|
49
|
-
danger (9.
|
48
|
+
danger (9.4.2)
|
50
49
|
claide (~> 1.0)
|
51
50
|
claide-plugins (>= 0.9.2)
|
52
51
|
colored2 (~> 3.1)
|
53
52
|
cork (~> 0.1)
|
54
53
|
faraday (>= 0.9.0, < 3.0)
|
55
54
|
faraday-http-cache (~> 2.0)
|
56
|
-
git (~> 1.13
|
55
|
+
git (~> 1.13)
|
57
56
|
kramdown (~> 2.3)
|
58
57
|
kramdown-parser-gfm (~> 1.0)
|
59
58
|
no_proxy_fix
|
60
|
-
octokit (
|
59
|
+
octokit (>= 4.0)
|
61
60
|
terminal-table (>= 1, < 4)
|
62
61
|
danger-gitlab (8.0.0)
|
63
62
|
danger
|
@@ -65,37 +64,36 @@ GEM
|
|
65
64
|
debug_inspector (1.2.0)
|
66
65
|
diff-lcs (1.5.0)
|
67
66
|
docile (1.4.0)
|
68
|
-
domain_name (0.
|
69
|
-
unf (>= 0.0.5, < 1.0.0)
|
67
|
+
domain_name (0.6.20240107)
|
70
68
|
e2mmap (0.1.0)
|
71
|
-
faraday (2.
|
72
|
-
faraday-net_http (>= 2.0, < 3.
|
73
|
-
|
74
|
-
faraday-http-cache (2.5.0)
|
69
|
+
faraday (2.9.0)
|
70
|
+
faraday-net_http (>= 2.0, < 3.2)
|
71
|
+
faraday-http-cache (2.5.1)
|
75
72
|
faraday (>= 0.8)
|
76
|
-
faraday-net_http (3.0
|
77
|
-
|
73
|
+
faraday-net_http (3.1.0)
|
74
|
+
net-http
|
75
|
+
ffi (1.16.3)
|
78
76
|
ffi-compiler (1.0.1)
|
79
77
|
ffi (>= 1.0.0)
|
80
78
|
rake
|
81
79
|
formatador (1.1.0)
|
82
|
-
git (1.
|
80
|
+
git (1.19.1)
|
83
81
|
addressable (~> 2.8)
|
84
82
|
rchardet (~> 1.8)
|
85
83
|
gitlab (4.19.0)
|
86
84
|
httparty (~> 0.20)
|
87
85
|
terminal-table (>= 1.5.1)
|
88
|
-
gitlab-dangerfiles (3.
|
86
|
+
gitlab-dangerfiles (3.13.0)
|
89
87
|
danger (>= 8.4.5)
|
90
88
|
danger-gitlab (>= 8.0.0)
|
91
89
|
rake
|
92
|
-
gitlab-styles (10.
|
93
|
-
rubocop (~> 1.
|
90
|
+
gitlab-styles (10.1.0)
|
91
|
+
rubocop (~> 1.50.2)
|
94
92
|
rubocop-graphql (~> 0.18)
|
95
93
|
rubocop-performance (~> 1.15)
|
96
94
|
rubocop-rails (~> 2.17)
|
97
|
-
rubocop-rspec (~> 2.
|
98
|
-
guard (2.18.
|
95
|
+
rubocop-rspec (~> 2.22)
|
96
|
+
guard (2.18.1)
|
99
97
|
formatador (>= 0.2.4)
|
100
98
|
listen (>= 2.7, < 4.0)
|
101
99
|
lumberjack (>= 1.0.12, < 2.0)
|
@@ -109,7 +107,7 @@ GEM
|
|
109
107
|
guard (~> 2.1)
|
110
108
|
guard-compat (~> 1.1)
|
111
109
|
rspec (>= 2.99.0, < 4.0)
|
112
|
-
hashdiff (1.0
|
110
|
+
hashdiff (1.1.0)
|
113
111
|
http (5.1.1)
|
114
112
|
addressable (~> 2.8)
|
115
113
|
http-cookie (~> 1.0)
|
@@ -121,45 +119,48 @@ GEM
|
|
121
119
|
httparty (0.21.0)
|
122
120
|
mini_mime (>= 1.0.0)
|
123
121
|
multi_xml (>= 0.5.2)
|
124
|
-
i18n (1.
|
122
|
+
i18n (1.14.1)
|
125
123
|
concurrent-ruby (~> 1.0)
|
126
|
-
jaro_winkler (1.5.
|
127
|
-
json (2.
|
124
|
+
jaro_winkler (1.5.6)
|
125
|
+
json (2.7.1)
|
128
126
|
kramdown (2.4.0)
|
129
127
|
rexml
|
130
128
|
kramdown-parser-gfm (1.1.0)
|
131
129
|
kramdown (~> 2.0)
|
132
|
-
lefthook (1.
|
130
|
+
lefthook (1.6.1)
|
133
131
|
listen (3.8.0)
|
134
132
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
135
133
|
rb-inotify (~> 0.9, >= 0.9.10)
|
136
134
|
llhttp-ffi (0.4.0)
|
137
135
|
ffi-compiler (~> 1.0)
|
138
136
|
rake (~> 13.0)
|
139
|
-
lumberjack (1.2.
|
137
|
+
lumberjack (1.2.10)
|
140
138
|
method_source (1.0.0)
|
141
|
-
mini_mime (1.1.
|
142
|
-
mini_portile2 (2.8.
|
143
|
-
minitest (5.
|
139
|
+
mini_mime (1.1.5)
|
140
|
+
mini_portile2 (2.8.5)
|
141
|
+
minitest (5.21.2)
|
144
142
|
mize (0.4.1)
|
145
143
|
protocol (~> 2.0)
|
146
144
|
multi_xml (0.6.0)
|
147
145
|
nap (1.1.0)
|
148
146
|
nenv (0.3.0)
|
147
|
+
net-http (0.4.1)
|
148
|
+
uri
|
149
149
|
no_proxy_fix (0.1.2)
|
150
|
-
nokogiri (1.
|
151
|
-
mini_portile2 (~> 2.8.
|
150
|
+
nokogiri (1.16.0)
|
151
|
+
mini_portile2 (~> 2.8.2)
|
152
152
|
racc (~> 1.4)
|
153
153
|
notiffany (0.1.3)
|
154
154
|
nenv (~> 0.1)
|
155
155
|
shellany (~> 0.0)
|
156
|
-
octokit (
|
156
|
+
octokit (8.0.0)
|
157
157
|
faraday (>= 1, < 3)
|
158
158
|
sawyer (~> 0.9)
|
159
159
|
open4 (1.3.4)
|
160
|
-
parallel (1.
|
161
|
-
parser (3.
|
160
|
+
parallel (1.24.0)
|
161
|
+
parser (3.3.0.5)
|
162
162
|
ast (~> 2.4.1)
|
163
|
+
racc
|
163
164
|
proc_to_ast (0.1.0)
|
164
165
|
coderay
|
165
166
|
parser
|
@@ -172,20 +173,20 @@ GEM
|
|
172
173
|
pry-byebug (3.10.1)
|
173
174
|
byebug (~> 11.0)
|
174
175
|
pry (>= 0.13, < 0.15)
|
175
|
-
public_suffix (5.0.
|
176
|
-
racc (1.
|
177
|
-
rack (3.0.
|
176
|
+
public_suffix (5.0.4)
|
177
|
+
racc (1.7.3)
|
178
|
+
rack (3.0.8)
|
178
179
|
rainbow (3.1.1)
|
179
|
-
rake (13.0
|
180
|
+
rake (13.1.0)
|
180
181
|
rb-fsevent (0.11.2)
|
181
182
|
rb-inotify (0.10.1)
|
182
183
|
ffi (~> 1.0)
|
183
184
|
rbs (2.8.4)
|
184
185
|
rchardet (1.8.0)
|
185
|
-
regexp_parser (2.
|
186
|
+
regexp_parser (2.9.0)
|
186
187
|
reverse_markdown (2.1.1)
|
187
188
|
nokogiri
|
188
|
-
rexml (3.2.
|
189
|
+
rexml (3.2.6)
|
189
190
|
rspec (3.12.0)
|
190
191
|
rspec-core (~> 3.12.0)
|
191
192
|
rspec-expectations (~> 3.12.0)
|
@@ -195,7 +196,7 @@ GEM
|
|
195
196
|
rspec-expectations (3.12.3)
|
196
197
|
diff-lcs (>= 1.2.0, < 2.0)
|
197
198
|
rspec-support (~> 3.12.0)
|
198
|
-
rspec-mocks (3.12.
|
199
|
+
rspec-mocks (3.12.6)
|
199
200
|
diff-lcs (>= 1.2.0, < 2.0)
|
200
201
|
rspec-support (~> 3.12.0)
|
201
202
|
rspec-parameterized (1.0.0)
|
@@ -209,41 +210,45 @@ GEM
|
|
209
210
|
rspec-parameterized-table_syntax (1.0.1)
|
210
211
|
binding_of_caller
|
211
212
|
rspec-parameterized-core (< 2)
|
212
|
-
rspec-support (3.12.
|
213
|
-
rubocop (1.
|
213
|
+
rspec-support (3.12.1)
|
214
|
+
rubocop (1.50.2)
|
214
215
|
json (~> 2.3)
|
215
216
|
parallel (~> 1.10)
|
216
217
|
parser (>= 3.2.0.0)
|
217
218
|
rainbow (>= 2.2.2, < 4.0)
|
218
219
|
regexp_parser (>= 1.8, < 3.0)
|
219
220
|
rexml (>= 3.2.5, < 4.0)
|
220
|
-
rubocop-ast (>= 1.
|
221
|
+
rubocop-ast (>= 1.28.0, < 2.0)
|
221
222
|
ruby-progressbar (~> 1.7)
|
222
223
|
unicode-display_width (>= 2.4.0, < 3.0)
|
223
|
-
rubocop-ast (1.
|
224
|
+
rubocop-ast (1.30.0)
|
224
225
|
parser (>= 3.2.1.0)
|
225
|
-
rubocop-capybara (2.
|
226
|
+
rubocop-capybara (2.20.0)
|
227
|
+
rubocop (~> 1.41)
|
228
|
+
rubocop-factory_bot (2.25.1)
|
226
229
|
rubocop (~> 1.41)
|
227
230
|
rubocop-graphql (0.19.0)
|
228
231
|
rubocop (>= 0.87, < 2)
|
229
|
-
rubocop-performance (1.
|
230
|
-
rubocop (>= 1.
|
231
|
-
rubocop-ast (>=
|
232
|
-
rubocop-rails (2.
|
232
|
+
rubocop-performance (1.20.2)
|
233
|
+
rubocop (>= 1.48.1, < 2.0)
|
234
|
+
rubocop-ast (>= 1.30.0, < 2.0)
|
235
|
+
rubocop-rails (2.23.1)
|
233
236
|
activesupport (>= 4.2.0)
|
234
237
|
rack (>= 1.1)
|
235
238
|
rubocop (>= 1.33.0, < 2.0)
|
236
|
-
|
237
|
-
|
239
|
+
rubocop-ast (>= 1.30.0, < 2.0)
|
240
|
+
rubocop-rspec (2.26.1)
|
241
|
+
rubocop (~> 1.40)
|
238
242
|
rubocop-capybara (~> 2.17)
|
243
|
+
rubocop-factory_bot (~> 2.22)
|
239
244
|
ruby-progressbar (1.13.0)
|
240
|
-
|
241
|
-
|
245
|
+
ruby_parser (3.21.0)
|
246
|
+
racc (~> 1.5)
|
242
247
|
sexp_processor (~> 4.16)
|
243
248
|
sawyer (0.9.2)
|
244
249
|
addressable (>= 2.3.5)
|
245
250
|
faraday (>= 0.17.3, < 3)
|
246
|
-
sexp_processor (4.17.
|
251
|
+
sexp_processor (4.17.1)
|
247
252
|
shellany (0.0.1)
|
248
253
|
simplecov (0.22.0)
|
249
254
|
docile (~> 1.1)
|
@@ -254,7 +259,7 @@ GEM
|
|
254
259
|
simplecov (~> 0.19)
|
255
260
|
simplecov-html (0.12.3)
|
256
261
|
simplecov_json_formatter (0.1.4)
|
257
|
-
solargraph (0.
|
262
|
+
solargraph (0.50.0)
|
258
263
|
backport (~> 1.2)
|
259
264
|
benchmark
|
260
265
|
bundler (~> 2.0)
|
@@ -274,26 +279,24 @@ GEM
|
|
274
279
|
table_print (1.5.7)
|
275
280
|
terminal-table (3.0.2)
|
276
281
|
unicode-display_width (>= 1.1.1, < 3)
|
277
|
-
thor (1.
|
278
|
-
tilt (2.
|
279
|
-
timecop (0.9.
|
282
|
+
thor (1.3.0)
|
283
|
+
tilt (2.3.0)
|
284
|
+
timecop (0.9.8)
|
280
285
|
tins (1.32.1)
|
281
286
|
sync
|
282
287
|
tzinfo (2.0.6)
|
283
288
|
concurrent-ruby (~> 1.0)
|
284
|
-
|
285
|
-
|
286
|
-
unf_ext (0.0.8.2)
|
287
|
-
unicode-display_width (2.4.2)
|
288
|
-
unparser (0.6.8)
|
289
|
+
unicode-display_width (2.5.0)
|
290
|
+
unparser (0.6.12)
|
289
291
|
diff-lcs (~> 1.3)
|
290
|
-
parser (>= 3.2.
|
292
|
+
parser (>= 3.2.2.4)
|
293
|
+
uri (0.13.0)
|
291
294
|
webmock (3.7.0)
|
292
295
|
addressable (>= 2.3.6)
|
293
296
|
crack (>= 0.3.2)
|
294
297
|
hashdiff (>= 0.4.0, < 2.0.0)
|
295
298
|
yard (0.9.34)
|
296
|
-
zeitwerk (2.6.
|
299
|
+
zeitwerk (2.6.12)
|
297
300
|
|
298
301
|
PLATFORMS
|
299
302
|
ruby
|
@@ -315,4 +318,4 @@ DEPENDENCIES
|
|
315
318
|
webmock (= 3.7.0)
|
316
319
|
|
317
320
|
BUNDLED WITH
|
318
|
-
2.4
|
321
|
+
2.5.4
|
data/exe/flaky-test-issues
CHANGED
@@ -19,10 +19,6 @@ options = OptionParser.new do |opts|
|
|
19
19
|
params[:project] = project
|
20
20
|
end
|
21
21
|
|
22
|
-
opts.on('-m', '--merge_request_iid MERGE_REQUEST_IID', String, 'An integer merge request IID') do |merge_request_iid|
|
23
|
-
params[:merge_request_iid] = merge_request_iid
|
24
|
-
end
|
25
|
-
|
26
22
|
opts.on('--base-issue-labels BASE_ISSUE_LABELS', String,
|
27
23
|
'Comma-separated labels (without tilde) to add to new flaky test issues') do |base_issue_labels|
|
28
24
|
params[:base_issue_labels] = base_issue_labels.split(',')
|
@@ -32,6 +28,10 @@ options = OptionParser.new do |opts|
|
|
32
28
|
params[:token] = token
|
33
29
|
end
|
34
30
|
|
31
|
+
opts.on('-r', '--related-issues-file RELATED_ISSUES_FILE', String, 'The file path for the related issues') do |related_issues_file|
|
32
|
+
params[:related_issues_file] = related_issues_file
|
33
|
+
end
|
34
|
+
|
35
35
|
opts.on('--dry-run', "Perform a dry-run (don't create issues)") do
|
36
36
|
params[:dry_run] = true
|
37
37
|
end
|
data/lefthook.yml
CHANGED
@@ -13,3 +13,16 @@ pre-push:
|
|
13
13
|
rubocop:
|
14
14
|
run: bundle exec rubocop
|
15
15
|
glob: '*.rb'
|
16
|
+
|
17
|
+
# Changelog git trailer for the first commit of the branch
|
18
|
+
changelog-on-first-commit:
|
19
|
+
run: |
|
20
|
+
first_commit_message=$(git log --format=%B -n 1 $(git log main..HEAD --pretty=format:"%h" | tail -1))
|
21
|
+
if ! echo ${first_commit_message} | grep "Changelog:"; then
|
22
|
+
echo Could not find a Changelog: git trailer on the first commit for this branch.
|
23
|
+
echo
|
24
|
+
echo Please add a trailer by amending the git commit message.
|
25
|
+
echo
|
26
|
+
echo See https://docs.gitlab.com/ee/development/changelog.html#overview for more info.
|
27
|
+
exit 1
|
28
|
+
fi
|
@@ -9,7 +9,7 @@ module GitlabQuality
|
|
9
9
|
client.create_branch(project, branch_name, ref)
|
10
10
|
end
|
11
11
|
|
12
|
-
Runtime::Logger.debug("Created branch #{branch['name']} (#{branch['web_url']})")
|
12
|
+
Runtime::Logger.debug("Created branch #{branch['name']} (#{branch['web_url']})") if branch
|
13
13
|
branch
|
14
14
|
end
|
15
15
|
end
|
@@ -5,11 +5,13 @@ module GitlabQuality
|
|
5
5
|
module GitlabClient
|
6
6
|
class CommitsClient < GitlabClient
|
7
7
|
def create(branch_name, file_path, new_content, message)
|
8
|
-
commit =
|
9
|
-
|
10
|
-
|
8
|
+
commit = handle_gitlab_client_exceptions do
|
9
|
+
client.create_commit(project, branch_name, message, [
|
10
|
+
{ action: :update, file_path: file_path, content: new_content }
|
11
|
+
])
|
12
|
+
end
|
11
13
|
|
12
|
-
Runtime::Logger.debug("Created commit #{commit['id']} (#{commit['web_url']}) on #{branch_name}")
|
14
|
+
Runtime::Logger.debug("Created commit #{commit['id']} (#{commit['web_url']}) on #{branch_name}") if commit
|
13
15
|
commit
|
14
16
|
end
|
15
17
|
end
|
@@ -15,24 +15,32 @@ module GitlabQuality
|
|
15
15
|
@retry_backoff = 0
|
16
16
|
end
|
17
17
|
|
18
|
-
def handle_gitlab_client_exceptions
|
18
|
+
def handle_gitlab_client_exceptions
|
19
19
|
yield
|
20
20
|
rescue Gitlab::Error::NotFound
|
21
21
|
# This error could be raised in assert_user_permission!
|
22
22
|
# If so, we want it to terminate at that point
|
23
23
|
raise
|
24
24
|
rescue SystemCallError, OpenSSL::SSL::SSLError, Net::OpenTimeout, Net::ReadTimeout,
|
25
|
-
Gitlab::Error::InternalServerError, Gitlab::Error::Parsing => e
|
25
|
+
Gitlab::Error::InternalServerError, Gitlab::Error::BadRequest, Gitlab::Error::ResponseError, Gitlab::Error::Parsing => e
|
26
26
|
@retry_backoff += RETRY_BACK_OFF_DELAY
|
27
27
|
|
28
28
|
raise if @retry_backoff > RETRY_BACK_OFF_DELAY * MAX_RETRY_ATTEMPTS
|
29
29
|
|
30
|
-
|
30
|
+
warn("#{error.class.name} #{error.message}")
|
31
31
|
warn("Sleeping for #{@retry_backoff} seconds before retrying...")
|
32
32
|
sleep @retry_backoff
|
33
33
|
|
34
34
|
retry
|
35
35
|
rescue StandardError => e
|
36
|
+
post_exception_to_slack(e) if Runtime::Env.ci_commit_ref_name == Runtime::Env.default_branch
|
37
|
+
|
38
|
+
raise e
|
39
|
+
end
|
40
|
+
|
41
|
+
def post_exception_to_slack(error)
|
42
|
+
return unless ENV['CI_SLACK_WEBHOOK_URL']
|
43
|
+
|
36
44
|
pipeline = Runtime::Env.pipeline_from_project_name
|
37
45
|
channel = case pipeline
|
38
46
|
when "canary"
|
@@ -42,9 +50,6 @@ module GitlabQuality
|
|
42
50
|
else
|
43
51
|
"qa-#{pipeline}"
|
44
52
|
end
|
45
|
-
error_msg = warn_exception(e)
|
46
|
-
|
47
|
-
return unless Runtime::Env.ci_commit_ref_name == Runtime::Env.default_branch
|
48
53
|
|
49
54
|
slack_options = {
|
50
55
|
slack_webhook_url: ENV.fetch('CI_SLACK_WEBHOOK_URL', nil),
|
@@ -54,7 +59,7 @@ module GitlabQuality
|
|
54
59
|
message: <<~MSG
|
55
60
|
An unexpected error occurred while reporting test results in issues.
|
56
61
|
The error occurred in job: #{Runtime::Env.ci_job_url}
|
57
|
-
`#{
|
62
|
+
`#{error.class.name} #{error.message}`
|
58
63
|
MSG
|
59
64
|
}
|
60
65
|
puts "Posting Slack message to channel: #{channel}"
|
@@ -79,12 +84,6 @@ module GitlabQuality
|
|
79
84
|
private_token: token
|
80
85
|
)
|
81
86
|
end
|
82
|
-
|
83
|
-
def warn_exception(error)
|
84
|
-
error_msg = "#{error.class.name} #{error.message}"
|
85
|
-
warn(error_msg)
|
86
|
-
error_msg
|
87
|
-
end
|
88
87
|
end
|
89
88
|
end
|
90
89
|
end
|
@@ -48,6 +48,12 @@ module GitlabQuality
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
def find_issue_notes(iid:)
|
52
|
+
handle_gitlab_client_exceptions do
|
53
|
+
client.issue_notes(project, iid, order_by: 'created_at', sort: 'asc').auto_paginate
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
51
57
|
def find_issue_discussions(iid:)
|
52
58
|
handle_gitlab_client_exceptions do
|
53
59
|
client.issue_discussions(project, iid, order_by: 'created_at', sort: 'asc').auto_paginate
|
@@ -75,12 +81,6 @@ module GitlabQuality
|
|
75
81
|
end
|
76
82
|
end
|
77
83
|
|
78
|
-
def find_issue_notes(iid:)
|
79
|
-
handle_gitlab_client_exceptions do
|
80
|
-
client.issue_notes(project, iid, order_by: 'created_at', sort: 'asc')&.auto_paginate
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
84
|
def create_issue_note(iid:, note:)
|
85
85
|
handle_gitlab_client_exceptions do
|
86
86
|
client.create_issue_note(project, iid, note)
|
@@ -5,10 +5,12 @@ module GitlabQuality
|
|
5
5
|
module GitlabClient
|
6
6
|
class MergeRequestsClient < GitlabClient
|
7
7
|
def find_merge_request_changes(merge_request_iid:)
|
8
|
-
|
8
|
+
handle_gitlab_client_exceptions do
|
9
|
+
client.merge_request_changes(project, merge_request_iid)
|
10
|
+
end
|
9
11
|
end
|
10
12
|
|
11
|
-
def create_merge_request(title:, source_branch:, target_branch:, description:, labels:, assignee_id: nil)
|
13
|
+
def create_merge_request(title:, source_branch:, target_branch:, description:, labels:, assignee_id: nil, reviewer_ids: [])
|
12
14
|
attrs = {
|
13
15
|
source_branch: source_branch,
|
14
16
|
target_branch: target_branch,
|
@@ -16,7 +18,8 @@ module GitlabQuality
|
|
16
18
|
labels: labels,
|
17
19
|
assignee_id: assignee_id,
|
18
20
|
squash: true,
|
19
|
-
remove_source_branch: true
|
21
|
+
remove_source_branch: true,
|
22
|
+
reviewer_ids: reviewer_ids
|
20
23
|
}.compact
|
21
24
|
|
22
25
|
merge_request = handle_gitlab_client_exceptions do
|
@@ -26,9 +26,11 @@ module GitlabQuality
|
|
26
26
|
puts "The following note would have been updated id: #{id} with body: #{note} for mr_iid: #{merge_request_iid}"
|
27
27
|
end
|
28
28
|
|
29
|
-
def create_merge_request(title:, source_branch:, target_branch:, description:, labels:)
|
29
|
+
def create_merge_request(title:, source_branch:, target_branch:, description:, labels:, assignee_id:, reviewer_ids:)
|
30
30
|
puts "A merge request would be created with title: #{title} " \
|
31
|
-
"source_branch: #{source_branch} target_branch: #{target_branch}
|
31
|
+
"source_branch: #{source_branch} target_branch: #{target_branch} " \
|
32
|
+
"description: #{description} labels: #{labels}, assignee_id: #{assignee_id}" \
|
33
|
+
"reviewer_ids: #{reviewer_ids}"
|
32
34
|
end
|
33
35
|
end
|
34
36
|
end
|
@@ -1,13 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'active_support/core_ext/object/blank'
|
4
|
+
|
3
5
|
module GitlabQuality
|
4
6
|
module TestTooling
|
5
7
|
module Report
|
6
8
|
module Concerns
|
7
9
|
module IssueReports
|
8
|
-
JOB_URL_REGEX
|
10
|
+
JOB_URL_REGEX = %r{(?<job_url>https://(?<host>[\w.]+)/(?<project_path>[\w\-./]+)/-/jobs/\d+)}
|
9
11
|
FAILED_JOB_DESCRIPTION_REGEX = /First happened in #{JOB_URL_REGEX}\./m
|
10
|
-
REPORT_ITEM_REGEX
|
12
|
+
REPORT_ITEM_REGEX = /^1\. \d{4}-\d{2}-\d{2}: #{JOB_URL_REGEX} \((?<pipeline_url>\S+)\)/
|
13
|
+
LATEST_REPORTS_TO_SHOW = 10
|
11
14
|
|
12
15
|
def initial_reports_section(test)
|
13
16
|
<<~REPORTS
|
@@ -17,22 +20,21 @@ module GitlabQuality
|
|
17
20
|
REPORTS
|
18
21
|
end
|
19
22
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
.scan(REPORT_ITEM_REGEX)
|
29
|
-
.size.to_i + 1
|
30
|
-
issue_description.sub(/^### Reports.*$/, "### Reports (#{reports_count})")
|
31
|
-
else # For issue with the legacy format, we add the Reports section
|
32
|
-
update_legacy_issue_description(issue_description)
|
33
|
-
end
|
23
|
+
def increment_reports(
|
24
|
+
current_reports_content:,
|
25
|
+
test:,
|
26
|
+
reports_section_header: '### Reports',
|
27
|
+
item_extra_content: nil,
|
28
|
+
reports_extra_content: nil)
|
29
|
+
preserved_content = current_reports_content.split(reports_section_header).first&.strip
|
30
|
+
reports = report_lines(current_reports_content) + [report_list_item(test, item_extra_content: item_extra_content)]
|
34
31
|
|
35
|
-
[
|
32
|
+
[
|
33
|
+
preserved_content,
|
34
|
+
"#{reports_section_header} (#{reports.size})",
|
35
|
+
reports_list(reports),
|
36
|
+
reports_extra_content
|
37
|
+
].reject(&:blank?).compact.join("\n\n")
|
36
38
|
end
|
37
39
|
|
38
40
|
def failed_issue_job_url(issue)
|
@@ -49,8 +51,28 @@ module GitlabQuality
|
|
49
51
|
|
50
52
|
private
|
51
53
|
|
52
|
-
def
|
53
|
-
|
54
|
+
def report_lines(content)
|
55
|
+
content.lines.grep(REPORT_ITEM_REGEX).map(&:strip)
|
56
|
+
end
|
57
|
+
|
58
|
+
def reports_list(reports)
|
59
|
+
sorted_reports = reports.sort.reverse
|
60
|
+
|
61
|
+
if sorted_reports.size > LATEST_REPORTS_TO_SHOW
|
62
|
+
[
|
63
|
+
"Last 10 reports:",
|
64
|
+
sorted_reports[...LATEST_REPORTS_TO_SHOW].join("\n"),
|
65
|
+
"<details><summary>See #{sorted_reports.size - LATEST_REPORTS_TO_SHOW} more reports</summary>",
|
66
|
+
sorted_reports[LATEST_REPORTS_TO_SHOW..].join("\n"),
|
67
|
+
"</details>"
|
68
|
+
].join("\n\n")
|
69
|
+
else
|
70
|
+
sorted_reports.join("\n")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def report_list_item(test, item_extra_content: nil)
|
75
|
+
"1. #{Time.new.utc.strftime('%F')}: #{test.ci_job_url} (#{ENV.fetch('CI_PIPELINE_URL', 'pipeline url is missing')}) #{item_extra_content}".strip
|
54
76
|
end
|
55
77
|
|
56
78
|
def job_urls_from_description(issue_description, regex)
|
@@ -60,15 +82,6 @@ module GitlabQuality
|
|
60
82
|
end
|
61
83
|
end
|
62
84
|
|
63
|
-
def update_legacy_issue_description(issue_description)
|
64
|
-
test_captures = issue_description.scan(JOB_URL_REGEX)
|
65
|
-
reports_count = test_captures.size.to_i + 1
|
66
|
-
|
67
|
-
updated_description = "#{issue_description}\n\n### Reports (#{reports_count})\n"
|
68
|
-
updated_description = [updated_description, *test_captures_to_report_items(test_captures)].join("\n") unless test_captures.empty?
|
69
|
-
updated_description
|
70
|
-
end
|
71
|
-
|
72
85
|
def test_captures_to_report_items(test_captures)
|
73
86
|
test_captures.map do |ci_job_url, _, _|
|
74
87
|
report_list_item(GitlabQuality::TestTooling::TestResult::JsonTestResult.new(
|