gitlab_quality-test_tooling 1.14.0 → 1.17.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.
Files changed (25) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +73 -70
  3. data/exe/flaky-test-issues +4 -4
  4. data/lefthook.yml +13 -0
  5. data/lib/gitlab_quality/test_tooling/gitlab_client/branches_client.rb +1 -1
  6. data/lib/gitlab_quality/test_tooling/gitlab_client/commits_client.rb +6 -4
  7. data/lib/gitlab_quality/test_tooling/gitlab_client/gitlab_client.rb +12 -13
  8. data/lib/gitlab_quality/test_tooling/gitlab_client/issues_client.rb +6 -6
  9. data/lib/gitlab_quality/test_tooling/gitlab_client/merge_requests_client.rb +6 -3
  10. data/lib/gitlab_quality/test_tooling/gitlab_client/merge_requests_dry_client.rb +4 -2
  11. data/lib/gitlab_quality/test_tooling/report/concerns/issue_reports.rb +41 -28
  12. data/lib/gitlab_quality/test_tooling/report/concerns/utils.rb +1 -1
  13. data/lib/gitlab_quality/test_tooling/report/flaky_test_issue.rb +78 -43
  14. data/lib/gitlab_quality/test_tooling/report/generate_test_session.rb +1 -4
  15. data/lib/gitlab_quality/test_tooling/report/knapsack_report_issue.rb +0 -3
  16. data/lib/gitlab_quality/test_tooling/report/relate_failure_issue.rb +4 -8
  17. data/lib/gitlab_quality/test_tooling/report/report_as_issue.rb +5 -3
  18. data/lib/gitlab_quality/test_tooling/report/slow_test_issue.rb +71 -78
  19. data/lib/gitlab_quality/test_tooling/runtime/env.rb +5 -1
  20. data/lib/gitlab_quality/test_tooling/test_meta/processor/add_to_blocking_processor.rb +33 -16
  21. data/lib/gitlab_quality/test_tooling/test_meta/processor/add_to_quarantine_processor.rb +34 -19
  22. data/lib/gitlab_quality/test_tooling/test_meta/processor/meta_processor.rb +21 -0
  23. data/lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb +70 -9
  24. data/lib/gitlab_quality/test_tooling/version.rb +1 -1
  25. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 970354551e0118a942865386f3e844762cf1fdfb06cfc02aa7bca602e55abc8f
4
- data.tar.gz: f512f45f80e5a3949b07a237c1f29c6bc73fcd8e320a92b6b3fcd0a23ccc311f
3
+ metadata.gz: b8709476aafe6dc96d2b49d1d74b18b2e3dbf6c37cb8ebb0acd631d05dbfe2ac
4
+ data.tar.gz: 26d4d54613a522014b5f3b93f38c0cb62027c2e209573727265a5c2b630a6d9d
5
5
  SHA512:
6
- metadata.gz: 639c54db934d3fb5ee5cc57264957a6ffff2714fff9dce6517701b7ff4e5ce74fca87a518f35b1e8d52852952d875f6b9aa45e79a506fbb9416d9712bba2ab95
7
- data.tar.gz: 1dbfcfab9f4161827ae2775a69f6203008cc4ea07dc23424a971c5451a354ebb28d7a698e922aecf8ca321a9612a05e5adf966c1bc0e38686c249aaa87ce6446
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.14.0)
5
- activesupport (>= 6.1, < 7.2)
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
- zeitwerk (~> 2.3)
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.2.1)
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.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.3.0)
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.0)
55
+ git (~> 1.13)
57
56
  kramdown (~> 2.3)
58
57
  kramdown-parser-gfm (~> 1.0)
59
58
  no_proxy_fix
60
- octokit (~> 5.0)
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.5.20190701)
69
- unf (>= 0.0.5, < 1.0.0)
67
+ domain_name (0.6.20240107)
70
68
  e2mmap (0.1.0)
71
- faraday (2.7.4)
72
- faraday-net_http (>= 2.0, < 3.1)
73
- ruby2_keywords (>= 0.0.4)
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.2)
77
- ffi (1.15.5)
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.13.2)
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.8.0)
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.0.0)
93
- rubocop (~> 1.43.0)
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.18)
98
- guard (2.18.0)
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.1)
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.13.0)
122
+ i18n (1.14.1)
125
123
  concurrent-ruby (~> 1.0)
126
- jaro_winkler (1.5.4)
127
- json (2.6.3)
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.3.11)
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.8)
137
+ lumberjack (1.2.10)
140
138
  method_source (1.0.0)
141
- mini_mime (1.1.2)
142
- mini_portile2 (2.8.1)
143
- minitest (5.18.0)
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.14.3)
151
- mini_portile2 (~> 2.8.0)
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 (5.6.1)
156
+ octokit (8.0.0)
157
157
  faraday (>= 1, < 3)
158
158
  sawyer (~> 0.9)
159
159
  open4 (1.3.4)
160
- parallel (1.23.0)
161
- parser (3.2.2.1)
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.1)
176
- racc (1.6.2)
177
- rack (3.0.7)
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.6)
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.8.0)
186
+ regexp_parser (2.9.0)
186
187
  reverse_markdown (2.1.1)
187
188
  nokogiri
188
- rexml (3.2.5)
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.5)
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.0)
213
- rubocop (1.43.0)
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.24.1, < 2.0)
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.28.0)
224
+ rubocop-ast (1.30.0)
224
225
  parser (>= 3.2.1.0)
225
- rubocop-capybara (2.18.0)
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.17.1)
230
- rubocop (>= 1.7.0, < 2.0)
231
- rubocop-ast (>= 0.4.0)
232
- rubocop-rails (2.19.1)
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
- rubocop-rspec (2.20.0)
237
- rubocop (~> 1.33)
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
- ruby2_keywords (0.0.5)
241
- ruby_parser (3.20.3)
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.0)
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.49.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.2.1)
278
- tilt (2.1.0)
279
- timecop (0.9.6)
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
- unf (0.1.4)
285
- unf_ext
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.0)
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.7)
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.2
321
+ 2.5.4
@@ -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 = client.create_commit(project, branch_name, message, [
9
- { action: :update, file_path: file_path, content: new_content }
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 # rubocop:disable Metrics/AbcSize
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
- warn_exception(e)
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
- `#{error_msg}`
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
- client.merge_request_changes(project, merge_request_iid)
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} description: #{description} labels: #{labels}"
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 = %r{(?<job_url>https://(?<host>[\w.]+)/(?<project_path>[\w\-./]+)/-/jobs/\d+)}
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 = /^1\. \d{4}-\d{2}-\d{2}: #{JOB_URL_REGEX} \((?<pipeline_url>.+)\)$/
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 add_report_to_issue_description(issue, test)
21
- issue_description = issue.description
22
-
23
- # We include the number of reports in the header, for visibility.
24
- new_issue_description =
25
- if issue_description.include?('### Reports')
26
- # We count the number of existing reports.
27
- reports_count = issue_description
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
- [new_issue_description, report_list_item(test)].join("\n")
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 report_list_item(test)
53
- "1. #{Time.new.utc.strftime('%F')}: #{test.ci_job_url} (#{ENV.fetch('CI_PIPELINE_URL', 'pipeline url is missing')})"
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(
@@ -16,7 +16,7 @@ module GitlabQuality
16
16
  end
17
17
 
18
18
  def new_issue_title(test)
19
- "#{partial_file_path(test.file)} | #{search_safe(test.name)}".strip
19
+ "[Test] #{partial_file_path(test.file)} | #{search_safe(test.name)}".strip
20
20
  end
21
21
 
22
22
  def partial_file_path(path)