dependabot-docker 0.295.0 → 0.296.1

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: 65df80cd815545e79e5a1fd377eeb5a6d6d96e8624378233d33662b638e32459
4
- data.tar.gz: 7ffe73358a0560061b2a87b7ffc1c1bac17dd3dbcbfbe5e5011708db3485882a
3
+ metadata.gz: 8143dd1e38323ca8d27cb0e0e229af3ae6d7291a945860fe495efb7c68707649
4
+ data.tar.gz: 37a0909536317744ba22fb800752fe4bc80565571a4f73dcbab7dede3e087d16
5
5
  SHA512:
6
- metadata.gz: 8ff3a199e2797341f91e1a4fd3fea47e33dee60bbbf6c766cc2f702ac3760ce651495e402de08201dffb33e3b918910ffb1d96fe3a3df13201832d8038a082c7
7
- data.tar.gz: 45027cd10b10efc6e71fb461a0aa7e73f6b369fbb4caf29993b91c4701ea989bb60395e22afe709ca272274ba414a9c2eccc3f89286fc472108e26b75b9b90b9
6
+ metadata.gz: 9543d1404fafc293c74e4c6ca95e957ca5a44a1c2a4c6926be8247e3b9f263794afb1ad782793017d801f0e0c1e6b18990e16d841f2e9b64ea432ce21aad4a6b
7
+ data.tar.gz: 6abbd8372171744ddf1d4317091ca43f9b09262ccb6e0e33777b996dfa90b0fabd42c9565881a990f11a795a1f2a73e8fb84f97a33026cc8cc92cac557034223
@@ -1,7 +1,8 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "docker_registry2"
5
+ require "sorbet-runtime"
5
6
 
6
7
  require "dependabot/update_checkers"
7
8
  require "dependabot/update_checkers/base"
@@ -14,21 +15,28 @@ require "dependabot/docker/utils/credentials_finder"
14
15
 
15
16
  module Dependabot
16
17
  module Docker
18
+ # rubocop:disable Metrics/ClassLength
17
19
  class UpdateChecker < Dependabot::UpdateCheckers::Base
20
+ extend T::Sig
21
+
22
+ sig { override.returns(T.nilable(T.any(String, Gem::Version))) }
18
23
  def latest_version
19
- latest_version_from(dependency.version)
24
+ latest_version_from(T.must(dependency.version))
20
25
  end
21
26
 
27
+ sig { override.returns(T.nilable(T.any(String, Gem::Version))) }
22
28
  def latest_resolvable_version
23
29
  # Resolvability isn't an issue for Docker containers.
24
30
  latest_version
25
31
  end
26
32
 
33
+ sig { override.returns(T.nilable(String)) }
27
34
  def latest_resolvable_version_with_no_unlock
28
35
  # No concept of "unlocking" for Docker containers
29
36
  dependency.version
30
37
  end
31
38
 
39
+ sig { override.returns(T::Array[T::Hash[Symbol, T.untyped]]) }
32
40
  def updated_requirements
33
41
  dependency.requirements.map do |req|
34
42
  updated_source = req.fetch(:source).dup
@@ -50,16 +58,19 @@ module Dependabot
50
58
 
51
59
  private
52
60
 
61
+ sig { override.returns(T::Boolean) }
53
62
  def latest_version_resolvable_with_full_unlock?
54
63
  # Full unlock checks aren't relevant for Dockerfiles
55
64
  false
56
65
  end
57
66
 
67
+ sig { override.returns(T::Array[Dependabot::Dependency]) }
58
68
  def updated_dependencies_after_full_unlock
59
69
  raise NotImplementedError
60
70
  end
61
71
 
62
- def version_can_update?(*)
72
+ sig { params(requirements_to_unlock: T.nilable(Symbol)).returns(T::Boolean) }
73
+ def version_can_update?(requirements_to_unlock:) # rubocop:disable Lint/UnusedMethodArgument
63
74
  if digest_requirements.any?
64
75
  !digest_up_to_date?
65
76
  else
