gitlab_quality-test_tooling 3.22.0 → 3.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a2bfb7b97e0b3a58ac7cbf7cc5f4ab8eb49bf3bf117fce216a34996ed4b4e471
4
- data.tar.gz: 93b21c6cf0608d72292514aa34770db9f7402813ac6b0aeafc383b74f48202b9
3
+ metadata.gz: 635939993ec2f8ac5d2593a070f8494cf9953510c3d2b1f659a86afadd57ff66
4
+ data.tar.gz: 7a75e161d96b24793411864ab93a467bad63bab716d2b1e2a5d1ab272583a9b9
5
5
  SHA512:
6
- metadata.gz: b58cd4d33e53fccf07cd9ca8a1113f0e93a50f33a2217f46c50c3d4ec3e5a1e2f777fbd5546ec20813385a913e989f29b56fbb936be7a5b0bff1fe4f2ffd9231
7
- data.tar.gz: 06a62a7194ebbdc04483a4691eef617c3e2d82d553851f82430ddef4634c0a53f1cb4d3e8cda82fb648bc57ef6a2dda581e4c774cc3eacb622473d7c86d6466d
6
+ metadata.gz: 47a4fb04a69850d455d1dde34a2fdf3026183590d839301c07bad0685c41a8c244e128a40006dd7b90fcf83175e873b01f258945073d03e1cc9c77fe3ee6f37a
7
+ data.tar.gz: bf09187090fd25886a6c4a0eb320b1d431db0df8a6eca497f09b178245ffb9c229a8ba0c84107016a036eb5f095b01e709dfadc136a0393864ef1b45445df65d
data/Gemfile.lock CHANGED
@@ -1,9 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab_quality-test_tooling (3.22.0)
4
+ gitlab_quality-test_tooling (3.23.0)
5
5
  activesupport (>= 7.0)
6
6
  amatch (~> 0.4.1)
7
+ csv (~> 3.0)
7
8
  fog-google (~> 1.25)
8
9
  gitlab (>= 4.19, < 7.0)
9
10
  http (~> 5.0)
@@ -18,30 +19,33 @@ PATH
18
19
  GEM
19
20
  remote: https://rubygems.org/
20
21
  specs:
21
- activesupport (7.1.4)
22
+ activesupport (7.2.4)
22
23
  base64
24
+ benchmark (>= 0.3)
23
25
  bigdecimal
24
- concurrent-ruby (~> 1.0, >= 1.0.2)
25
- connection_pool (>= 2.2.5)
26
+ concurrent-ruby (~> 1.0, >= 1.3.1)
27
+ connection_pool (>= 2.2.5, < 3)
26
28
  drb
27
29
  i18n (>= 1.6, < 2)
28
- minitest (>= 5.1)
29
- mutex_m
30
- tzinfo (~> 2.0)
31
- addressable (2.8.7)
32
- public_suffix (>= 2.0.2, < 7.0)
30
+ logger (>= 1.4.2)
31
+ minitest (>= 5.1, < 6)
32
+ securerandom (>= 0.3)
33
+ tzinfo (~> 2.0, >= 2.0.5)
34
+ addressable (2.9.0)
35
+ public_suffix (>= 2.0.2, < 8.0)
33
36
  amatch (0.4.1)
34
37
  mize
35
38
  tins (~> 1.0)
36
39
  ast (2.4.2)
37
40
  backport (1.2.0)
38
- base64 (0.2.0)
41
+ base64 (0.3.0)
39
42
  benchmark (0.3.0)
40
- bigdecimal (3.1.8)
43
+ bigdecimal (4.1.3)
41
44
  binding_of_caller (1.0.1)
42
45
  debug_inspector (>= 1.2.0)
43
46
  builder (3.3.0)
44
- byebug (11.1.3)
47
+ byebug (13.0.0)
48
+ reline (>= 0.6.0)
45
49
  claide (1.1.0)
46
50
  claide-plugins (0.9.2)
47
51
  cork
@@ -50,14 +54,14 @@ GEM
50
54
  climate_control (1.2.0)
51
55
  coderay (1.1.3)
52
56
  colored2 (3.1.2)
53
- concurrent-ruby (1.3.4)
54
- connection_pool (2.4.1)
57
+ concurrent-ruby (1.3.8)
58
+ connection_pool (2.5.5)
55
59
  cork (0.3.0)
