dependabot-docker 0.259.0 → 0.260.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 +4 -4
- data/lib/dependabot/docker/file_fetcher.rb +28 -13
- data/lib/dependabot/docker/file_parser.rb +20 -3
- data/lib/dependabot/docker/file_updater.rb +54 -26
- data/lib/dependabot/docker/metadata_finder.rb +5 -1
- data/lib/dependabot/docker/requirement.rb +4 -2
- data/lib/dependabot/docker/tag.rb +33 -15
- data/lib/dependabot/docker/update_checker.rb +1 -1
- data/lib/dependabot/docker/utils/credentials_finder.rb +15 -7
- data/lib/dependabot/docker/utils/helpers.rb +6 -1
- data/lib/dependabot/docker/version.rb +21 -9
- 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: c2b8bc30ebbc60146a41cb00193a87642254cea63e48d63a6ceb5f0bd3305e63
|
|
4
|
+
data.tar.gz: 8085d1d31692622d6ee57bbdc0466e388257275fb7aaa3841a6a426192f9f5ea
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 95e886db37f7981efa16b2c00569b3eb37cb5dc5ebcb4824d34cb2d776d25276c982597088451d8cbdf2816fddf19418c0979c699e80529d5c63b5fef34dcbd2
|
|
7
|
+
data.tar.gz: c9034900857a4f7714769f3639da527f8cfdc2d70ab2591b54718e33844c70c76364c6cc8e808523988bbd7f78bb6a6c7c97fcacec14ed15b8b4ecd7290ace09
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "sorbet-runtime"
|
|
@@ -15,11 +15,13 @@ module Dependabot
|
|
|
15
15
|
YAML_REGEXP = /^[^\.].*\.ya?ml$/i
|
|
16
16
|
DOCKER_REGEXP = /dockerfile/i
|
|
17
17
|
|
|
18
|
+
sig { override.params(filenames: T::Array[String]).returns(T::Boolean) }
|
|
18
19
|
def self.required_files_in?(filenames)
|
|
19
20
|
filenames.any? { |f| f.match?(DOCKER_REGEXP) } or
|
|
20
21
|
filenames.any? { |f| f.match?(YAML_REGEXP) }
|
|
21
22
|
end
|
|
22
23
|
|
|
24
|
+
sig { override.returns(String) }
|
|
23
25
|
def self.required_files_message
|
|
24
26
|
"Repo must contain a Dockerfile or Kubernetes YAML files."
|
|
25
27
|
end
|
|
@@ -40,54 +42,66 @@ module Dependabot
|
|
|
40
42
|
elsif incorrectly_encoded_dockerfiles.none?
|
|
41
43
|
raise(
|
|
42
44
|
Dependabot::DependencyFileNotParseable,
|
|
43
|
-
incorrectly_encoded_yamlfiles.first.path
|
|
45
|
+
T.must(incorrectly_encoded_yamlfiles.first).path
|
|
44
46
|
)
|
|
45
47
|
else
|
|
46
48
|
raise(
|
|
47
49
|
Dependabot::DependencyFileNotParseable,
|
|
48
|
-
incorrectly_encoded_dockerfiles.first.path
|
|
50
|
+
T.must(incorrectly_encoded_dockerfiles.first).path
|
|
49
51
|
)
|
|
50
52
|
end
|
|
51
53
|
end
|
|
52
54
|
|
|
53
55
|
private
|
|
54
56
|
|
|
57
|
+
sig { returns(T::Array[DependencyFile]) }
|
|
55
58
|
def dockerfiles
|
|
56
|
-
@dockerfiles ||=
|
|
57
|
-
|
|
59
|
+
@dockerfiles ||= T.let(fetch_dockerfiles, T.nilable(T::Array[DependencyFile]))
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
63
|
+
def fetch_dockerfiles
|
|
64
|
+
repo_contents(raise_errors: false)
|
|
58
65
|
.select { |f| f.type == "file" && f.name.match?(DOCKER_REGEXP) }
|
|
59
66
|
.map { |f| fetch_file_from_host(f.name) }
|
|
60
67
|
end
|
|
61
68
|
|
|
69
|
+
sig { returns(T::Array[DependencyFile]) }
|
|
62
70
|
def correctly_encoded_dockerfiles
|
|
63
|
-
dockerfiles.select { |f| f.content
|
|
71
|
+
dockerfiles.select { |f| f.content&.valid_encoding? }
|
|
64
72
|
end
|
|
65
73
|
|
|
74
|
+
sig { returns(T::Array[DependencyFile]) }
|
|
66
75
|
def incorrectly_encoded_dockerfiles
|
|
67
|
-
dockerfiles.reject { |f| f.content
|
|
76
|
+
dockerfiles.reject { |f| f.content&.valid_encoding? }
|
|
68
77
|
end
|
|
69
78
|
|
|
79
|
+
sig { returns(T::Array[DependencyFile]) }
|
|
70
80
|
def yamlfiles
|
|
71
|
-
@yamlfiles ||=
|
|
81
|
+
@yamlfiles ||= T.let(
|
|
72
82
|
repo_contents(raise_errors: false)
|
|
73
|
-
|
|
74
|
-
|
|
83
|
+
.select { |f| f.type == "file" && f.name.match?(YAML_REGEXP) }
|
|
84
|
+
.map { |f| fetch_file_from_host(f.name) },
|
|
85
|
+
T.nilable(T::Array[DependencyFile])
|
|
86
|
+
)
|
|
75
87
|
end
|
|
76
88
|
|
|
89
|
+
sig { params(resource: Object).returns(T.nilable(T::Boolean)) }
|
|
77
90
|
def likely_kubernetes_resource?(resource)
|
|
78
91
|
# Heuristic for being a Kubernetes resource. We could make this tighter but this probably works well.
|
|
79
92
|
resource.is_a?(::Hash) && resource.key?("apiVersion") && resource.key?("kind")
|
|
80
93
|
end
|
|
81
94
|
|
|
95
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
82
96
|
def correctly_encoded_yamlfiles
|
|
83
|
-
candidate_files = yamlfiles.select { |f| f.content
|
|
97
|
+
candidate_files = yamlfiles.select { |f| f.content&.valid_encoding? }
|
|
84
98
|
candidate_files.select do |f|
|
|
85
99
|
if f.type == "file" && Utils.likely_helm_chart?(f)
|
|
86
100
|
true
|
|
87
101
|
else
|
|
88
102
|
# This doesn't handle multi-resource files, but it shouldn't matter, since the first resource
|
|
89
103
|
# in a multi-resource file had better be a valid k8s resource
|
|
90
|
-
content = ::YAML.safe_load(f.content, aliases: true)
|
|
104
|
+
content = ::YAML.safe_load(T.must(f.content), aliases: true)
|
|
91
105
|
likely_kubernetes_resource?(content)
|
|
92
106
|
end
|
|
93
107
|
rescue ::Psych::Exception
|
|
@@ -95,8 +109,9 @@ module Dependabot
|
|
|
95
109
|
end
|
|
96
110
|
end
|
|
97
111
|
|
|
112
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
98
113
|
def incorrectly_encoded_yamlfiles
|
|
99
|
-
yamlfiles.reject { |f| f.content
|
|
114
|
+
yamlfiles.reject { |f| f.content&.valid_encoding? }
|
|
100
115
|
end
|
|
101
116
|
end
|
|
102
117
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "docker_registry2"
|
|
@@ -7,10 +7,13 @@ require "dependabot/dependency"
|
|
|
7
7
|
require "dependabot/file_parsers"
|
|
8
8
|
require "dependabot/file_parsers/base"
|
|
9
9
|
require "dependabot/errors"
|
|
10
|
+
require "sorbet-runtime"
|
|
10
11
|
|
|
11
12
|
module Dependabot
|
|
12
13
|
module Docker
|
|
13
14
|
class FileParser < Dependabot::FileParsers::Base
|
|
15
|
+
extend T::Sig
|
|
16
|
+
|
|
14
17
|
require "dependabot/file_parsers/base/dependency_set"
|
|
15
18
|
|
|
16
19
|
YAML_REGEXP = /^[^\.].*\.ya?ml$/i
|
|
@@ -39,11 +42,12 @@ module Dependabot
|
|
|
39
42
|
|
|
40
43
|
IMAGE_SPEC = %r{^(#{REGISTRY}/)?#{IMAGE}#{TAG}?(?:@sha256:#{DIGEST})?#{NAME}?}x
|
|
41
44
|
|
|
45
|
+
sig { override.returns(T::Array[Dependabot::Dependency]) }
|
|
42
46
|
def parse
|
|
43
47
|
dependency_set = DependencySet.new
|
|
44
48
|
|
|
45
49
|
dockerfiles.each do |dockerfile|
|
|
46
|
-
dockerfile.content.each_line do |line|
|
|
50
|
+
T.must(dockerfile.content).each_line do |line|
|
|
47
51
|
next unless FROM_LINE.match?(line)
|
|
48
52
|
|
|
49
53
|
parsed_from_line = T.must(FROM_LINE.match(line)).named_captures
|
|
@@ -75,15 +79,18 @@ module Dependabot
|
|
|
75
79
|
|
|
76
80
|
private
|
|
77
81
|
|
|
82
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
78
83
|
def dockerfiles
|
|
79
84
|
# The Docker file fetcher fetches Dockerfiles and yaml files. Reject yaml files.
|
|
80
85
|
dependency_files.reject { |f| f.type == "file" && f.name.match?(YAML_REGEXP) }
|
|
81
86
|
end
|
|
82
87
|
|
|
88
|
+
sig { params(parsed_from_line: T::Hash[String, T.nilable(String)]).returns(T.nilable(String)) }
|
|
83
89
|
def version_from(parsed_from_line)
|
|
84
90
|
parsed_from_line.fetch("tag") || parsed_from_line.fetch("digest")
|
|
85
91
|
end
|
|
86
92
|
|
|
93
|
+
sig { params(parsed_from_line: T::Hash[String, T.nilable(String)]).returns(T::Hash[String, T.nilable(String)]) }
|
|
87
94
|
def source_from(parsed_from_line)
|
|
88
95
|
source = {}
|
|
89
96
|
|
|
@@ -96,6 +103,7 @@ module Dependabot
|
|
|
96
103
|
source
|
|
97
104
|
end
|
|
98
105
|
|
|
106
|
+
sig { override.void }
|
|
99
107
|
def check_required_files
|
|
100
108
|
# Just check if there are any files at all.
|
|
101
109
|
return if dependency_files.any?
|
|
@@ -103,6 +111,7 @@ module Dependabot
|
|
|
103
111
|
raise "No Dockerfile!"
|
|
104
112
|
end
|
|
105
113
|
|
|
114
|
+
sig { params(file: T.untyped).returns(Dependabot::FileParsers::Base::DependencySet) }
|
|
106
115
|
def workfile_file_dependencies(file)
|
|
107
116
|
dependency_set = DependencySet.new
|
|
108
117
|
|
|
@@ -130,6 +139,10 @@ module Dependabot
|
|
|
130
139
|
raise Dependabot::DependencyFileNotParseable, file.path
|
|
131
140
|
end
|
|
132
141
|
|
|
142
|
+
sig do
|
|
143
|
+
params(file: T.untyped, details: T.untyped,
|
|
144
|
+
version: T.nilable(T.any(String, Dependabot::Version))).returns(Dependabot::Dependency)
|
|
145
|
+
end
|
|
133
146
|
def build_image_dependency(file, details, version)
|
|
134
147
|
Dependency.new(
|
|
135
148
|
name: details.fetch("image"),
|
|
@@ -144,6 +157,7 @@ module Dependabot
|
|
|
144
157
|
)
|
|
145
158
|
end
|
|
146
159
|
|
|
160
|
+
sig { params(json_obj: T.anything).returns(T.untyped) }
|
|
147
161
|
def deep_fetch_images(json_obj)
|
|
148
162
|
case json_obj
|
|
149
163
|
when Hash then deep_fetch_images_from_hash(json_obj)
|
|
@@ -152,6 +166,7 @@ module Dependabot
|
|
|
152
166
|
end
|
|
153
167
|
end
|
|
154
168
|
|
|
169
|
+
sig { params(json_object: T.untyped).returns(T::Array[T.untyped]) }
|
|
155
170
|
def deep_fetch_images_from_hash(json_object)
|
|
156
171
|
img = json_object.fetch("image", nil)
|
|
157
172
|
|
|
@@ -167,11 +182,13 @@ module Dependabot
|
|
|
167
182
|
images + json_object.values.flat_map { |obj| deep_fetch_images(obj) }
|
|
168
183
|
end
|
|
169
184
|
|
|
185
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
170
186
|
def manifest_files
|
|
171
187
|
# Dependencies include both Dockerfiles and yaml, select yaml.
|
|
172
188
|
dependency_files.select { |f| f.type == "file" && f.name.match?(YAML_REGEXP) }
|
|
173
189
|
end
|
|
174
190
|
|
|
191
|
+
sig { params(img_hash: T::Hash[String, T.nilable(String)]).returns(T::Array[String]) }
|
|
175
192
|
def parse_helm(img_hash)
|
|
176
193
|
tag_value = img_hash.key?("tag") ? img_hash.fetch("tag", nil) : img_hash.fetch("version", nil)
|
|
177
194
|
return [] unless tag_value
|
|
@@ -179,7 +196,7 @@ module Dependabot
|
|
|
179
196
|
repo = img_hash.fetch("repository", nil)
|
|
180
197
|
return [] unless repo
|
|
181
198
|
|
|
182
|
-
tag_details = tag_value.to_s.match(TAG_WITH_DIGEST).named_captures
|
|
199
|
+
tag_details = T.must(tag_value.to_s.match(TAG_WITH_DIGEST)).named_captures
|
|
183
200
|
tag = tag_details["tag"]
|
|
184
201
|
return [repo] unless tag
|
|
185
202
|
|
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "dependabot/docker/utils/helpers"
|
|
5
5
|
require "dependabot/file_updaters"
|
|
6
6
|
require "dependabot/file_updaters/base"
|
|
7
7
|
require "dependabot/errors"
|
|
8
|
+
require "sorbet-runtime"
|
|
8
9
|
|
|
9
10
|
module Dependabot
|
|
10
11
|
module Docker
|
|
11
12
|
class FileUpdater < Dependabot::FileUpdaters::Base
|
|
13
|
+
extend T::Sig
|
|
14
|
+
|
|
12
15
|
FROM_REGEX = /FROM(\s+--platform\=\S+)?/i
|
|
13
16
|
|
|
14
17
|
YAML_REGEXP = /^[^\.].*\.ya?ml$/i
|
|
15
18
|
DOCKER_REGEXP = /dockerfile/i
|
|
16
19
|
|
|
20
|
+
sig { override.returns(T::Array[Regexp]) }
|
|
17
21
|
def self.updated_files_regex
|
|
18
22
|
[
|
|
19
23
|
DOCKER_REGEXP,
|
|
@@ -21,15 +25,16 @@ module Dependabot
|
|
|
21
25
|
]
|
|
22
26
|
end
|
|
23
27
|
|
|
28
|
+
sig { override.returns(T::Array[Dependabot::DependencyFile]) }
|
|
24
29
|
def updated_dependency_files
|
|
25
30
|
updated_files = []
|
|
26
31
|
dependency_files.each do |file|
|
|
27
|
-
next unless requirement_changed?(file, dependency)
|
|
32
|
+
next unless requirement_changed?(file, T.must(dependency))
|
|
28
33
|
|
|
29
34
|
updated_files << if file.name.match?(YAML_REGEXP)
|
|
30
35
|
updated_file(
|
|
31
36
|
file: file,
|
|
32
|
-
content: updated_yaml_content(file)
|
|
37
|
+
content: T.must(updated_yaml_content(file))
|
|
33
38
|
)
|
|
34
39
|
else
|
|
35
40
|
updated_file(
|
|
@@ -47,11 +52,13 @@ module Dependabot
|
|
|
47
52
|
|
|
48
53
|
private
|
|
49
54
|
|
|
55
|
+
sig { returns T.nilable(Dependabot::Dependency) }
|
|
50
56
|
def dependency
|
|
51
57
|
# Dockerfiles will only ever be updating a single dependency
|
|
52
58
|
dependencies.first
|
|
53
59
|
end
|
|
54
60
|
|
|
61
|
+
sig { override.void }
|
|
55
62
|
def check_required_files
|
|
56
63
|
# Just check if there are any files at all.
|
|
57
64
|
return if dependency_files.any?
|
|
@@ -59,14 +66,15 @@ module Dependabot
|
|
|
59
66
|
raise "No Dockerfile!"
|
|
60
67
|
end
|
|
61
68
|
|
|
69
|
+
sig { params(file: Dependabot::DependencyFile).returns(String) }
|
|
62
70
|
def updated_dockerfile_content(file)
|
|
63
71
|
old_sources = previous_sources(file)
|
|
64
72
|
new_sources = sources(file)
|
|
65
73
|
|
|
66
|
-
updated_content = file.content
|
|
74
|
+
updated_content = T.let(file.content, T.untyped)
|
|
67
75
|
|
|
68
|
-
old_sources.zip(new_sources).each do |old_source, new_source|
|
|
69
|
-
updated_content = update_digest_and_tag(updated_content, old_source, new_source)
|
|
76
|
+
T.must(old_sources).zip(new_sources).each do |old_source, new_source|
|
|
77
|
+
updated_content = update_digest_and_tag(updated_content, old_source, T.must(new_source))
|
|
70
78
|
end
|
|
71
79
|
|
|
72
80
|
raise "Expected content to change!" if updated_content == file.content
|
|
@@ -74,6 +82,10 @@ module Dependabot
|
|
|
74
82
|
updated_content
|
|
75
83
|
end
|
|
76
84
|
|
|
85
|
+
sig do
|
|
86
|
+
params(previous_content: String, old_source: T::Hash[Symbol, T.nilable(String)],
|
|
87
|
+
new_source: T::Hash[Symbol, T.nilable(String)]).returns(String)
|
|
88
|
+
end
|
|
77
89
|
def update_digest_and_tag(previous_content, old_source, new_source)
|
|
78
90
|
old_digest = old_source[:digest]
|
|
79
91
|
new_digest = new_source[:digest]
|
|
@@ -86,7 +98,7 @@ module Dependabot
|
|
|
86
98
|
else
|
|
87
99
|
""
|
|
88
100
|
end
|
|
89
|
-
old_declaration += dependency.name
|
|
101
|
+
old_declaration += T.must(dependency).name
|
|
90
102
|
old_declaration +=
|
|
91
103
|
if specified_with_tag?(old_source) then ":#{old_tag}"
|
|
92
104
|
else
|
|
@@ -109,36 +121,44 @@ module Dependabot
|
|
|
109
121
|
end
|
|
110
122
|
end
|
|
111
123
|
|
|
124
|
+
sig { params(source: T::Hash[Symbol, T.nilable(String)]).returns(T.nilable(String)) }
|
|
112
125
|
def specified_with_tag?(source)
|
|
113
126
|
source[:tag]
|
|
114
127
|
end
|
|
115
128
|
|
|
129
|
+
sig { params(source: T::Hash[Symbol, T.nilable(String)]).returns(T.nilable(String)) }
|
|
116
130
|
def specified_with_digest?(source)
|
|
117
131
|
source[:digest]
|
|
118
132
|
end
|
|
119
133
|
|
|
134
|
+
sig { params(file: Dependabot::DependencyFile).returns(T.nilable(T::Array[String])) }
|
|
120
135
|
def new_tags(file)
|
|
121
136
|
requirements(file)
|
|
122
137
|
.map { |r| r.fetch(:source)[:tag] }
|
|
123
138
|
end
|
|
124
139
|
|
|
140
|
+
sig { params(file: Dependabot::DependencyFile).returns(T.nilable(T::Array[String])) }
|
|
125
141
|
def old_tags(file)
|
|
126
142
|
previous_requirements(file)
|
|
127
|
-
|
|
143
|
+
&.map { |r| r.fetch(:source)[:tag] }
|
|
128
144
|
end
|
|
129
145
|
|
|
146
|
+
sig { params(source: T::Hash[Symbol, T.nilable(String)]).returns(T.nilable(String)) }
|
|
130
147
|
def private_registry_url(source)
|
|
131
148
|
source[:registry]
|
|
132
149
|
end
|
|
133
150
|
|
|
151
|
+
sig { params(file: Dependabot::DependencyFile).returns(T::Array[T::Hash[Symbol, T.nilable(String)]]) }
|
|
134
152
|
def sources(file)
|
|
135
153
|
requirements(file).map { |r| r.fetch(:source) }
|
|
136
154
|
end
|
|
137
155
|
|
|
156
|
+
sig { params(file: Dependabot::DependencyFile).returns(T.nilable(T::Array[T::Hash[Symbol, T.nilable(String)]])) }
|
|
138
157
|
def previous_sources(file)
|
|
139
|
-
previous_requirements(file)
|
|
158
|
+
previous_requirements(file)&.map { |r| r.fetch(:source) }
|
|
140
159
|
end
|
|
141
160
|
|
|
161
|
+
sig { params(file: Dependabot::DependencyFile).returns(T.nilable(String)) }
|
|
142
162
|
def updated_yaml_content(file)
|
|
143
163
|
updated_content = file.content
|
|
144
164
|
updated_content = update_helm(file, updated_content) if Utils.likely_helm_chart?(file)
|
|
@@ -149,6 +169,7 @@ module Dependabot
|
|
|
149
169
|
updated_content
|
|
150
170
|
end
|
|
151
171
|
|
|
172
|
+
sig { params(file: Dependabot::DependencyFile, content: T.nilable(String)).returns(T.nilable(String)) }
|
|
152
173
|
def update_helm(file, content)
|
|
153
174
|
# TODO: this won't work if two images have the same tag version
|
|
154
175
|
old_tags = old_helm_tags(file)
|
|
@@ -158,13 +179,14 @@ module Dependabot
|
|
|
158
179
|
|
|
159
180
|
old_tags.each do |old_tag|
|
|
160
181
|
old_tag_regex = /^\s+(?:-\s)?(?:tag|version):\s+["']?#{old_tag}["']?(?=\s|$)/
|
|
161
|
-
modified_content = modified_content
|
|
182
|
+
modified_content = modified_content&.gsub(old_tag_regex) do |old_img_tag|
|
|
162
183
|
old_img_tag.gsub(old_tag.to_s, new_helm_tag(file).to_s)
|
|
163
184
|
end
|
|
164
185
|
end
|
|
165
186
|
modified_content
|
|
166
187
|
end
|
|
167
188
|
|
|
189
|
+
sig { params(file: Dependabot::DependencyFile, content: T.nilable(String)).returns(T.nilable(String)) }
|
|
168
190
|
def update_image(file, content)
|
|
169
191
|
old_images = old_yaml_images(file)
|
|
170
192
|
return if old_images.empty?
|
|
@@ -173,53 +195,59 @@ module Dependabot
|
|
|
173
195
|
|
|
174
196
|
old_images.each do |old_image|
|
|
175
197
|
old_image_regex = /^\s*(?:-\s)?image:\s+#{old_image}(?=\s|$)/
|
|
176
|
-
modified_content = modified_content
|
|
198
|
+
modified_content = modified_content&.gsub(old_image_regex) do |old_img|
|
|
177
199
|
old_img.gsub(old_image.to_s, new_yaml_image(file).to_s)
|
|
178
200
|
end
|
|
179
201
|
end
|
|
180
202
|
modified_content
|
|
181
203
|
end
|
|
182
204
|
|
|
205
|
+
sig { params(file: Dependabot::DependencyFile).returns(String) }
|
|
183
206
|
def new_yaml_image(file)
|
|
184
|
-
element = dependency.requirements.find { |r| r[:file] == file.name }
|
|
185
|
-
prefix = element
|
|
186
|
-
digest = element
|
|
187
|
-
tag = element
|
|
188
|
-
"#{prefix}#{dependency.name}#{tag}#{digest}"
|
|
207
|
+
element = T.must(dependency).requirements.find { |r| r[:file] == file.name }
|
|
208
|
+
prefix = element&.dig(:source, :registry) ? "#{element.fetch(:source)[:registry]}/" : ""
|
|
209
|
+
digest = element&.dig(:source, :digest) ? "@sha256:#{element.fetch(:source)[:digest]}" : ""
|
|
210
|
+
tag = element&.dig(:source, :tag) ? ":#{element.fetch(:source)[:tag]}" : ""
|
|
211
|
+
"#{prefix}#{T.must(dependency).name}#{tag}#{digest}"
|
|
189
212
|
end
|
|
190
213
|
|
|
214
|
+
sig { params(file: Dependabot::DependencyFile).returns(T::Array[String]) }
|
|
191
215
|
def old_yaml_images(file)
|
|
192
|
-
previous_requirements(file).map do |r|
|
|
216
|
+
T.must(previous_requirements(file)).map do |r|
|
|
193
217
|
prefix = r.fetch(:source)[:registry] ? "#{r.fetch(:source)[:registry]}/" : ""
|
|
194
218
|
digest = r.fetch(:source)[:digest] ? "@sha256:#{r.fetch(:source)[:digest]}" : ""
|
|
195
219
|
tag = r.fetch(:source)[:tag] ? ":#{r.fetch(:source)[:tag]}" : ""
|
|
196
|
-
"#{prefix}#{dependency.name}#{tag}#{digest}"
|
|
220
|
+
"#{prefix}#{T.must(dependency).name}#{tag}#{digest}"
|
|
197
221
|
end
|
|
198
222
|
end
|
|
199
223
|
|
|
224
|
+
sig { params(file: Dependabot::DependencyFile).returns(T::Array[String]) }
|
|
200
225
|
def old_helm_tags(file)
|
|
201
|
-
previous_requirements(file).map do |r|
|
|
226
|
+
T.must(previous_requirements(file)).map do |r|
|
|
202
227
|
tag = r.fetch(:source)[:tag] || ""
|
|
203
228
|
digest = r.fetch(:source)[:digest] ? "@sha256:#{r.fetch(:source)[:digest]}" : ""
|
|
204
229
|
"#{tag}#{digest}"
|
|
205
230
|
end
|
|
206
231
|
end
|
|
207
232
|
|
|
233
|
+
sig { params(file: Dependabot::DependencyFile).returns(String) }
|
|
208
234
|
def new_helm_tag(file)
|
|
209
|
-
element = dependency.requirements.find { |r| r[:file] == file.name }
|
|
210
|
-
tag = element.
|
|
211
|
-
digest = element.
|
|
235
|
+
element = T.must(dependency).requirements.find { |r| r[:file] == file.name }
|
|
236
|
+
tag = T.must(element).dig(:source, :tag) || ""
|
|
237
|
+
digest = T.must(element).dig(:source, :digest) ? "@sha256:#{T.must(element).dig(:source, :digest)}" : ""
|
|
212
238
|
"#{tag}#{digest}"
|
|
213
239
|
end
|
|
214
240
|
|
|
241
|
+
sig { params(file: Dependabot::DependencyFile).returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
|
215
242
|
def requirements(file)
|
|
216
|
-
dependency.requirements
|
|
217
|
-
|
|
243
|
+
T.must(dependency).requirements
|
|
244
|
+
.select { |r| r[:file] == file.name }
|
|
218
245
|
end
|
|
219
246
|
|
|
247
|
+
sig { params(file: Dependabot::DependencyFile).returns T.nilable(T::Array[T::Hash[Symbol, T.untyped]]) }
|
|
220
248
|
def previous_requirements(file)
|
|
221
|
-
dependency.previous_requirements
|
|
222
|
-
|
|
249
|
+
T.must(dependency).previous_requirements
|
|
250
|
+
&.select { |r| r[:file] == file.name }
|
|
223
251
|
end
|
|
224
252
|
end
|
|
225
253
|
end
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "dependabot/metadata_finders"
|
|
5
5
|
require "dependabot/metadata_finders/base"
|
|
6
6
|
require "dependabot/shared_helpers"
|
|
7
|
+
require "sorbet-runtime"
|
|
7
8
|
|
|
8
9
|
module Dependabot
|
|
9
10
|
module Docker
|
|
10
11
|
class MetadataFinder < Dependabot::MetadataFinders::Base
|
|
12
|
+
extend T::Sig
|
|
13
|
+
|
|
11
14
|
private
|
|
12
15
|
|
|
16
|
+
sig { override.returns(T.nilable(Dependabot::Source)) }
|
|
13
17
|
def look_up_source
|
|
14
18
|
return if dependency.requirements.empty?
|
|
15
19
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "sorbet-runtime"
|
|
@@ -17,15 +17,17 @@ module Dependabot
|
|
|
17
17
|
# contains a single element.
|
|
18
18
|
sig { override.params(requirement_string: T.nilable(String)).returns(T::Array[Requirement]) }
|
|
19
19
|
def self.requirements_array(requirement_string)
|
|
20
|
-
[new(requirement_string)]
|
|
20
|
+
[new(T.must(requirement_string))]
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
sig { override.params(version: Version).returns(T::Boolean) }
|
|
23
24
|
def satisfied_by?(version)
|
|
24
25
|
super(version.release_part)
|
|
25
26
|
end
|
|
26
27
|
|
|
27
28
|
# Patches Gem::Requirement to make it accept requirement strings like
|
|
28
29
|
# "~> 4.2.5, >= 4.2.5.1" without first needing to split them.
|
|
30
|
+
sig { params(requirements: String).void }
|
|
29
31
|
def initialize(*requirements)
|
|
30
32
|
requirements = requirements.flatten.flat_map do |req_string|
|
|
31
33
|
req_string.split(",").map(&:strip)
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strong
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "dependabot/docker/file_parser"
|
|
5
|
+
require "sorbet-runtime"
|
|
5
6
|
|
|
6
7
|
module Dependabot
|
|
7
8
|
module Docker
|
|
8
9
|
class Tag
|
|
10
|
+
extend T::Sig
|
|
9
11
|
WORDS_WITH_BUILD = /(?:(?:-[a-z]+)+-[0-9]+)+/
|
|
10
12
|
VERSION_REGEX = /v?(?<version>[0-9]+(?:\.[0-9]+)*(?:_[0-9]+|\.[a-z0-9]+|#{WORDS_WITH_BUILD}|-(?:kb)?[0-9]+)*)/i
|
|
11
13
|
VERSION_WITH_SFX = /^#{VERSION_REGEX}(?<suffix>-[a-z][a-z0-9.\-]*)?$/i
|
|
@@ -17,25 +19,30 @@ module Dependabot
|
|
|
17
19
|
#{VERSION_WITH_SFX}|
|
|
18
20
|
#{VERSION_WITH_PFX_AND_SFX}
|
|
19
21
|
/x
|
|
20
|
-
|
|
22
|
+
sig { returns(String) }
|
|
21
23
|
attr_reader :name
|
|
22
24
|
|
|
25
|
+
sig { params(name: String).void }
|
|
23
26
|
def initialize(name)
|
|
24
27
|
@name = name
|
|
25
28
|
end
|
|
26
29
|
|
|
30
|
+
sig { returns(String) }
|
|
27
31
|
def to_s
|
|
28
32
|
name
|
|
29
33
|
end
|
|
30
34
|
|
|
35
|
+
sig { returns(T::Boolean) }
|
|
31
36
|
def digest?
|
|
32
37
|
name.match?(FileParser::DIGEST)
|
|
33
38
|
end
|
|
34
39
|
|
|
40
|
+
sig { returns(T.nilable(T::Boolean)) }
|
|
35
41
|
def looks_like_prerelease?
|
|
36
|
-
numeric_version
|
|
42
|
+
numeric_version&.match?(/[a-zA-Z]/)
|
|
37
43
|
end
|
|
38
44
|
|
|
45
|
+
sig { params(other: Tag).returns(T::Boolean) }
|
|
39
46
|
def comparable_to?(other)
|
|
40
47
|
return false unless comparable?
|
|
41
48
|
|
|
@@ -51,47 +58,55 @@ module Dependabot
|
|
|
51
58
|
equal_prefix && equal_format && equal_suffix
|
|
52
59
|
end
|
|
53
60
|
|
|
61
|
+
sig { returns(T::Boolean) }
|
|
54
62
|
def comparable?
|
|
55
63
|
name.match?(NAME_WITH_VERSION)
|
|
56
64
|
end
|
|
57
65
|
|
|
66
|
+
sig { params(other: Tag).returns(T::Boolean) }
|
|
58
67
|
def same_precision?(other)
|
|
59
68
|
other.precision == precision
|
|
60
69
|
end
|
|
61
70
|
|
|
71
|
+
sig { params(other: Tag).returns(T::Boolean) }
|
|
62
72
|
def same_but_less_precise?(other)
|
|
63
73
|
other.segments.zip(segments).all? do |segment, other_segment|
|
|
64
74
|
segment == other_segment || other_segment.nil?
|
|
65
75
|
end
|
|
66
76
|
end
|
|
67
77
|
|
|
78
|
+
sig { returns(T.nilable(T::Boolean)) }
|
|
68
79
|
def canonical?
|
|
69
80
|
return false unless numeric_version
|
|
70
81
|
return true if name == numeric_version
|
|
71
82
|
|
|
72
83
|
# .NET tags are suffixed with -sdk
|
|
73
|
-
return true if name == numeric_version + "-sdk"
|
|
84
|
+
return true if numeric_version && name == numeric_version.to_s + "-sdk"
|
|
74
85
|
|
|
75
|
-
name == "jdk-" + numeric_version
|
|
86
|
+
numeric_version && name == "jdk-" + T.must(numeric_version)
|
|
76
87
|
end
|
|
77
88
|
|
|
89
|
+
sig { returns T.nilable(String) }
|
|
78
90
|
def prefix
|
|
79
|
-
name.match(NAME_WITH_VERSION)
|
|
91
|
+
name.match(NAME_WITH_VERSION)&.named_captures&.fetch("prefix")
|
|
80
92
|
end
|
|
81
93
|
|
|
94
|
+
sig { returns T.nilable(String) }
|
|
82
95
|
def suffix
|
|
83
|
-
name.match(NAME_WITH_VERSION)
|
|
96
|
+
name.match(NAME_WITH_VERSION)&.named_captures&.fetch("suffix")
|
|
84
97
|
end
|
|
85
98
|
|
|
99
|
+
sig { returns T.nilable(String) }
|
|
86
100
|
def version
|
|
87
|
-
name.match(NAME_WITH_VERSION)
|
|
101
|
+
name.match(NAME_WITH_VERSION)&.named_captures&.fetch("version")
|
|
88
102
|
end
|
|
89
103
|
|
|
104
|
+
sig { returns(Symbol) }
|
|
90
105
|
def format
|
|
91
106
|
return :sha_suffixed if name.match?(/(^|\-g?)[0-9a-f]{7,}$/)
|
|
92
|
-
return :year_month if version
|
|
93
|
-
return :year_month_day if version
|
|
94
|
-
return :build_num if version
|
|
107
|
+
return :year_month if version&.match?(/^[12]\d{3}(?:[.\-]|$)/)
|
|
108
|
+
return :year_month_day if version&.match?(/^[12](?:\d{5}|\d{7})(?:[.\-]|$)/)
|
|
109
|
+
return :build_num if version&.match?(/^\d+$/)
|
|
95
110
|
|
|
96
111
|
# As an example, "21-ea-32", "22-ea-7", and "22-ea-jdk-nanoserver-1809"
|
|
97
112
|
# are mapped to "<version>-ea-<build_num>", "<version>-ea-<build_num>",
|
|
@@ -100,25 +115,28 @@ module Dependabot
|
|
|
100
115
|
# That means only "22-ea-7" will be considered as a viable update
|
|
101
116
|
# candidate for "21-ea-32", since it's the only one that respects that
|
|
102
117
|
# format.
|
|
103
|
-
if version
|
|
104
|
-
return :"<version>#{version.match(WORDS_WITH_BUILD).to_s.gsub(/-[0-9]+/, '-<build_num>')}"
|
|
118
|
+
if version&.match?(WORDS_WITH_BUILD)
|
|
119
|
+
return :"<version>#{T.must(version).match(WORDS_WITH_BUILD).to_s.gsub(/-[0-9]+/, '-<build_num>')}"
|
|
105
120
|
end
|
|
106
121
|
|
|
107
122
|
:normal
|
|
108
123
|
end
|
|
109
124
|
|
|
125
|
+
sig { returns(T.nilable(String)) }
|
|
110
126
|
def numeric_version
|
|
111
127
|
return unless comparable?
|
|
112
128
|
|
|
113
|
-
version
|
|
129
|
+
version&.gsub(/kb/i, "")&.gsub(/-[a-z]+/, "")&.downcase
|
|
114
130
|
end
|
|
115
131
|
|
|
132
|
+
sig { returns(Integer) }
|
|
116
133
|
def precision
|
|
117
134
|
segments.length
|
|
118
135
|
end
|
|
119
136
|
|
|
137
|
+
sig { returns(T::Array[String]) }
|
|
120
138
|
def segments
|
|
121
|
-
numeric_version.split(/[.-]/)
|
|
139
|
+
T.must(numeric_version).split(/[.-]/)
|
|
122
140
|
end
|
|
123
141
|
end
|
|
124
142
|
end
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "aws-sdk-ecr"
|
|
5
5
|
require "base64"
|
|
6
|
+
require "sorbet-runtime"
|
|
6
7
|
|
|
7
8
|
require "dependabot/credential"
|
|
8
9
|
require "dependabot/errors"
|
|
@@ -16,6 +17,7 @@ module Dependabot
|
|
|
16
17
|
AWS_ECR_URL = /dkr\.ecr\.(?<region>[^.]+)\.amazonaws\.com/
|
|
17
18
|
DEFAULT_DOCKER_HUB_REGISTRY = "registry.hub.docker.com"
|
|
18
19
|
|
|
20
|
+
sig { params(credentials: T::Array[Dependabot::Credential]).void }
|
|
19
21
|
def initialize(credentials)
|
|
20
22
|
@credentials = credentials
|
|
21
23
|
end
|
|
@@ -32,14 +34,20 @@ module Dependabot
|
|
|
32
34
|
build_aws_credentials(registry_details)
|
|
33
35
|
end
|
|
34
36
|
|
|
37
|
+
sig { returns(T.nilable(String)) }
|
|
35
38
|
def base_registry
|
|
36
|
-
@base_registry ||=
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
@base_registry ||= T.let(
|
|
40
|
+
credentials.find do |cred|
|
|
41
|
+
cred["type"] == "docker_registry" && cred.replaces_base?
|
|
42
|
+
end,
|
|
43
|
+
T.nilable(Dependabot::Credential)
|
|
44
|
+
)
|
|
45
|
+
@base_registry ||= Dependabot::Credential.new({ "registry" => DEFAULT_DOCKER_HUB_REGISTRY,
|
|
46
|
+
"credentials" => nil })
|
|
40
47
|
@base_registry["registry"]
|
|
41
48
|
end
|
|
42
49
|
|
|
50
|
+
sig { params(registry: String).returns(T::Boolean) }
|
|
43
51
|
def using_dockerhub?(registry)
|
|
44
52
|
registry == DEFAULT_DOCKER_HUB_REGISTRY
|
|
45
53
|
end
|
|
@@ -76,11 +84,11 @@ module Dependabot
|
|
|
76
84
|
|
|
77
85
|
# Otherwise, we need to use the provided Access Key ID and secret to
|
|
78
86
|
# generate a temporary username and password
|
|
79
|
-
@authorization_tokens ||= {}
|
|
87
|
+
@authorization_tokens ||= T.let({}, T.nilable(T::Hash[String, String]))
|
|
80
88
|
@authorization_tokens[registry_hostname] ||=
|
|
81
89
|
ecr_client.get_authorization_token.authorization_data.first.authorization_token
|
|
82
90
|
username, password =
|
|
83
|
-
Base64.decode64(@authorization_tokens[registry_hostname]).split(":")
|
|
91
|
+
Base64.decode64(T.must(@authorization_tokens[registry_hostname])).split(":")
|
|
84
92
|
registry_details.merge(Dependabot::Credential.new({ "username" => username, "password" => password }))
|
|
85
93
|
rescue Aws::Errors::MissingCredentialsError,
|
|
86
94
|
Aws::ECR::Errors::UnrecognizedClientException,
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strong
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
+
require "sorbet-runtime"
|
|
5
|
+
|
|
4
6
|
module Dependabot
|
|
5
7
|
module Docker
|
|
6
8
|
module Utils
|
|
7
9
|
HELM_REGEXP = /values[\-a-zA-Z_0-9]*\.ya?ml$/i
|
|
8
10
|
|
|
11
|
+
extend T::Sig
|
|
12
|
+
|
|
13
|
+
sig { params(file: Dependabot::DependencyFile).returns(T::Boolean) }
|
|
9
14
|
def self.likely_helm_chart?(file)
|
|
10
15
|
file.name.match?(HELM_REGEXP)
|
|
11
16
|
end
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "dependabot/version"
|
|
5
5
|
require "dependabot/utils"
|
|
6
6
|
require "dependabot/docker/tag"
|
|
7
|
+
require "sorbet-runtime"
|
|
7
8
|
|
|
8
9
|
module Dependabot
|
|
9
10
|
module Docker
|
|
@@ -13,54 +14,65 @@ module Dependabot
|
|
|
13
14
|
# for a description of Java versions.
|
|
14
15
|
#
|
|
15
16
|
class Version < Dependabot::Version
|
|
17
|
+
extend T::Sig
|
|
16
18
|
# The regex has limits for the 0,255 and 1,255 repetitions to avoid infinite limits which makes codeql angry.
|
|
17
19
|
# A docker image cannot be longer than 255 characters anyways.
|
|
18
20
|
DOCKER_VERSION_REGEX = /^(?<prefix>[a-z._\-]{0,255})[_\-v]?(?<version>.{1,255})$/
|
|
19
21
|
|
|
22
|
+
sig { override.params(version: VersionParameter).void }
|
|
20
23
|
def initialize(version)
|
|
21
|
-
parsed_version = version.match(DOCKER_VERSION_REGEX)
|
|
22
|
-
release_part, update_part = parsed_version[:version].split("_", 2)
|
|
24
|
+
parsed_version = version.to_s.match(DOCKER_VERSION_REGEX)
|
|
25
|
+
release_part, update_part = T.must(T.must(parsed_version)[:version]).split("_", 2)
|
|
23
26
|
|
|
24
27
|
# The numeric_version is needed here to validate the version string (ex: 20.9.0-alpine3.18)
|
|
25
28
|
# when the call is made via Depenedabot Api to convert the image version to semver.
|
|
26
|
-
release_part = Tag.new(release_part.chomp(".").chomp("-").chomp("_")).numeric_version
|
|
29
|
+
release_part = Tag.new(T.must(release_part).chomp(".").chomp("-").chomp("_")).numeric_version
|
|
27
30
|
|
|
28
|
-
@release_part = Dependabot::Version.new(release_part.tr("-", "."))
|
|
29
|
-
@update_part =
|
|
31
|
+
@release_part = T.let(Dependabot::Version.new(T.must(release_part).tr("-", ".")), Dependabot::Version)
|
|
32
|
+
@update_part = T.let(
|
|
33
|
+
Dependabot::Version.new(update_part&.start_with?(/[0-9]/) ? update_part : 0),
|
|
34
|
+
Dependabot::Version
|
|
35
|
+
)
|
|
30
36
|
|
|
31
37
|
super(@release_part)
|
|
32
38
|
end
|
|
33
39
|
|
|
40
|
+
sig { override.params(version: VersionParameter).returns(T::Boolean) }
|
|
34
41
|
def self.correct?(version)
|
|
35
42
|
return true if version.is_a?(Gem::Version)
|
|
36
43
|
|
|
37
44
|
# We can't call new here because Gem::Version calls self.correct? in its initialize method
|
|
38
45
|
# causing an infinite loop, so instead we check if the release_part of the version is correct
|
|
39
|
-
parsed_version = version.match(DOCKER_VERSION_REGEX)
|
|
46
|
+
parsed_version = version.to_s.match(DOCKER_VERSION_REGEX)
|
|
40
47
|
return false if parsed_version.nil?
|
|
41
48
|
|
|
42
|
-
release_part, = parsed_version[:version].split("_", 2)
|
|
43
|
-
release_part = Tag.new(release_part.chomp(".").chomp("-").chomp("_")).numeric_version || parsed_version
|
|
49
|
+
release_part, = T.must(parsed_version[:version]).split("_", 2)
|
|
50
|
+
release_part = Tag.new(T.must(release_part).chomp(".").chomp("-").chomp("_")).numeric_version || parsed_version
|
|
44
51
|
super(release_part.to_s)
|
|
45
52
|
rescue ArgumentError
|
|
46
53
|
# if we can't instantiate a version, it can't be correct
|
|
47
54
|
false
|
|
48
55
|
end
|
|
49
56
|
|
|
57
|
+
sig { override.returns(String) }
|
|
50
58
|
def to_semver
|
|
51
59
|
@release_part.to_semver
|
|
52
60
|
end
|
|
53
61
|
|
|
62
|
+
sig { returns(T::Array[String]) }
|
|
54
63
|
def segments
|
|
55
64
|
@release_part.segments
|
|
56
65
|
end
|
|
57
66
|
|
|
67
|
+
sig { returns(Dependabot::Version) }
|
|
58
68
|
attr_reader :release_part
|
|
59
69
|
|
|
70
|
+
sig { params(other: Dependabot::Docker::Version).returns(T.nilable(Integer)) }
|
|
60
71
|
def <=>(other)
|
|
61
72
|
sort_criteria <=> other.sort_criteria
|
|
62
73
|
end
|
|
63
74
|
|
|
75
|
+
sig { returns(T::Array[Dependabot::Version]) }
|
|
64
76
|
def sort_criteria
|
|
65
77
|
[@release_part, @update_part]
|
|
66
78
|
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.260.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dependabot
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-
|
|
11
|
+
date: 2024-06-06 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.260.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.
|
|
26
|
+
version: 0.260.0
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: debug
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -258,7 +258,7 @@ licenses:
|
|
|
258
258
|
- MIT
|
|
259
259
|
metadata:
|
|
260
260
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
|
261
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
|
261
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.260.0
|
|
262
262
|
post_install_message:
|
|
263
263
|
rdoc_options: []
|
|
264
264
|
require_paths:
|