@@ -67,6 +78,7 @@ module Dependabot
67
78
  end
68
79
  end
69
80
 
81
+ sig { returns(T::Boolean) }
70
82
  def version_up_to_date?
71
83
  if digest_requirements.any?
72
84
  version_tag_up_to_date? && digest_up_to_date?
@@ -75,6 +87,7 @@ module Dependabot
75
87
  end
76
88
  end
77
89
 
90
+ sig { returns(T::Boolean) }
78
91
  def version_tag_up_to_date?
79
92
  version = dependency.version
80
93
  return false unless version
@@ -86,6 +99,7 @@ module Dependabot
86
99
  comparable_version_from(latest_tag) <= comparable_version_from(version_tag)
87
100
  end
88
101
 
102
+ sig { returns(T::Boolean) }
89
103
  def digest_up_to_date?
90
104
  digest_requirements.all? do |req|
91
105
  next true unless updated_digest
@@ -94,21 +108,24 @@ module Dependabot
94
108
  end
95
109
  end
96
110
 
111
+ sig { params(version: String).returns(String) }
97
112
  def latest_version_from(version)
98
113
  latest_tag_from(version).name
99
114
  end
100
115
 
116
+ sig { params(version: String).returns(Dependabot::Docker::Tag) }
101
117
  def latest_tag_from(version)
102
- @tags ||= {}
103
- return @tags[version] if @tags.key?(version)
118
+ @tags ||= T.let({}, T.nilable(T::Hash[String, Dependabot::Docker::Tag]))
119
+ return T.must(@tags[version]) if @tags.key?(version)
104
120
 
105
121
  @tags[version] = fetch_latest_tag(Tag.new(version))
106
122
  end
107
123
 
108
124
  # NOTE: It's important that this *always* returns a tag (even if
109
125
  # it's the existing one) as it is what we later check the digest of.
126
+ sig { params(version_tag: Dependabot::Docker::Tag).returns(Dependabot::Docker::Tag) }
110
127
  def fetch_latest_tag(version_tag)
111
- return Tag.new(latest_digest) if version_tag.digest? && latest_digest
128
+ return Tag.new(T.must(latest_digest)) if version_tag.digest? && latest_digest
112
129
  return version_tag unless version_tag.comparable?
113
130
 
114
131
  # Prune out any downgrade tags before checking for pre-releases
@@ -148,10 +165,18 @@ module Dependabot
148
165
  end
149
166
  end
150
167
 
168
+ sig { params(original_tag: Dependabot::Docker::Tag).returns(T::Array[Dependabot::Docker::Tag]) }
151
169
  def comparable_tags_from_registry(original_tag)
152
170
  tags_from_registry.select { |tag| tag.comparable_to?(original_tag) }
153
171
  end
154
172
 
173
+ sig do
174
+ params(
175
+ candidate_tags: T::Array[Dependabot::Docker::Tag],
176
+ version_tag: Dependabot::Docker::Tag
177
+ )
178
+ .returns(T::Array[Dependabot::Docker::Tag])
179
+ end
155
180
  def remove_version_downgrades(candidate_tags, version_tag)
156
181
  current_version = comparable_version_from(version_tag)
157
182
 
@@ -160,18 +185,33 @@ module Dependabot
160
185
  end
161
186
  end
162
187
 
188
+ sig do
189
+ params(
190
+ candidate_tags: T::Array[Dependabot::Docker::Tag],
191
+ version_tag: Dependabot::Docker::Tag
192
+ )
193
+ .returns(T::Array[Dependabot::Docker::Tag])
194
+ end
163
195
  def remove_prereleases(candidate_tags, version_tag)
164
196
  return candidate_tags if prerelease?(version_tag)
165
197
 
166
198
  candidate_tags.reject { |tag| prerelease?(tag) }
167
199
  end
168
200
 
201
+ sig do
202
+ params(
203
+ candidate_tags: T::Array[Dependabot::Docker::Tag],
204
+ version_tag: Dependabot::Docker::Tag
205
+ )
206
+ .returns(T::Array[Dependabot::Docker::Tag])
207
+ end
169
208
  def remove_precision_changes(candidate_tags, version_tag)