56
60
  colored2 (~> 3.1)
57
61
  crack (1.0.0)
58
62
  bigdecimal
59
63
  rexml
60
- csv (3.3.0)
64
+ csv (3.3.6)
61
65
  danger (9.5.0)
62
66
  claide (~> 1.0)
63
67
  claide-plugins (>= 0.9.2)
@@ -78,18 +82,20 @@ GEM
78
82
  diff-lcs (1.5.1)
79
83
  docile (1.4.1)
80
84
  domain_name (0.6.20240107)
81
- drb (2.2.1)
85
+ drb (2.2.3)
82
86
  e2mmap (0.1.0)
83
87
  excon (1.6.0)
84
88
  logger
85
- faraday (2.12.0)
86
- faraday-net_http (>= 2.0, < 3.4)
89
+ faraday (2.14.4)
90
+ faraday-net_http (>= 2.0, < 3.5)
87
91
  json
88
92
  logger
93
+ faraday-follow_redirects (0.5.0)
94
+ faraday (>= 1, < 3)
89
95
  faraday-http-cache (2.5.1)
90
96
  faraday (>= 0.8)
91
- faraday-net_http (3.3.0)
92
- net-http
97
+ faraday-net_http (3.4.4)
98
+ net-http (~> 0.5)
93
99
  ffi (1.17.0)
94
100
  ffi-compiler (1.3.2)
95
101
  ffi (>= 1.15.5)
@@ -138,16 +144,17 @@ GEM
138
144
  rubocop-rails (~> 2.26.0)
139
145
  rubocop-rspec (~> 3.0.4)
140
146
  rubocop-rspec_rails (~> 2.30.0)
141
- google-apis-compute_v1 (0.108.0)
147
+ google-apis-compute_v1 (0.155.0)
142
148
  google-apis-core (>= 0.15.0, < 2.a)
143
- google-apis-core (0.15.1)
144
- addressable (~> 2.5, >= 2.5.1)
145
- googleauth (~> 1.9)
146
- httpclient (>= 2.8.3, < 3.a)
147
- mini_mime (~> 1.0)
148
- mutex_m
149
+ google-apis-core (1.2.2)
150
+ addressable (~> 2.8, >= 2.8.7)
151
+ faraday (~> 2.13)
152
+ faraday-follow_redirects (~> 0.3)
153
+ googleauth (~> 1.14)
154
+ mini_mime (~> 1.1)
155
+ multi_json (~> 1.11)
149
156
  representable (~> 3.0)
150
- retriable (>= 2.0, < 4.a)
157
+ retriable (>= 3.1, < 5.0)
151
158
  google-apis-dns_v1 (0.44.0)
152
159
  google-apis-core (>= 0.15.0, < 2.a)
153
160
  google-apis-iamcredentials_v1 (0.21.0)
@@ -162,12 +169,14 @@ GEM
162
169
  google-apis-core (>= 0.15.0, < 2.a)
163
170
  google-cloud-env (2.2.1)
164
171
  faraday (>= 1.0, < 3.a)
165
- googleauth (1.11.1)
172
+ google-logging-utils (0.2.0)
173
+ googleauth (1.17.4)
166
174
  faraday (>= 1.0, < 3.a)
167
- google-cloud-env (~> 2.1)
168
- jwt (>= 1.4, < 3.0)
169
- multi_json (~> 1.11)
175
+ google-cloud-env (~> 2.2)
176
+ google-logging-utils (~> 0.1)
177
+ jwt (>= 1.4, < 4.0)
170
178
  os (>= 0.9, < 2.0)
179
+ pstore (~> 0.1)
171
180
  signet (>= 0.16, < 2.a)
172
181
  guard (2.18.1)
173
182
  formatador (>= 0.2.4)
@@ -194,16 +203,16 @@ GEM
194
203
  http-cookie (1.0.7)
195
204
  domain_name (~> 0.5)
196
205
  http-form_data (2.3.0)
197
- httparty (0.22.0)
206
+ httparty (0.24.3)
198
207
  csv
199
208
  mini_mime (>= 1.0.0)
200
209
  multi_xml (>= 0.5.2)
201
- httpclient (2.8.3)
202
- i18n (1.14.6)
210
+ i18n (1.15.2)
203
211
  concurrent-ruby (~> 1.0)
212
+ io-console (0.9.4)
204
213
  jaro_winkler (1.6.0)
