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 +4 -4
- data/lib/dependabot/docker/update_checker.rb +109 -22
- data/lib/dependabot/docker/utils/credentials_finder.rb +2 -2
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8143dd1e38323ca8d27cb0e0e229af3ae6d7291a945860fe495efb7c68707649
|
4
|
+
data.tar.gz: 37a0909536317744ba22fb800752fe4bc80565571a4f73dcbab7dede3e087d16
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9543d1404fafc293c74e4c6ca95e957ca5a44a1c2a4c6926be8247e3b9f263794afb1ad782793017d801f0e0c1e6b18990e16d841f2e9b64ea432ce21aad4a6b
|
7
|
+
data.tar.gz: 6abbd8372171744ddf1d4317091ca43f9b09262ccb6e0e33777b996dfa90b0fabd42c9565881a990f11a795a1f2a73e8fb84f97a33026cc8cc92cac557034223
|
@@ -1,7 +1,8 @@
|
|
1
|
-
# typed:
|
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
|
-
|
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 ||=
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
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 ||=
|
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 ||=
|
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
|
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.
|
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-
|
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.
|
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.
|
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.
|
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:
|