dependabot-docker 0.390.0 → 0.391.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: 5dab05a06765637bf76bff8f754c5139cf9652f0fd64794200b98cde43a05008
4
- data.tar.gz: 750a5ecbaf42000e3aee5b91cf0e6563918c1e97f5bfd67c000a73cad2266d59
3
+ metadata.gz: 8f8970643afb19fb1fcb8400d78829bcd94dd9938a0b62bb8272117146d60756
4
+ data.tar.gz: 52de182a249408f725617f9a4e5bc1453c1ab630760340d47e7d52d862f9c6ba
5
5
  SHA512:
6
- metadata.gz: f8f5801aa19d4e071b6d838e4c96a8ba395a1c4277fb0059201878df3808506997eab692964185f736dd232244a5f5d1d29882ce58cb6adda14e67575a7d42ca
7
- data.tar.gz: e23963530ca9eedab7de6ffcfa2ecff538a502784d308c8b305645eb60e23ce4b2ce2328ce4c747daadd8a4730879f1e9c62b5aa46e028aebecb35b6439899cc
6
+ metadata.gz: 5d107f6d0903a0c7682866f5a754d3671505c9d515f903601d9cf7259c63f9a65cef54939c34672f77d35e18ca348176071d36702eb6fdd3ebcfd97ddaaee3b6
7
+ data.tar.gz: d5cdf57817917e7bab0042bb924d2f6645de1588dc630d2e14b345e889861821c4e95b0a1e0b7ea9319211dee93b74ed97c3bd46e0934b3201ba5d84ed78b117
@@ -27,8 +27,11 @@ module Dependabot
27
27
  def look_up_source
28
28
  return if dependency.requirements.empty?
29
29
 
30
- new_source = dependency.requirements.first&.fetch(:source)
31
- return unless new_source && new_source[:registry] && (new_source[:tag] || new_source[:digest])
30
+ requirement = dependency.requirements.first
31
+ return unless requirement
32
+
33
+ new_source = docker_source(requirement)
34
+ return unless new_source[:registry] && (new_source[:tag] || new_source[:digest])
32
35
 
33
36
  details = image_details(new_source)
34
37
  image_source = image_label(details, "org.opencontainers.image.source")
@@ -44,6 +47,17 @@ module Dependabot
44
47
  nil
45
48
  end
46
49
 
50
+ sig { params(requirement: Dependabot::DependencyRequirement).returns(DockerSource) }
51
+ def docker_source(requirement)
52
+ raise TypeError, "Docker source must be a hash" if requirement.source_hash.nil?
53
+
54
+ {
55
+ registry: requirement.source_string("registry"),
56
+ tag: requirement.source_string("tag"),
57
+ digest: requirement.source_string("digest")
58
+ }
59
+ end
60
+
47
61
  sig do