170
209
  candidate_tags.select do |tag|
171
210
  tag.same_precision?(version_tag)
172
211
  end
173
212
  end
174
213
 
214
+ sig { returns(T.nilable(Dependabot::Docker::Tag)) }
175
215
  def latest_tag
176
216
  return unless latest_digest
177
217
 
@@ -182,16 +222,21 @@ module Dependabot
182
222
  .find { |t| digest_of(t.name) == latest_digest }
183
223
  end
184
224
 
225
+ sig { returns(T.nilable(String)) }
185
226
  def updated_digest
186
- @updated_digest ||= if latest_tag_from(dependency.version).digest?
187
- latest_digest
188
- else
189
- digest_of(latest_version)
190
- end
227
+ @updated_digest ||= T.let(
228
+ if latest_tag_from(T.must(dependency.version)).digest?
229
+ latest_digest
230
+ else
231
+ digest_of(T.cast(latest_version, String))
232
+ end,
233
+ T.nilable(String)
234
+ )
191
235
  end
192
236
 
237
+ sig { returns(T::Array[Dependabot::Docker::Tag]) }
193
238
  def tags_from_registry
194
- @tags_from_registry ||=
239
+ @tags_from_registry ||= T.let(
195
240
  begin
196
241
  client = docker_registry_client
197
242
 
@@ -202,7 +247,9 @@ module Dependabot
202
247
  raise if attempt > 3
203
248
 
204
249
  retry
205
- end
250
+ end,
251
+ T.nilable(T::Array[Dependabot::Docker::Tag])
252
+ )
206
253
  rescue DockerRegistry2::RegistryAuthenticationException,
207
254
  RestClient::Forbidden
208
255
  raise PrivateSourceAuthenticationFailure, registry_hostname
@@ -210,36 +257,46 @@ module Dependabot
210
257
  RestClient::Exceptions::ReadTimeout
211
258
  raise if using_dockerhub?
212
259
 
213
- raise PrivateSourceTimedOut, registry_hostname
260
+ raise PrivateSourceTimedOut, T.must(registry_hostname)
261
+ rescue RestClient::ServerBrokeConnection,
262
+ RestClient::TooManyRequests
263
+ raise PrivateSourceBadResponse, registry_hostname
214
264
  end
215
265
 
266
+ sig { returns(T.nilable(String)) }
216
267
  def latest_digest
217
268
  return unless tags_from_registry.map(&:name).include?("latest")
218
269
 
219
270
  digest_of("latest")
220
271
  end
221
272
 
273
+ sig { params(tag: String).returns(T.nilable(String)) }
222
274
  def digest_of(tag)
223
- @digests ||= {}
275
+ @digests ||= T.let({}, T.nilable(T::Hash[String, T.nilable(String)]))
224
276
  return @digests[tag] if @digests.key?(tag)
225
277
 
226
278
  @digests[tag] = fetch_digest_of(tag)
227
279
  end
228
280
 
281
+ sig { params(tag: String).returns(T.nilable(String)) }
229
282
  def fetch_digest_of(tag)
230
283
  docker_registry_client.manifest_digest(docker_repo_name, tag)&.delete_prefix("sha256:")
231
284
  rescue *transient_docker_errors => e
232
285
  attempt ||= 1
233
286
  attempt += 1
234
287
  return if attempt > 3 && e.is_a?(DockerRegistry2::NotFound)
235
- raise if attempt > 3
288
+ raise PrivateSourceBadResponse, registry_hostname if attempt > 3
236
289
 
237
290
  retry
238
291
  rescue DockerRegistry2::RegistryAuthenticationException,
239
292
  RestClient::Forbidden
240
293
  raise PrivateSourceAuthenticationFailure, registry_hostname
294
+ rescue RestClient::ServerBrokeConnection,
295
+ RestClient::TooManyRequests
296
+ raise PrivateSourceBadResponse, registry_hostname
241
297
  end
242
298
 