205
- json (2.7.2)
206
- jwt (2.9.3)
214
+ json (2.21.2)
215
+ jwt (3.3.0)
207
216
  base64
208
217
  kramdown (2.4.0)
209
218
  rexml
@@ -217,7 +226,7 @@ GEM
217
226
  llhttp-ffi (0.5.0)
218
227
  ffi-compiler (~> 1.0)
219
228
  rake (~> 13.0)
220
- logger (1.6.1)
229
+ logger (1.7.0)
221
230
  lumberjack (1.2.10)
222
231
  method_source (1.1.0)
223
232
  mime-types (3.6.0)
@@ -225,19 +234,18 @@ GEM
225
234
  mime-types-data (~> 3.2015)
226
235
  mime-types-data (3.2024.1001)
227
236
  mini_mime (1.1.5)
228
- mini_portile2 (2.8.7)
229
- minitest (5.25.1)
237
+ mini_portile2 (2.8.9)
238
+ minitest (5.27.0)
230
239
  mize (0.6.0)
231
240
  multi_json (1.15.0)
232
- multi_xml (0.7.1)
233
- bigdecimal (~> 3.1)
234
- mutex_m (0.2.0)
241
+ multi_xml (0.9.1)
242
+ bigdecimal (>= 3.1, < 5)
235
243
  nap (1.1.0)
236
244
  nenv (0.3.0)
237
- net-http (0.4.1)
238
- uri
245
+ net-http (0.9.1)
246
+ uri (>= 0.11.1)
239
247
  netrc (0.11.0)
240
- nokogiri (1.16.7)
248
+ nokogiri (1.19.4)
241
249
  mini_portile2 (~> 2.8.2)
242
250
  racc (~> 1.4)
243
251
  notiffany (0.1.3)
@@ -259,12 +267,13 @@ GEM
259
267
  pry (0.14.2)
260
268
  coderay (~> 1.1)
261
269
  method_source (~> 1.0)
262
- pry-byebug (3.10.1)
263
- byebug (~> 11.0)
264
- pry (>= 0.13, < 0.15)
265
- public_suffix (6.0.1)
270
+ pry-byebug (3.12.0)
271
+ byebug (~> 13.0)
272
+ pry (>= 0.13, < 0.17)
273
+ pstore (0.2.1)
274
+ public_suffix (7.0.5)
266
275
  racc (1.8.1)
267
- rack (3.2.1)
276
+ rack (3.2.7)
268
277
  rainbow (3.1.1)
269
278
  rake (13.2.1)
270
279
  rb-fsevent (0.11.2)
@@ -273,6 +282,8 @@ GEM
273
282
  rbs (2.8.4)
274
283
  rchardet (1.8.0)
275
284
  regexp_parser (2.11.2)
285
+ reline (0.7.0)
286
+ io-console (~> 0.5)
276
287
  representable (3.2.0)
277
288
  declarative (< 0.1.0)
278
289
  trailblazer-option (>= 0.1.1, < 0.2.0)
@@ -285,7 +296,7 @@ GEM
285
296
  retriable (3.1.2)
286
297
  reverse_markdown (2.1.1)
287
298
  nokogiri
288
- rexml (3.3.8)
299
+ rexml (3.4.4)
289
300
  rouge (4.4.0)
290
301
  rspec (3.13.0)
291
302
  rspec-core (~> 3.13.0)
@@ -348,12 +359,12 @@ GEM
348
359
  sawyer (0.9.2)
349
360
  addressable (>= 2.3.5)
350
361
  faraday (>= 0.17.3, < 3)
362
+ securerandom (0.4.1)
351
363
  shellany (0.0.1)
352
- signet (0.19.0)
364
+ signet (0.22.0)
353
365
  addressable (~> 2.8)
354
366
  faraday (>= 0.17.5, < 3.a)
355
- jwt (>= 1.5, < 3.0)
356
- multi_json (~> 1.10)
367
+ jwt (>= 1.5, < 4.0)
357
368
  simplecov (0.22.0)
358
369
  docile (~> 1.1)
359
370
  simplecov-html (~> 0.11)
@@ -397,9 +408,9 @@ GEM
397
408
  unparser (0.6.15)
398
409
  diff-lcs (~> 1.3)
399
410
  parser (>= 3.3.0)