48
62
  params(
49
63
  source: DockerSource
@@ -52,24 +52,18 @@ module Dependabot
52
52
  class UpdateChecker < Dependabot::UpdateCheckers::Base
53
53
  extend T::Sig
54
54
 
55
- MANIFEST_LIST_TYPES = T.let(
56
- [
57
- "application/vnd.docker.distribution.manifest.list.v2+json",
58
- "application/vnd.oci.image.index.v1+json"
59
- ].freeze,
60
- T::Array[String]
61
- )
55
+ MANIFEST_LIST_TYPES = [
56
+ "application/vnd.docker.distribution.manifest.list.v2+json",
57
+ "application/vnd.oci.image.index.v1+json"
58
+ ].freeze
62
59
 
63
60
  # Media types returned for single-platform (non manifest-list) images.
64
61
  # Used to cheaply rule out manifest-list comparison via a HEAD request's
65
62
  # negotiated Content-Type, avoiding a full manifest GET for these images.
66
- SINGLE_PLATFORM_MANIFEST_TYPES = T.let(
67
- [
68
- "application/vnd.docker.distribution.manifest.v2+json",
69
- "application/vnd.oci.image.manifest.v1+json"
70
- ].freeze,
71
- T::Array[String]
72
- )
63
+ SINGLE_PLATFORM_MANIFEST_TYPES = [
64
+ "application/vnd.docker.distribution.manifest.v2+json",
65
+ "application/vnd.oci.image.manifest.v1+json"
66
+ ].freeze
73
67
 
74
68
  # Tolerance window for platform timestamp comparison.
75
69
  # Multi-arch CI builds may finish platforms at slightly different times.
@@ -78,7 +72,7 @@ module Dependabot
78
72
  # Maximum number of candidates to run platform timestamp validation against.
79
73
  # Each validation can require 1 + 1 + N*2 registry API calls for N platforms,
80
74
  # so we cap the attempts to avoid rate limiting or excessive latency.
81
- MAX_PLATFORM_VALIDATION_ATTEMPTS = T.let(5, Integer)
75
+ MAX_PLATFORM_VALIDATION_ATTEMPTS = 5
82
76
 
83
77
  # Page size used when listing tags from a registry. Without an explicit page
84
78
  # size, registries such as Docker Hub try to return every tag in a single
@@ -86,7 +80,7 @@ module Dependabot
86
80
  # (e.g. hexpm/elixir has ~1M tags). Requesting a bounded page keeps each
87
81
  # request fast; the client then follows the registry's pagination links to
88
82
  # collect the remaining tags.
89
- TAGS_PAGE_SIZE = T.let(100, Integer)
83
+ TAGS_PAGE_SIZE = 100
90
84
 
91
85
  DockerSource = T.type_alias do
92
86
  T::Hash[Symbol, T.nilable(String)]
@@ -163,23 +157,25 @@ module Dependabot
163
157
 
164
158
  sig { override.returns(T::Array[Dependabot::DependencyRequirement]) }
165
159
  def updated_requirements
166
- updated = dependency.requirements.map do |req|
167
- updated_source = req.fetch(:source).dup
168
-
169
- tag = req[:source][:tag]
170
- digest = req[:source][:digest]
160
+ dependency.requirements.map do |req|
161
+ updated_source = T.must(req.source_hash).dup
162
+ source = docker_source(req)
163
+ tag = source[:tag]
164
+ digest = source[:digest]
171
165
 
172
166
  if tag
173
167
  updated_tag = latest_version_from(tag)
174
- updated_source[:tag] = updated_tag
175
- updated_source[:digest] = resolved_digest_for(tag, updated_tag, digest) if digest || pin_digests?
168
+ set_source_string(updated_source, "tag", updated_tag)
169
+ if digest || pin_digests?
170
+ set_source_string(updated_source, "digest", resolved_digest_for(tag, updated_tag, digest))
171
+ end
176
172
  elsif digest
177
- updated_source[:digest] = digest_within_cooldown?("latest") ? digest : digest_of("latest")
173
+ updated_digest = digest_within_cooldown?("latest") ? digest : digest_of("latest")
174
+ set_source_string(updated_source, "digest", updated_digest)
178
175
  end
179
176
 
180
- req.merge(source: updated_source)
177
+ Dependabot::DependencyRequirement.create(req.merge(source: updated_source))
181
178
  end
182
- wrap_requirements(updated)
183
179
  end
184
180
 
185
181
  private
@@ -242,8 +238,8 @@ module Dependabot
242
238
 
243
239
  sig { params(req: Dependabot::DependencyRequirement).returns(T::Boolean) }
244
240
  def digest_requirement_up_to_date?(req)
245
- source = req.fetch(:source)
246
- source_digest = source.fetch(:digest)
241
+ source = docker_source(req)
242
+ source_digest = T.must(source[:digest])
247
243
  source_tag = source[:tag]
248
244
 
249
245
  if source_tag
@@ -864,11 +860,7 @@ module Dependabot
864
860
 
865
861
  sig { returns(T.nilable(String)) }
866
862
  def registry_hostname
867
- if dependency.requirements.first&.dig(:source, :registry)
868
- return T.must(dependency.requirements.first).dig(:source, :registry)
869
- end
870
-
871
- credentials_finder.base_registry
863
+ dependency.requirements.first&.source_string("registry") || credentials_finder.base_registry
872
864
  end
873
865
 
874
866
  sig { returns(T::Boolean) }
@@ -1000,7 +992,35 @@ module Dependabot
1000
992
  sig { returns(T::Array[Dependabot::DependencyRequirement]) }
1001
993
  def digest_requirements
1002
994
  dependency.requirements.select do |requirement|
1003
- requirement.dig(:source, :digest)
995
+ requirement.source_string("digest")
996
+ end
997
+ end
998
+
999
+ sig { params(requirement: Dependabot::DependencyRequirement).returns(DockerSource) }
1000
+ def docker_source(requirement)
1001
+ raise TypeError, "Docker source must be a hash" if requirement.source_hash.nil?
1002
+
1003
+ {
1004
+ registry: requirement.source_string("registry"),
1005
+ tag: requirement.source_string("tag"),
1006
+ digest: requirement.source_string("digest"),
1007
+ platform: requirement.source_string("platform")
1008
+ }
1009
+ end
1010
+
1011
+ sig do
1012
+ params(
1013
+ source: Dependabot::DependencyRequirement::ObjectHash,
1014
+ key: String,
1015
+ value: T.nilable(String)
1016
+ ).void
1017
+ end
1018
+ def set_source_string(source, key, value)
1019
+ symbol_key = key.to_sym
1020
+ if source.key?(key) && !source.key?(symbol_key)
1021
+ source[key] = value
1022
+ else
1023
+ source[symbol_key] = value
1004
1024
  end
1005
1025
  end
1006
1026
 
@@ -1,4 +1,4 @@
1
- # typed: strict
1
+ # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/file_updaters"
@@ -17,9 +17,13 @@ module Dependabot
17
17
 
18
18
  FROM_REGEX = /FROM(\s+--platform\=\S+)?/i
19
19
 
20
+ ImageSource = T.type_alias do
21
+ T::Hash[Symbol, T.nilable(String)]
22
+ end
23
+
20
24
  sig { override.returns(T::Array[Dependabot::DependencyFile]) }
21
25
  def updated_dependency_files
22
- updated_files = []
26
+ updated_files = T.let([], T::Array[Dependabot::DependencyFile])
23
27
  dependency_files.each do |file|
24
28
  next unless requirement_changed?(file, T.must(dependency))
25
29
 
@@ -72,8 +76,8 @@ module Dependabot
72
76
  sig do
73
77
  params(
74
78
  previous_content: String,
75
- old_source: T::Hash[Symbol, T.nilable(String)],
76
- new_source: T::Hash[Symbol, T.nilable(String)]
79
+ old_source: ImageSource,
80
+ new_source: ImageSource
77
81
  ).returns(String)
78
82
  end
79
83
  def update_digest_and_tag(previous_content, old_source, new_source)
@@ -178,19 +182,21 @@ module Dependabot
178
182
 
179
183
  sig { params(file: Dependabot::DependencyFile).returns(String) }
180
184
  def new_yaml_image(file)
181
- element = T.must(dependency).requirements.find { |r| r[:file] == file.name }
182
- prefix = element&.dig(:source, :registry) ? "#{element.fetch(:source)[:registry]}/" : ""
183
- digest = element&.dig(:source, :digest) ? "@sha256:#{element.fetch(:source)[:digest]}" : ""
184
- tag = element&.dig(:source, :tag) ? ":#{element.fetch(:source)[:tag]}" : ""
185
+ element = T.must(dependency).requirements.find { |r| r.file == file.name }
186
+ source = image_source(element)
187
+ prefix = source[:registry] ? "#{source[:registry]}/" : ""
188
+ digest = source[:digest] ? "@sha256:#{source[:digest]}" : ""
189
+ tag = source[:tag] ? ":#{source[:tag]}" : ""
185
190
  "#{prefix}#{T.must(dependency).name}#{tag}#{digest}"
186
191
  end
187
192
 
188
193
  sig { params(file: Dependabot::DependencyFile).returns(T::Array[String]) }
189
194
  def old_yaml_images(file)
190
195
  T.must(previous_requirements(file)).map do |r|
191
- prefix = r.fetch(:source)[:registry] ? "#{r.fetch(:source)[:registry]}/" : ""
192
- digest = r.fetch(:source)[:digest] ? "@sha256:#{r.fetch(:source)[:digest]}" : ""
193
- tag = r.fetch(:source)[:tag] ? ":#{r.fetch(:source)[:tag]}" : ""
196
+ source = image_source(r)
197
+ prefix = source[:registry] ? "#{source[:registry]}/" : ""
198
+ digest = source[:digest] ? "@sha256:#{source[:digest]}" : ""
199
+ tag = source[:tag] ? ":#{source[:tag]}" : ""
194
200
  "#{prefix}#{T.must(dependency).name}#{tag}#{digest}"
195
201
  end
196
202
  end
@@ -198,17 +204,19 @@ module Dependabot
198
204
  sig { params(file: Dependabot::DependencyFile).returns(T::Array[String]) }
199
205
  def old_helm_tags(file)
200
206
  T.must(previous_requirements(file)).map do |r|
201
- tag = r.fetch(:source)[:tag] || ""
202
- digest = r.fetch(:source)[:digest] ? "@sha256:#{r.fetch(:source)[:digest]}" : ""
207
+ source = image_source(r)
208
+ tag = source[:tag] || ""
209
+ digest = source[:digest] ? "@sha256:#{source[:digest]}" : ""
203
210
  "#{tag}#{digest}"
204
211
  end
205
212
  end
206
213
 
207
214
  sig { params(file: Dependabot::DependencyFile).returns(String) }
208
215
  def new_helm_tag(file)
209
- element = T.must(dependency).requirements.find { |r| r[:file] == file.name }
210
- tag = T.must(element).dig(:source, :tag) || ""
211
- digest = T.must(element).dig(:source, :digest) ? "@sha256:#{T.must(element).dig(:source, :digest)}" : ""
216
+ element = T.must(dependency).requirements.find { |r| r.file == file.name }
217
+ source = image_source(element)
218
+ tag = source[:tag] || ""
219
+ digest = source[:digest] ? "@sha256:#{source[:digest]}" : ""
212
220
  "#{tag}#{digest}"
213
221
  end
214
222
 
@@ -219,15 +227,15 @@ module Dependabot
219
227
  changed_requirements =
220
228
  dependency.requirements - T.must(dependency.previous_requirements)
221
229
 
222
- changed_requirements.any? { |f| f[:file] == file.name }
230
+ changed_requirements.any? { |f| f.file == file.name }
223
231
  end
224
232
 
225
- sig { params(source: T::Hash[Symbol, T.nilable(String)]).returns(T::Boolean) }
233
+ sig { params(source: ImageSource).returns(T::Boolean) }
226
234
  def specified_with_tag?(source)
227
235
  !source[:tag].nil?
228
236
  end
229
237
 
230
- sig { params(source: T::Hash[Symbol, T.nilable(String)]).returns(T::Boolean) }
238
+ sig { params(source: ImageSource).returns(T::Boolean) }
231
239
  def specified_with_digest?(source)
232
240
  !source[:digest].nil?
233
241
  end
@@ -235,28 +243,41 @@ module Dependabot
235
243
  sig { params(file: Dependabot::DependencyFile).returns(T::Array[Dependabot::DependencyRequirement]) }
236
244
  def requirements(file)
237
245
  T.must(dependency).requirements
238
- .select { |r| r[:file] == file.name }
246
+ .select { |r| r.file == file.name }
239
247
  end
240
248
 
241
249
  sig { params(file: Dependabot::DependencyFile).returns(T.nilable(T::Array[Dependabot::DependencyRequirement])) }
242
250
  def previous_requirements(file)
243
251
  T.must(dependency).previous_requirements
244
- &.select { |r| r[:file] == file.name }
252
+ &.select { |r| r.file == file.name }
245
253
  end
246
254
 
247
- sig { params(source: T::Hash[Symbol, T.nilable(String)]).returns(T.nilable(String)) }
255
+ sig { params(source: ImageSource).returns(T.nilable(String)) }
248
256
  def private_registry_url(source)
249
257
  source[:registry]
250
258
  end
251
259
 
252
- sig { params(file: Dependabot::DependencyFile).returns(T::Array[T::Hash[Symbol, T.nilable(String)]]) }
260
+ sig { params(file: Dependabot::DependencyFile).returns(T::Array[ImageSource]) }
253
261
  def sources(file)
254
- requirements(file).map { |r| r.fetch(:source) }
262
+ requirements(file).map { |r| image_source(r) }
255
263
  end
256
264
 
257
- sig { params(file: Dependabot::DependencyFile).returns(T.nilable(T::Array[T::Hash[Symbol, T.nilable(String)]])) }
265
+ sig { params(file: Dependabot::DependencyFile).returns(T.nilable(T::Array[ImageSource])) }
258
266
  def previous_sources(file)
259
- previous_requirements(file)&.map { |r| r.fetch(:source) }
267
+ previous_requirements(file)&.map { |r| image_source(r) }
268
+ end
269
+
270
+ sig { params(requirement: T.nilable(Dependabot::DependencyRequirement)).returns(ImageSource) }
271
+ def image_source(requirement)
272
+ return { registry: nil, tag: nil, digest: nil } if requirement.nil?
273
+
274
+ raise TypeError, "container source must be a hash" if requirement.source_hash.nil?
275
+
276
+ {
277
+ registry: requirement.source_string("registry"),
278
+ tag: requirement.source_string("tag"),
279
+ digest: requirement.source_string("digest")
280
+ }
260
281
  end
261
282
 
262
283
  sig { returns(T.nilable(Dependabot::Dependency)) }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-docker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.390.0
4
+ version: 0.391.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 0.390.0
18
+ version: 0.391.0
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - '='
24
24
  - !ruby/object:Gem::Version
25
- version: 0.390.0
25
+ version: 0.391.0
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: debug
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -266,7 +266,7 @@ licenses:
266
266
  - MIT
267
267
  metadata:
268
268
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
269
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.390.0
269
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.391.0
270
270
  rdoc_options: []
271
271
  require_paths:
272
272
  - lib