dependabot-docker 0.296.0 → 0.296.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/dependabot/docker/update_checker.rb +102 -21
- 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,25 +257,28 @@ 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)
|
214
261
|
rescue RestClient::ServerBrokeConnection,
|
215
262
|
RestClient::TooManyRequests
|
216
263
|
raise PrivateSourceBadResponse, registry_hostname
|
217
264
|
end
|
218
265
|
|
266
|
+
sig { returns(T.nilable(String)) }
|
219
267
|
def latest_digest
|
220
268
|
return unless tags_from_registry.map(&:name).include?("latest")
|
221
269
|
|
222
270
|
digest_of("latest")
|
223
271
|
end
|
224
272
|
|
273
|
+
sig { params(tag: String).returns(T.nilable(String)) }
|
225
274
|
def digest_of(tag)
|
226
|
-
@digests ||= {}
|
275
|
+
@digests ||= T.let({}, T.nilable(T::Hash[String, T.nilable(String)]))
|
227
276
|
return @digests[tag] if @digests.key?(tag)
|
228
277
|
|
229
278
|
@digests[tag] = fetch_digest_of(tag)
|
230
279
|
end
|
231
280
|
|
281
|
+
sig { params(tag: String).returns(T.nilable(String)) }
|
232
282
|
def fetch_digest_of(tag)
|
233
283
|
docker_registry_client.manifest_digest(docker_repo_name, tag)&.delete_prefix("sha256:")
|
234
284
|
rescue *transient_docker_errors => e
|
@@ -246,6 +296,7 @@ module Dependabot
|
|
246
296
|
raise PrivateSourceBadResponse, registry_hostname
|
247
297
|
end
|
248
298
|
|
299
|
+
sig { returns(T::Array[T.class_of(StandardError)]) }
|
249
300
|
def transient_docker_errors
|
250
301
|
[
|
251
302
|
RestClient::Exceptions::Timeout,
|
@@ -257,15 +308,16 @@ module Dependabot
|
|
257
308
|
]
|
258
309
|
end
|
259
310
|
|
311
|
+
sig { params(tag: Dependabot::Docker::Tag).returns(T::Boolean) }
|
260
312
|
def prerelease?(tag)
|
261
313
|
return true if tag.looks_like_prerelease?
|
262
314
|
|
263
315
|
# Compare the numeric version against the version of the `latest` tag.
|
264
316
|
return false unless latest_tag
|
265
317
|
|
266
|
-
if comparable_version_from(tag) > comparable_version_from(latest_tag)
|
318
|
+
if comparable_version_from(tag) > comparable_version_from(T.must(latest_tag))
|
267
319
|
Dependabot.logger.info \
|
268
|
-
"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, " \
|
269
321
|
"so dependabot is treating `#{tag.name}` as a pre-release. " \
|
270
322
|
"The `latest` tag needs to point to `#{tag.name}` for Dependabot to consider it."
|
271
323
|
|
@@ -275,10 +327,12 @@ module Dependabot
|
|
275
327
|
end
|
276
328
|
end
|
277
329
|
|
330
|
+
sig { params(tag: Dependabot::Docker::Tag).returns(Dependabot::Version) }
|
278
331
|
def comparable_version_from(tag)
|
279
332
|
version_class.new(tag.numeric_version)
|
280
333
|
end
|
281
334
|
|
335
|
+
sig { returns(T.nilable(String)) }
|
282
336
|
def registry_hostname
|
283
337
|
if dependency.requirements.first&.dig(:source, :registry)
|
284
338
|
return T.must(dependency.requirements.first).dig(:source, :registry)
|
@@ -287,18 +341,25 @@ module Dependabot
|
|
287
341
|
credentials_finder.base_registry
|
288
342
|
end
|
289
343
|
|
344
|
+
sig { returns(T::Boolean) }
|
290
345
|
def using_dockerhub?
|
291
346
|
registry_hostname == "registry.hub.docker.com"
|
292
347
|
end
|
293
348
|
|
349
|
+
sig { returns(T.nilable(Dependabot::Credential)) }
|
294
350
|
def registry_credentials
|
295
351
|
credentials_finder.credentials_for_registry(registry_hostname)
|
296
352
|
end
|
297
353
|
|
354
|
+
sig { returns(Dependabot::Docker::Utils::CredentialsFinder) }
|
298
355
|
def credentials_finder
|
299
|
-
@credentials_finder ||=
|
356
|
+
@credentials_finder ||= T.let(
|
357
|
+
Utils::CredentialsFinder.new(credentials),
|
358
|
+
T.nilable(Dependabot::Docker::Utils::CredentialsFinder)
|
359
|
+
)
|
300
360
|
end
|
301
361
|
|
362
|
+
sig { returns(String) }
|
302
363
|
def docker_repo_name
|
303
364
|
return dependency.name unless using_dockerhub?
|
304
365
|
return dependency.name unless dependency.name.split("/").count < 2
|
@@ -310,8 +371,9 @@ module Dependabot
|
|
310
371
|
DEFAULT_DOCKER_OPEN_TIMEOUT_IN_SECONDS = 2
|
311
372
|
DEFAULT_DOCKER_READ_TIMEOUT_IN_SECONDS = 5
|
312
373
|
|
374
|
+
sig { returns(DockerRegistry2::Registry) }
|
313
375
|
def docker_registry_client
|
314
|
-
@docker_registry_client ||=
|
376
|
+
@docker_registry_client ||= T.let(
|
315
377
|
DockerRegistry2::Registry.new(
|
316
378
|
"https://#{registry_hostname}",
|
317
379
|
user: registry_credentials&.fetch("username", nil),
|
@@ -319,17 +381,28 @@ module Dependabot
|
|
319
381
|
read_timeout: docker_read_timeout_in_seconds,
|
320
382
|
open_timeout: docker_open_timeout_in_seconds,
|
321
383
|
http_options: { proxy: ENV.fetch("HTTPS_PROXY", nil) }
|
322
|
-
)
|
384
|
+
),
|
385
|
+
T.nilable(DockerRegistry2::Registry)
|
386
|
+
)
|
323
387
|
end
|
324
388
|
|
389
|
+
sig { returns(Integer) }
|
325
390
|
def docker_open_timeout_in_seconds
|
326
391
|
ENV.fetch("DEPENDABOT_DOCKER_OPEN_TIMEOUT_IN_SECONDS", DEFAULT_DOCKER_OPEN_TIMEOUT_IN_SECONDS).to_i
|
327
392
|
end
|
328
393
|
|
394
|
+
sig { returns(Integer) }
|
329
395
|
def docker_read_timeout_in_seconds
|
330
396
|
ENV.fetch("DEPENDABOT_DOCKER_READ_TIMEOUT_IN_SECONDS", DEFAULT_DOCKER_READ_TIMEOUT_IN_SECONDS).to_i
|
331
397
|
end
|
332
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
|
333
406
|
def sort_tags(candidate_tags, version_tag)
|
334
407
|
candidate_tags.sort do |tag_a, tag_b|
|
335
408
|
if comparable_version_from(tag_a) > comparable_version_from(tag_b)
|
@@ -346,6 +419,7 @@ module Dependabot
|
|
346
419
|
end
|
347
420
|
end
|
348
421
|
|
422
|
+
sig { params(candidate_tags: T::Array[Dependabot::Docker::Tag]).returns(T::Array[Dependabot::Docker::Tag]) }
|
349
423
|
def filter_ignored(candidate_tags)
|
350
424
|
filtered =
|
351
425
|
candidate_tags
|
@@ -363,22 +437,29 @@ module Dependabot
|
|
363
437
|
filtered
|
364
438
|
end
|
365
439
|
|
440
|
+
sig { params(tags: T::Array[Dependabot::Docker::Tag]).returns(T::Array[Dependabot::Docker::Tag]) }
|
366
441
|
def filter_lower_versions(tags)
|
367
442
|
tags.select do |tag|
|
368
443
|
comparable_version_from(tag) > comparable_version_from(version_tag)
|
369
444
|
end
|
370
445
|
end
|
371
446
|
|
447
|
+
sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
372
448
|
def digest_requirements
|
373
449
|
dependency.requirements.select do |requirement|
|
374
450
|
requirement.dig(:source, :digest)
|
375
451
|
end
|
376
452
|
end
|
377
453
|
|
454
|
+
sig { returns(Dependabot::Docker::Tag) }
|
378
455
|
def version_tag
|
379
|
-
@version_tag ||=
|
456
|
+
@version_tag ||= T.let(
|
457
|
+
Tag.new(T.must(dependency.version)),
|
458
|
+
T.nilable(Dependabot::Docker::Tag)
|
459
|
+
)
|
380
460
|
end
|
381
461
|
end
|
462
|
+
# rubocop:enable Metrics/ClassLength
|
382
463
|
end
|
383
464
|
end
|
384
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.296.
|
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-02-
|
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.296.
|
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.296.
|
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.296.
|
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:
|