400
- uri (0.13.1)
401
- webmock (3.7.0)
402
- addressable (>= 2.3.6)
411
+ uri (1.1.1)
412
+ webmock (3.26.4)
413
+ addressable (>= 2.8.0)
403
414
  crack (>= 0.3.2)
404
415
  hashdiff (>= 0.4.0, < 2.0.0)
405
416
  yard (0.9.37)
@@ -416,7 +427,7 @@ DEPENDENCIES
416
427
  gitlab_quality-test_tooling!
417
428
  guard-rspec (~> 4.7)
418
429
  lefthook (~> 1.3)
419
- pry-byebug (= 3.10.1)
430
+ pry-byebug (= 3.12.0)
420
431
  rake (~> 13.0)
421
432
  rest-client (~> 2.1.0)
422
433
  rspec (~> 3.12)
@@ -425,7 +436,7 @@ DEPENDENCIES
425
436
  simplecov-cobertura (~> 2.1)
426
437
  solargraph (~> 0.41)
427
438
  timecop (~> 0.9.5)
428
- webmock (= 3.7.0)
439
+ webmock (= 3.26.4)
429
440
 
430
441
  BUNDLED WITH
431
442
  2.7.2
data/README.md CHANGED
@@ -51,6 +51,7 @@ Purpose: Post a message to Slack, and optionally add a test summary table based
51
51
  Usage: exe/post-to-slack [options]
52
52
  -w SLACK_WEBHOOK_URL, Slack webhook URL
53
53
  --slack-webhook-url
54
+ -b, --slack-bot-token TOKEN Slack bot token, used instead of the webhook URL when set
54
55
  -c, --channel CHANNEL Slack channel to post the message to
55
56
  -m, --message MESSAGE Post message to Slack
56
57
  -t FILES, Add a test summary table based on RSpec report files (JUnit XML)
data/exe/post-to-slack CHANGED
@@ -19,6 +19,11 @@ options = OptionParser.new do |opts|
19
19
  params[:slack_webhook_url] = slack_webhook_url
20
20
  end
21
21
 
22
+ # No String type: OptionParser's String rejects "", and CI passes an unset variable as "".
23
+ opts.on('-b', '--slack-bot-token TOKEN', 'Slack bot token, used instead of the webhook URL when set') do |token|
24
+ params[:slack_bot_token] = token unless token.empty?
25
+ end
26
+
22
27
  opts.on('-a', '--gitlab-api-token TOKEN', String, 'GitLab API token') do |token|
23
28
  gitlab_api_token = token unless token.empty?
24
29
  end
@@ -9,9 +9,10 @@
9
9
  -- Parameters use `{name}` braces, substituted as literal text by gsub in
10
10
  -- TestHealthRiskAggregator#build_sql after validation. A typoed placeholder
11
11
  -- silently survives gsub, so match the names exactly.
12
- -- {snapshot_date} date stamp for this run
13
- -- {coverage_start} day of the most recent full per-test capture
14
- -- {risk_window} quarantine/flaky lookback, default '30 DAY'
12
+ -- {snapshot_date} date stamp for this run
13
+ -- {coverage_start} day of the most recent full per-test capture
14
+ -- {risk_window} flaky and ownership lookback, default '30 DAY'
15
+ -- {quarantine_window} default-branch quarantine lookback, fixed at '3 DAY'
15
16
  --
16
17
  -- The INSERT is unconditional. Idempotency comes from the target table's
17
18
  -- ReplacingMergeTree(version) engine keyed by the row tuple: re-runs and
@@ -26,17 +27,16 @@
26
27
  INSERT INTO code_coverage.test_health_risk_per_group
27
28
  WITH
28
29
  quarantine_status AS (
29
- -- `date` is the daily aggregation timestamp on the test_metrics summary
30
- -- view (when the per-test counts were rolled up), not the date a test
31
- -- entered quarantine. We treat any test marked quarantined within the
32
- -- risk window as currently quarantined.
33
- SELECT
34
- test_file,
35
- uniqIfMerge(quarantined_cases) > 0 AS is_quarantined
36
- FROM test_metrics.test_file_quarantine_summary
37
- WHERE date >= now() - INTERVAL {risk_window}
38
- GROUP BY test_file
39
- HAVING is_quarantined
30
+ -- The same source and window the Quarantine score counts from, so both
31
+ -- agree on which specs are quarantined. The MV keeps default-branch
32
+ -- pipelines only; test_file_quarantine_summary also counts stable-branch
33
+ -- and backport pipelines, which keep a spec quarantined long after master
34
+ -- has fixed it.
35
+ SELECT DISTINCT
36
+ file_path AS test_file,
37
+ TRUE AS is_quarantined
38
+ FROM test_metrics.quarantined_tests_hourly_mv
39
+ WHERE hour_timestamp >= now() - INTERVAL {quarantine_window}
40
40
  ),
