dependabot-docker_compose 0.298.0 → 0.299.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: 8a3db024dd3fcc06548464dfcc4d200d9902985db3370b63a8a19780982c5e9d
4
- data.tar.gz: 3b72a87e970f39783a4043ff3b8fb1e5046edb836458c2b11d0a0a202fa996bc
3
+ metadata.gz: 861d5c42bba5e0e574cfafdf438e749b62be2948c015641006cc24484f600089
4
+ data.tar.gz: 458e5b67bc719d3d38f353049098acf6770895e864695a9da763cc20a551b9bf
5
5
  SHA512:
6
- metadata.gz: c725b06c42e3dc9ff8d8d835ea54c877a6d8c8dd3a033685e3aca5b3816cf36e5a012859f3b0b2dc6a078696c5034fdf8bcfd60f52a44972b82813478652832e
7
- data.tar.gz: 566b2fb4658e7f06ca74520791f5b20c3a426baa50540bd0886e4ea93a5ffba1b97e26a86649c996f8aa80a94e6923a3db3f06392592607e6824d70658330df1
6
+ metadata.gz: c9c01ed28d5c74d401305cc5a0476adf12b476467f145631f49ce7dd480f6d578e31d9378bc87e9e05ebbfc0467c2ca1d12f8acdd39c0913a72293af1ee8fa8a
7
+ data.tar.gz: 07326f38f060f039037f14fe307a3c36e65f31f37299f322be6a64f5d66fa272875f8942e54e3499c18acbfa7d34137bb7ae3f53887ece99d7013e04a235f29a
@@ -11,7 +11,7 @@ module Dependabot
11
11
  sig { override.returns(T::Array[DependencyFile]) }
12
12
  def fetch_files
13
13
  fetched_files = []
14
- fetched_files += correctly_encoded_docker_compose_files if allow_beta_ecosystems?
14
+ fetched_files += correctly_encoded_docker_compose_files
15
15
 
16
16
  return fetched_files if fetched_files.any?
17
17
 
@@ -10,7 +10,16 @@ module Dependabot
10
10
  class FileParser < Dependabot::Shared::SharedFileParser
11
11
  extend T::Sig
12
12
 