299
+ sig { returns(T::Array[T.class_of(StandardError)]) }
243
300
  def transient_docker_errors
244
301
  [
245
302
  RestClient::Exceptions::Timeout,
@@ -251,15 +308,16 @@ module Dependabot
251
308
  ]
252
309
  end
253
310
 
311
+ sig { params(tag: Dependabot::Docker::Tag).returns(T::Boolean) }
254
312
  def prerelease?(tag)
255
313
  return true if tag.looks_like_prerelease?
256
314
 
257
315
  # Compare the numeric version against the version of the `latest` tag.
258
316
  return false unless latest_tag
259
317
 
260
- if comparable_version_from(tag) > comparable_version_from(latest_tag)
318
+ if comparable_version_from(tag) > comparable_version_from(T.must(latest_tag))
261
319
  Dependabot.logger.info \
262
- "The `latest` tag points to the same image as the `#{latest_tag.name}` image, " \
320
+ "The `latest` tag points to the same image as the `#{T.must(latest_tag).name}` image, " \
263
321
  "so dependabot is treating `#{tag.name}` as a pre-release. " \
264
322
  "The `latest` tag needs to point to `#{tag.name}` for Dependabot to consider it."
265
323
 
@@ -269,10 +327,12 @@ module Dependabot
269
327
  end
270
328
  end
271
329
 
330
+ sig { params(tag: Dependabot::Docker::Tag).returns(Dependabot::Version) }
272
331
  def comparable_version_from(tag)
273
332
  version_class.new(tag.numeric_version)
274
333
  end
275
334
 
335
+ sig { returns(T.nilable(String)) }
276
336
  def registry_hostname
277
337
  if dependency.requirements.first&.dig(:source, :registry)
278
338
  return T.must(dependency.requirements.first).dig(:source, :registry)
@@ -281,18 +341,25 @@ module Dependabot
281
341
  credentials_finder.base_registry
282
342
  end
283
343
 
344
+ sig { returns(T::Boolean) }
284
345
  def using_dockerhub?
285
346
  registry_hostname == "registry.hub.docker.com"
286
347
  end
287
348
 
349
+ sig { returns(T.nilable(Dependabot::Credential)) }
288
350
  def registry_credentials
289
351
  credentials_finder.credentials_for_registry(registry_hostname)
290
352
  end
291
353
 
354
+ sig { returns(Dependabot::Docker::Utils::CredentialsFinder) }
292
355
  def credentials_finder
293
- @credentials_finder ||= Utils::CredentialsFinder.new(credentials)
356
+ @credentials_finder ||= T.let(
357
+ Utils::CredentialsFinder.new(credentials),
358
+ T.nilable(Dependabot::Docker::Utils::CredentialsFinder)
359
+ )
294
360
  end
295
361
 
362
+ sig { returns(String) }
296
363
  def docker_repo_name
297
364
  return dependency.name unless using_dockerhub?
298
365
  return dependency.name unless dependency.name.split("/").count < 2
@@ -304,8 +371,9 @@ module Dependabot
304
371
  DEFAULT_DOCKER_OPEN_TIMEOUT_IN_SECONDS = 2
305
372
  DEFAULT_DOCKER_READ_TIMEOUT_IN_SECONDS = 5
306
373
 
374
+ sig { returns(DockerRegistry2::Registry) }
307
375
  def docker_registry_client
308
- @docker_registry_client ||=
376
+ @docker_registry_client ||= T.let(
309
377
  DockerRegistry2::Registry.new(
310
378
  "https://#{registry_hostname}",
311
379
  user: registry_credentials&.fetch("username", nil),
@@ -313,17 +381,28 @@ module Dependabot
313
381
  read_timeout: docker_read_timeout_in_seconds,
314
382
  open_timeout: docker_open_timeout_in_seconds,
315
383
  http_options: { proxy: ENV.fetch("HTTPS_PROXY", nil) }
316
- )
384
+ ),
385
+ T.nilable(DockerRegistry2::Registry)
386
+ )
317
387
  end
318
388
 