41
41
  flaky_status AS (
42
42
  SELECT
@@ -39,6 +39,8 @@ module GitlabQuality
39
39
  # denominator built from sparse data.
40
40
  DEFAULT_ANCHOR_LOOKBACK = '21 DAY'
41
41
  DEFAULT_RISK_WINDOW = '30 DAY'
42
+ # Must match the Quarantine score's window in the runbooks Test Health views.
43
+ QUARANTINE_WINDOW = '3 DAY'
42
44
 
43
45
  # `snapshot_date` is YYYY-MM-DD; intervals are `<integer> <unit>`
44
46
  # (singular or plural).
@@ -126,6 +128,7 @@ module GitlabQuality
126
128
  .gsub('{snapshot_date}', validate_date(snapshot_date))
127
129
  .gsub('{coverage_start}', coverage_start)
128
130
  .gsub('{risk_window}', validate_interval(risk_window))
131
+ .gsub('{quarantine_window}', QUARANTINE_WINDOW)
129
132
  end
130
133
 
131
134
  # DateTime/Time `to_s` includes the time portion and is rejected.
@@ -40,13 +40,14 @@ module GitlabQuality
40
40
  end
41
41
 
42
42
  def post_exception_to_slack(error)
43
- return unless ENV['CI_SLACK_WEBHOOK_URL']
43
+ return if ENV.values_at('CI_SLACK_BOT_TOKEN', 'CI_SLACK_WEBHOOK_URL').all? { |value| value.to_s.empty? }
44
44
 
45
45
  pipeline = Runtime::Env.pipeline_from_project_name
46
46
  channel = Runtime::Env.slack_alerts_channel
47
47
 
48
48
  slack_options = {
49
49
  slack_webhook_url: ENV.fetch('CI_SLACK_WEBHOOK_URL', nil),
50
+ slack_bot_token: ENV.fetch('CI_SLACK_BOT_TOKEN', nil),
50
51
  channel: channel,
51
52
  username: "GitLab Quality Test Tooling",
52
53
  icon_emoji: ':ci_failing:',
@@ -59,6 +60,9 @@ module GitlabQuality
59
60
  puts "Posting Slack message to channel: #{channel}"
60
61
 
61
62
  GitlabQuality::TestTooling::Slack::PostToSlack.new(**slack_options).invoke!
63
+ # The caller re-raises the GitLab error after this, so a failed alert must not replace it.
64
+ rescue StandardError => e
65
+ warn("Failed to post the error to Slack: #{e.message}")
62
66
  end
63
67
 
64
68
  def ignore_gitlab_client_exceptions
@@ -122,7 +122,7 @@ module GitlabQuality
122
122
  issue_attrs = {}
123
123
 
124
124
  new_description = new_issue_description(test)
125
- issue_attrs[:description] = new_description if issue.description != new_description
125
+ issue_attrs[:description] = new_description unless issue.description.to_s.include?(new_description.strip)
126
126
 
127
127
  new_labels = up_to_date_labels(test: test, issue: issue).to_a
128
128
  issue_attrs[:add_labels] = new_labels if (new_labels - issue.labels).any?
@@ -8,9 +8,12 @@ module GitlabQuality
8
8
  class PostToSlack
9
9
  MAX_PATTERN_MESSAGE_LENGTH = 150
10
10
  MAX_GROUPED_FAILURES_TO_DISPLAY = 10
11
+ POST_MESSAGE_URL = 'https://slack.com/api/chat.postMessage'
11
12
 
12
- def initialize(slack_webhook_url:, channel:, message:, username:, icon_emoji:, environment_issues_file: nil)
13
+ # Posts with slack_bot_token when it is set and not empty, otherwise to slack_webhook_url.
14
+ def initialize(channel:, message:, username:, icon_emoji:, slack_webhook_url: nil, slack_bot_token: nil, environment_issues_file: nil)
13
15
  @slack_webhook_url = slack_webhook_url
16
+ @slack_bot_token = slack_bot_token
14
17
  @channel = channel
15
18
  @message = message
16
19
  @username = username
@@ -25,6 +28,8 @@ module GitlabQuality
25
28
  params['icon_emoji'] = icon_emoji
26
29
  params['text'] = build_message
27
30
 
31
+ return post_with_token(params) unless slack_bot_token.to_s.empty?
32
+
28
33
  Support::HttpRequest.make_http_request(
29
34
  method: 'post',
30
35
  url: slack_webhook_url,
@@ -35,7 +40,29 @@ module GitlabQuality
35
40
 
36
41
  private
37
42
 
38
- attr_reader :slack_webhook_url, :channel, :message, :username, :icon_emoji, :environment_issues_file
43
+ attr_reader :slack_webhook_url, :slack_bot_token, :channel, :message, :username, :icon_emoji, :environment_issues_file
44
+
45
+ # chat.postMessage answers HTTP 200 with {"ok":false,...} on errors, so the body decides.
46
+ def post_with_token(params)
47
+ response = Support::HttpRequest.make_http_request(
48
+ method: 'post',
49
+ url: POST_MESSAGE_URL,
50
+ params: params,
51
+ headers: { 'Authorization' => "Bearer #{slack_bot_token}" },
52
+ show_response: true
53
+ )
54
+
55
+ raise "Slack did not accept the message: #{response.body}" unless accepted?(response.body.to_s)
56
+
57
+ response
58
+ end
59
+
60
+ def accepted?(body)
61
+ parsed = JSON.parse(body)
62
+ parsed.is_a?(Hash) && parsed['ok'] == true
63
+ rescue JSON::ParserError
64
+ false
65
+ end
39
66
 
40
67
  def build_message
41
68
  messages = []
@@ -295,6 +295,7 @@ module GitlabQuality
295
295
  channel = Runtime::Env.slack_alerts_channel
296
296
  slack_options = {
297
297
  slack_webhook_url: ENV.fetch('CI_SLACK_WEBHOOK_URL', nil),
298
+ slack_bot_token: ENV.fetch('CI_SLACK_BOT_TOKEN', nil),
298
299
  channel: channel,
299
300
  username: "GitLab Quality Test Tooling",
300
301
  icon_emoji: ':warning:',
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GitlabQuality
4
4
  module TestTooling
5
- VERSION = "3.22.0"
5
+ VERSION = "3.23.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: 3.22.0
4
+ version: 3.23.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: 2026-09-09 00:00:00.000000000 Z
11
+ date: 2026-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - '='
88
88
  - !ruby/object:Gem::Version
89
- version: 3.10.1
89
+ version: 3.12.0
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - '='
95
95
  - !ruby/object:Gem::Version
96
- version: 3.10.1
96
+ version: 3.12.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rake
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -212,14 +212,14 @@ dependencies:
212
212
  requirements:
213
213
  - - '='
214
214
  - !ruby/object:Gem::Version
215
- version: 3.7.0
215
+ version: 3.26.4
216
216
  type: :development
217
217
  prerelease: false
218
218
  version_requirements: !ruby/object:Gem::Requirement
219
219
  requirements:
220
220
  - - '='
221
221
  - !ruby/object:Gem::Version
222
- version: 3.7.0
222
+ version: 3.26.4
223
223
  - !ruby/object:Gem::Dependency
224
224
  name: activesupport
225
225
  requirement: !ruby/object:Gem::Requirement
@@ -248,6 +248,20 @@ dependencies:
248
248
  - - "~>"
249
249
  - !ruby/object:Gem::Version
250
250
  version: 0.4.1
251
+ - !ruby/object:Gem::Dependency
252
+ name: csv
253
+ requirement: !ruby/object:Gem::Requirement
254
+ requirements:
255
+ - - "~>"
256
+ - !ruby/object:Gem::Version
257
+ version: '3.0'
258
+ type: :runtime
259
+ prerelease: false
260
+ version_requirements: !ruby/object:Gem::Requirement
261
+ requirements:
262
+ - - "~>"
263
+ - !ruby/object:Gem::Version
264
+ version: '3.0'
251
265
  - !ruby/object:Gem::Dependency
252
266
  name: fog-google
253
267
  requirement: !ruby/object:Gem::Requirement