13
- FROM_IMAGE = %r{^(?:#{REGISTRY}/)?#{IMAGE}(?:#{TAG})?(?:#{DIGEST})?(?:#{NAME})?}
13
+ ENV_VAR = /\${[^}]+}/
14
+ DIGEST = /(?<digest>[0-9a-f]{64})/
15
+ IMAGE_REGEX = %r{^(#{REGISTRY}/)?#{IMAGE}#{TAG}?(?:@sha256:#{DIGEST})?#{NAME}?}x
16
+
17
+ FROM = /FROM/i
18
+ PLATFORM = /--platform\=(?<platform>\S+)/
19
+
20
+ FROM_LINE =
21
+ %r{^#{FROM}\s+(#{PLATFORM}\s+)?(#{REGISTRY}/)?
22
+ #{IMAGE}#{TAG}?(?:@sha256:#{DIGEST})?#{NAME}?}x
14
23
 
15
24
  sig { returns(Ecosystem) }
16
25
  def ecosystem
@@ -28,9 +37,15 @@ module Dependabot
28
37
  dependency_set = DependencySet.new
29
38
 
30
39
  composefiles.each do |composefile|
31
- yaml = YAML.safe_load(T.must(composefile.content))
40
+ yaml = YAML.safe_load(T.must(composefile.content), aliases: true)
41
+ next unless yaml["services"].is_a?(Hash)
42
+
32
43
  yaml["services"].each do |_, service|
33
- parsed_from_image = T.must(FROM_IMAGE.match(service["image"])).named_captures
44
+ next unless service.is_a?(Hash)
45
+
46
+ parsed_from_image = parse_image_spec(service)
47
+ next unless parsed_from_image
48
+
34
49
  parsed_from_image["registry"] = nil if parsed_from_image["registry"] == "docker.io"
35
50
 
36
51
  version = version_from(parsed_from_image)
@@ -45,6 +60,32 @@ module Dependabot
45
60
 
46
61
  private
47
62
 
63
+ sig { params(service: T.untyped).returns(T.nilable(T::Hash[String, T.nilable(String)])) }
64
+ def parse_image_spec(service)
65
+ return nil unless service
66
+
67
+ if service["image"]
68
+ return nil if service["image"].match?(/^\${[^}]+}$/)
69
+
70
+ match = IMAGE_REGEX.match(service["image"])
71
+ return match&.named_captures
72
+ elsif service["build"].is_a?(Hash) && service["build"]["dockerfile_inline"]
73
+ return nil if service["build"]["dockerfile_inline"].match?(/^FROM\s+\${[^}]+}$/)
74
+
75
+ match = FROM_LINE.match(service["build"]["dockerfile_inline"])
76
+ return match&.named_captures
77
+ end
78
+
79
+ nil
80
+ end
81
+
82
+ sig { params(parsed_image: T::Hash[String, T.nilable(String)]).returns(T.nilable(String)) }
83
+ def version_from(parsed_image)
84
+ return nil if parsed_image["tag"]&.match?(ENV_VAR)
85
+
86
+ super
87
+ end
88
+
48
89
  sig { override.returns(String) }
49
90
  def package_manager
50
91
  "docker_compose"
@@ -10,7 +10,7 @@ module Dependabot
10
10
  extend T::Helpers
11
11
 
12
12
  YAML_REGEXP = /(docker-)?compose(?>\.[\w-]+)?\.ya?ml/i
13
- IMAGE_REGEX = /image:\s*/
13
+ IMAGE_REGEX = /(?:from|image:\s*)/i
14
14
 
15
15
  sig { override.returns(T::Array[Regexp]) }
16
16
  def self.updated_files_regex
@@ -34,7 +34,7 @@ module Dependabot
34
34
 
35
35
  sig { override.params(escaped_declaration: String).returns(Regexp) }
36
36
  def build_old_declaration_regex(escaped_declaration)
37
- %r{#{IMAGE_REGEX}\s+(docker\.io/)?#{escaped_declaration}(?=\s|$)}
37
+ %r{#{IMAGE_REGEX}\s+["']?(docker\.io/)?#{escaped_declaration}["']?(?=\s|$)}
38
38
  end
39
39
 
40
40
  sig { override.returns(T::Array[Dependabot::DependencyFile]) }
@@ -54,48 +54,6 @@ module Dependabot
54
54
 
55
55
  updated_files
56
56
  end
57
-
58
- sig do
59
- override.params(previous_content: String, old_source: T::Hash[Symbol, T.nilable(String)],
60
- new_source: T::Hash[Symbol, T.nilable(String)]).returns(String)
61
- end
62
- def update_digest_and_tag(previous_content, old_source, new_source)
63
- old_digest = old_source[:digest]
64
- new_digest = new_source[:digest]
65
-
66
- old_tag = old_source[:tag]
67
- new_tag = new_source[:tag]
68
-
69
- old_declaration =
70
- if private_registry_url(old_source)
71
- "#{private_registry_url(old_source)}/"
72
- else
73
- ""
74
- end
75
- old_declaration += T.must(dependency).name
76
- old_declaration +=
77
- if specified_with_tag?(old_source)
78
- ":#{old_tag}"
79
- else
80
- ""
81
- end
82
- old_declaration +=
83
- if old_digest&.start_with?("sha256:")
84
- "@#{old_digest}"
85
- else
86
- ""
87
- end
88
-
89
- escaped_declaration = Regexp.escape(old_declaration)
90
-
91
- old_declaration_regex = build_old_declaration_regex(escaped_declaration)
92
-
93
- previous_content.gsub(old_declaration_regex) do |old_dec|
94
- old_dec
95
- .gsub(":#{old_tag}", ":#{new_tag}")
96
- .gsub(old_digest.to_s, new_digest.to_s)
97
- end
98
- end
99
57
  end
100
58
  end
101
59
  end
@@ -2,9 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "sorbet-runtime"
5
- require "dependabot/docker_compose/version"
6
5
  require "dependabot/ecosystem"
7
- require "dependabot/docker_compose/requirement"
8
6
 
9
7
  module Dependabot
10
8
  module DockerCompose
@@ -3,13 +3,17 @@
3
3
 
4
4
  # These all need to be required so the various classes can be registered in a
5
5
  # lookup table of package manager names to concrete classes.
6
+
7
+ require "dependabot/docker"
8
+
6
9
  require "dependabot/docker_compose/file_fetcher"
7
10
  require "dependabot/docker_compose/file_parser"
8
- require "dependabot/docker_compose/update_checker"
9
11
  require "dependabot/docker_compose/file_updater"
10
- require "dependabot/docker_compose/metadata_finder"
11
- require "dependabot/docker_compose/requirement"
12
- require "dependabot/docker_compose/version"
12
+
13
+ Dependabot::Utils.register_version_class("docker_compose", Dependabot::Docker::Version)
14
+ Dependabot::UpdateCheckers.register("docker_compose", Dependabot::Docker::UpdateChecker)
15
+ Dependabot::Utils.register_requirement_class("docker_compose", Dependabot::Docker::Requirement)
16
+ Dependabot::MetadataFinders.register("docker_compose", Dependabot::Docker::MetadataFinder)
13
17
 
14
18
  require "dependabot/pull_request_creator/labeler"
15
19
  Dependabot::PullRequestCreator::Labeler
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-docker_compose
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.298.0
4
+ version: 0.299.0
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-20 00:00:00.000000000 Z
11
+ date: 2025-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dependabot-common
@@ -16,14 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.298.0
19
+ version: 0.299.0
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.298.0
26
+ version: 0.299.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: dependabot-docker
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.299.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.299.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: debug
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -246,23 +260,13 @@ files:
246
260
  - lib/dependabot/docker_compose/file_fetcher.rb
247
261
  - lib/dependabot/docker_compose/file_parser.rb
248
262
  - lib/dependabot/docker_compose/file_updater.rb
249
- - lib/dependabot/docker_compose/metadata_finder.rb
250
263
  - lib/dependabot/docker_compose/package_manager.rb
251
- - lib/dependabot/docker_compose/requirement.rb
252
- - lib/dependabot/docker_compose/tag.rb
253
- - lib/dependabot/docker_compose/update_checker.rb
254
- - lib/dependabot/docker_compose/version.rb
255
- - lib/dependabot/shared/shared_file_fetcher.rb
256
- - lib/dependabot/shared/shared_file_parser.rb
257
- - lib/dependabot/shared/shared_file_updater.rb
258
- - lib/dependabot/shared/utils/credentials_finder.rb
259
- - lib/dependabot/shared/utils/helpers.rb
260
264
  homepage: https://github.com/dependabot/dependabot-core
261
265
  licenses:
262
266
  - MIT
263
267
  metadata:
264
268
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
265
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.298.0
269
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.299.0
266
270
  post_install_message:
267
271
  rdoc_options: []
268
272
  require_paths:
@@ -1,39 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- require "dependabot/metadata_finders"
5
- require "dependabot/metadata_finders/base"
6
- require "dependabot/shared_helpers"
7
- require "sorbet-runtime"
8
-
9
- module Dependabot
10
- module DockerCompose
11
- class MetadataFinder < Dependabot::MetadataFinders::Base
12
- extend T::Sig
13
-
14
- private
15
-
16
- sig { override.returns(T.nilable(Dependabot::Source)) }
17
- def look_up_source
18
- return if dependency.requirements.empty?
19
-
20
- new_source = dependency.requirements.first&.fetch(:source)
21
- return unless new_source && new_source[:registry] && new_source[:tag]
22
-
23
- image_ref = "#{new_source[:registry]}/#{dependency.name}:#{new_source[:tag]}"
24
- image_details_output = SharedHelpers.run_shell_command("regctl image inspect #{image_ref}")
25
- image_details = JSON.parse(image_details_output)
26
- image_source = image_details.dig("config", "Labels", "org.opencontainers.image.source")
27
- return unless image_source
28
-
29
- Dependabot::Source.from_url(image_source)
30
- rescue StandardError => e
31
- Dependabot.logger.warn("Error looking up Docker Compose source: #{e.message}")
32
- nil
33
- end
34
- end
35
- end
36
- end
37
-
38
- Dependabot::MetadataFinders
39
- .register("docker_compose", Dependabot::DockerCompose::MetadataFinder)
@@ -1,43 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- require "sorbet-runtime"
5
-
6
- require "dependabot/requirement"
7
- require "dependabot/utils"
8
-
9
- module Dependabot
10
- module DockerCompose
11
- # Lifted from the bundler package manager
12
- class Requirement < Dependabot::Requirement
13
- extend T::Sig
14
-
15
- # For consistency with other languages, we define a requirements array.
16
- # Ruby doesn't have an `OR` separator for requirements, so it always
17
- # contains a single element.
18
- sig { override.params(requirement_string: T.nilable(String)).returns(T::Array[Requirement]) }
19
- def self.requirements_array(requirement_string)
20
- [new(T.must(requirement_string))]
21
- end
22
-
23
- sig { override.params(version: Version).returns(T::Boolean) }
24
- def satisfied_by?(version)
25
- super(version.release_part)
26
- end
27
-
28
- # Patches Gem::Requirement to make it accept requirement strings like
29
- # "~> 4.2.5, >= 4.2.5.1" without first needing to split them.
30
- sig { params(requirements: T.any(T.nilable(String), T::Array[T.nilable(String)])).void }
31
- def initialize(*requirements)
32
- requirements = requirements.flatten.flat_map do |req_string|
33
- req_string.to_s.split(",").map(&:strip)
34
- end
35
-
36
- super(requirements)
37
- end
38
- end
39
- end
40
- end
41
-
42
- Dependabot::Utils
43
- .register_requirement_class("docker_compose", Dependabot::DockerCompose::Requirement)
@@ -1,144 +0,0 @@
1
- # typed: strong
2
- # frozen_string_literal: true
3
-
4
- require "sorbet-runtime"
5
-
6
- module Dependabot
7
- module DockerCompose
8
- class Tag
9
- extend T::Sig
10
- WORDS_WITH_BUILD = /(?:(?:-[a-z]+)+-[0-9]+)+/
11
- VERSION_REGEX = /v?(?<version>[0-9]+(?:[_.][0-9]+)*(?:\.[a-z0-9]+|#{WORDS_WITH_BUILD}|-(?:kb)?[0-9]+)*)/i
12
- VERSION_WITH_SFX = /^#{VERSION_REGEX}(?<suffix>-[a-z][a-z0-9.\-]*)?$/i
13
- VERSION_WITH_PFX = /^(?<prefix>[a-z][a-z0-9.\-_]*-)?#{VERSION_REGEX}$/i
14
- VERSION_WITH_PFX_AND_SFX = /^(?<prefix>[a-z\-_]+-)?#{VERSION_REGEX}(?<suffix>-[a-z\-]+)?$/i
15
- NAME_WITH_VERSION =
16
- /
17
- #{VERSION_WITH_PFX}|
18
- #{VERSION_WITH_SFX}|
19
- #{VERSION_WITH_PFX_AND_SFX}
20
- /x
21
- DIGEST = /@(?<digest>[^\s]+)/
22
-
23
- sig { returns(String) }
24
- attr_reader :name
25
-
26
- sig { params(name: String).void }
27
- def initialize(name)
28
- @name = name
29
- end
30
-
31
- sig { returns(String) }
32
- def to_s
33
- name
34
- end
35
-
36
- sig { returns(T::Boolean) }
37
- def digest?
38
- name.match?(DIGEST)
39
- end
40
-
41
- sig { returns(T.nilable(T::Boolean)) }
42
- def looks_like_prerelease?
43
- numeric_version&.match?(/[a-zA-Z]/)
44
- end
45
-
46
- sig { params(other: Tag).returns(T::Boolean) }
47
- def comparable_to?(other)
48
- return false unless comparable?
49
-
50
- other_prefix = other.prefix
51
- other_suffix = other.suffix
52
- other_format = other.format
53
-
54
- equal_prefix = prefix == other_prefix
55
- equal_format = format == other_format
56
- return equal_prefix && equal_format if other_format == :sha_suffixed
57
-
58
- equal_suffix = suffix == other_suffix
59
- equal_prefix && equal_format && equal_suffix
60
- end
61
-
62
- sig { returns(T::Boolean) }
63
- def comparable?
64
- name.match?(NAME_WITH_VERSION)
65
- end
66
-
67
- sig { params(other: Tag).returns(T::Boolean) }
68
- def same_precision?(other)
69
- other.precision == precision
70
- end
71
-
72
- sig { params(other: Tag).returns(T::Boolean) }
73
- def same_but_less_precise?(other)
74
- other.segments.zip(segments).all? do |segment, other_segment|
75
- segment == other_segment || other_segment.nil?
76
- end
77
- end
78
-
79
- sig { returns(T.nilable(T::Boolean)) }
80
- def canonical?
81
- return false unless numeric_version
82
- return true if name == numeric_version
83
-
84
- # .NET tags are suffixed with -sdk
85
- return true if numeric_version && name == numeric_version.to_s + "-sdk"
86
-
87
- numeric_version && name == "jdk-" + T.must(numeric_version)
88
- end
89
-
90
- sig { returns T.nilable(String) }
91
- def prefix
92
- name.match(NAME_WITH_VERSION)&.named_captures&.fetch("prefix")
93
- end
94
-
95
- sig { returns T.nilable(String) }
96
- def suffix
97
- name.match(NAME_WITH_VERSION)&.named_captures&.fetch("suffix")
98
- end
99
-
100
- sig { returns T.nilable(String) }
101
- def version
102
- name.match(NAME_WITH_VERSION)&.named_captures&.fetch("version")
103
- end
104
-
105
- sig { returns(Symbol) }
106
- def format
107
- return :sha_suffixed if name.match?(/(^|\-g?)[0-9a-f]{7,}$/)
108
- return :year_month if version&.match?(/^[12]\d{3}(?:[.\-]|$)/)
109
- return :year_month_day if version&.match?(/^[12](?:\d{5}|\d{7})(?:[.\-]|$)/)
110
- return :build_num if version&.match?(/^\d+$/)
111
-
112
- # As an example, "21-ea-32", "22-ea-7", and "22-ea-jdk-nanoserver-1809"
113
- # are mapped to "<version>-ea-<build_num>", "<version>-ea-<build_num>",
114
- # and "<version>-ea-jdk-nanoserver-<build_num>" respectively.
115
- #
116
- # That means only "22-ea-7" will be considered as a viable update
117
- # candidate for "21-ea-32", since it's the only one that respects that
118
- # format.
119
- if version&.match?(WORDS_WITH_BUILD)
120
- return :"<version>#{T.must(version).match(WORDS_WITH_BUILD).to_s.gsub(/-[0-9]+/, '-<build_num>')}"
121
- end
122
-
123
- :normal
124
- end
125
-
126
- sig { returns(T.nilable(String)) }
127
- def numeric_version
128
- return unless comparable?
129
-
130
- version&.gsub(/kb/i, "")&.gsub(/-[a-z]+/, "")&.downcase
131
- end
132
-
133
- sig { returns(Integer) }
134
- def precision
135
- segments.length
136
- end
137
-
138
- sig { returns(T::Array[String]) }
139
- def segments
140
- T.must(numeric_version).split(/[.-]/)
141
- end
142
- end
143
- end
144
- end