389
+ sig { returns(Integer) }
319
390
  def docker_open_timeout_in_seconds
320
391
  ENV.fetch("DEPENDABOT_DOCKER_OPEN_TIMEOUT_IN_SECONDS", DEFAULT_DOCKER_OPEN_TIMEOUT_IN_SECONDS).to_i
321
392
  end
322
393
 
394
+ sig { returns(Integer) }
323
395
  def docker_read_timeout_in_seconds
324
396
  ENV.fetch("DEPENDABOT_DOCKER_READ_TIMEOUT_IN_SECONDS", DEFAULT_DOCKER_READ_TIMEOUT_IN_SECONDS).to_i
325
397
  end
326
398
 
399
+ sig do
400
+ params(
401
+ candidate_tags: T::Array[Dependabot::Docker::Tag],
402
+ version_tag: Dependabot::Docker::Tag
403
+ )
404
+ .returns(T::Array[Dependabot::Docker::Tag])
405
+ end
327
406
  def sort_tags(candidate_tags, version_tag)
328
407
  candidate_tags.sort do |tag_a, tag_b|
329
408
  if comparable_version_from(tag_a) > comparable_version_from(tag_b)
@@ -340,6 +419,7 @@ module Dependabot
340
419
  end
341
420
  end
342
421
 
422
+ sig { params(candidate_tags: T::Array[Dependabot::Docker::Tag]).returns(T::Array[Dependabot::Docker::Tag]) }
343
423
  def filter_ignored(candidate_tags)
344
424
  filtered =
345
425
  candidate_tags
@@ -357,22 +437,29 @@ module Dependabot
357
437
  filtered
358
438
  end
359
439
 
440
+ sig { params(tags: T::Array[Dependabot::Docker::Tag]).returns(T::Array[Dependabot::Docker::Tag]) }
360
441
  def filter_lower_versions(tags)
361
442
  tags.select do |tag|
362
443
  comparable_version_from(tag) > comparable_version_from(version_tag)
363
444
  end
364
445
  end
365
446
 
447
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
366
448
  def digest_requirements
367
449
  dependency.requirements.select do |requirement|
368
450
  requirement.dig(:source, :digest)
369
451
  end
370
452
  end
371
453
 
454
+ sig { returns(Dependabot::Docker::Tag) }
372
455
  def version_tag
373
- @version_tag ||= Tag.new(T.must(dependency.version))
456
+ @version_tag ||= T.let(
457
+ Tag.new(T.must(dependency.version)),
458
+ T.nilable(Dependabot::Docker::Tag)
459
+ )
374
460
  end
375
461
  end
462
+ # rubocop:enable Metrics/ClassLength
376
463
  end
377
464
  end
378
465
 
@@ -22,14 +22,14 @@ module Dependabot
22
22
  @credentials = credentials
23
23
  end
24
24
 
25
- sig { params(registry_hostname: String).returns(T.nilable(Dependabot::Credential)) }
25
+ sig { params(registry_hostname: T.nilable(String)).returns(T.nilable(Dependabot::Credential)) }
26
26
  def credentials_for_registry(registry_hostname)
27
27
  registry_details =
28
28
  credentials
29
29
  .select { |cred| cred["type"] == "docker_registry" }
30
30
  .find { |cred| cred.fetch("registry") == registry_hostname }
31
31
  return unless registry_details
32
- return registry_details unless registry_hostname.match?(AWS_ECR_URL)
32
+ return registry_details unless registry_hostname&.match?(AWS_ECR_URL)
33
33
 
34
34
  build_aws_credentials(registry_details)
35
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-docker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.295.0
4
+ version: 0.296.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-01-30 00:00:00.000000000 Z
11
+ date: 2025-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dependabot-common
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.295.0
19
+ version: 0.296.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.295.0
26
+ version: 0.296.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: debug
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -259,7 +259,7 @@ licenses:
259
259
  - MIT
260
260
  metadata:
261
261
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
262
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.295.0
262
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.296.1
263
263
  post_install_message:
264
264
  rdoc_options: []
265
265
  require_paths: