dependabot-composer 0.313.0 → 0.314.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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 29ab5140fc3922296ae068fc81545dbf1e01d84a2da1487c3a53181a701c7c7f
|
4
|
+
data.tar.gz: f4cb4b81173ab94e82c0651d582838d437fb87840f07e23510fa7e5777564985
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2059c491794159ad9caa2a1f3e660bfe5f08e1d594b3cbe35ad0100b197f102e68cd61327434c2ab7c1d789d9da46f0c4032cd688e7382c17a662b312bc8457f
|
7
|
+
data.tar.gz: 93afa7387f283006a6290c7e035b78460e8159e4d747214bd2965c8130057a1eaac1a7c8f70f08c275306d690b51439997f6e316599afe6516610b64144c5a7f
|
@@ -0,0 +1,284 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "json"
|
5
|
+
require "time"
|
6
|
+
require "cgi"
|
7
|
+
require "excon"
|
8
|
+
require "nokogiri"
|
9
|
+
require "sorbet-runtime"
|
10
|
+
require "dependabot/registry_client"
|
11
|
+
require "dependabot/package/package_release"
|
12
|
+
require "dependabot/package/package_details"
|
13
|
+
|
14
|
+
# Stores metadata for a package, including all its available versions
|
15
|
+
module Dependabot
|
16
|
+
module Composer
|
17
|
+
module Package
|
18
|
+
class PackageDetailsFetcher
|
19
|
+
extend T::Sig
|
20
|
+
|
21
|
+
PACKAGE_TYPE = "composer"
|
22
|
+
PACKAGE_LANGUAGE = "php"
|
23
|
+
|
24
|
+
sig do
|
25
|
+
params(
|
26
|
+
dependency: Dependabot::Dependency,
|
27
|
+
dependency_files: T::Array[Dependabot::DependencyFile],
|
28
|
+
credentials: T::Array[Dependabot::Credential],
|
29
|
+
ignored_versions: T::Array[String],
|
30
|
+
security_advisories: T::Array[Dependabot::SecurityAdvisory],
|
31
|
+
raise_on_ignored: T::Boolean
|
32
|
+
).void
|
33
|
+
end
|
34
|
+
def initialize(
|
35
|
+
dependency:,
|
36
|
+
dependency_files:,
|
37
|
+
credentials:,
|
38
|
+
ignored_versions:,
|
39
|
+
security_advisories:,
|
40
|
+
raise_on_ignored: false
|
41
|
+
)
|
42
|
+
@dependency = dependency
|
43
|
+
@dependency_files = dependency_files
|
44
|
+
@credentials = credentials
|
45
|
+
@ignored_versions = ignored_versions
|
46
|
+
@raise_on_ignored = raise_on_ignored
|
47
|
+
@security_advisories = security_advisories
|
48
|
+
|
49
|
+
@registry_urls = T.let(nil, T.nilable(T::Array[String]))
|
50
|
+
@registry_version_details = T.let(nil, T.nilable(T::Array[T::Hash[String, T.untyped]]))
|
51
|
+
end
|
52
|
+
|
53
|
+
sig { returns(Dependabot::Dependency) }
|
54
|
+
attr_reader :dependency
|
55
|
+
|
56
|
+
sig { returns(T::Array[T.untyped]) }
|
57
|
+
attr_reader :dependency_files
|
58
|
+
|
59
|
+
sig { returns(T::Array[T.untyped]) }
|
60
|
+
attr_reader :credentials
|
61
|
+
|
62
|
+
sig { returns(T::Array[String]) }
|
63
|
+
attr_reader :ignored_versions
|
64
|
+
|
65
|
+
sig { returns(T::Array[Dependabot::SecurityAdvisory]) }
|
66
|
+
attr_reader :security_advisories
|
67
|
+
|
68
|
+
sig { returns(T::Array[Dependabot::Package::PackageRelease]) }
|
69
|
+
def fetch_releases
|
70
|
+
available_version_details = registry_version_details
|
71
|
+
.select do |version_details|
|
72
|
+
version = version_details.fetch("version")
|
73
|
+
version && version_class.correct?(version.gsub(/^v/, ""))
|
74
|
+
end
|
75
|
+
|
76
|
+
releases = available_version_details.map do |version_details|
|
77
|
+
format_version_release(version_details)
|
78
|
+
end
|
79
|
+
releases
|
80
|
+
end
|
81
|
+
|
82
|
+
sig { returns(Dependabot::Package::PackageDetails) }
|
83
|
+
def fetch
|
84
|
+
available_version_details = registry_version_details
|
85
|
+
.select do |version_details|
|
86
|
+
version = version_details.fetch("version")
|
87
|
+
version && version_class.correct?(version.gsub(/^v/, ""))
|
88
|
+
end
|
89
|
+
|
90
|
+
releases = available_version_details.map do |version_details|
|
91
|
+
format_version_release(version_details)
|
92
|
+
end
|
93
|
+
Dependabot::Package::PackageDetails.new(
|
94
|
+
dependency: dependency,
|
95
|
+
releases: releases.reverse.uniq(&:version)
|
96
|
+
)
|
97
|
+
end
|
98
|
+
|
99
|
+
sig do
|
100
|
+
returns(T::Array[T::Hash[String, T.untyped]])
|
101
|
+
end
|
102
|
+
def registry_version_details
|
103
|
+
return @registry_version_details unless @registry_version_details.nil?
|
104
|
+
|
105
|
+
repositories =
|
106
|
+
JSON.parse(T.must(composer_file.content))
|
107
|
+
.fetch("repositories", [])
|
108
|
+
.select { |r| r.is_a?(Hash) }
|
109
|
+
|
110
|
+
urls = repositories
|
111
|
+
.select { |h| h["type"] == PackageManager::NAME }
|
112
|
+
.filter_map { |h| h["url"] }
|
113
|
+
.map { |url| url.gsub(%r{\/$}, "") + "/packages.json" }
|
114
|
+
|
115
|
+
unless repositories.any? { |rep| rep["packagist.org"] == false }
|
116
|
+
urls << "https://repo.packagist.org/p2/#{dependency.name.downcase}.json"
|
117
|
+
end
|
118
|
+
|
119
|
+
@registry_version_details = []
|
120
|
+
urls.each do |url|
|
121
|
+
@registry_version_details += fetch_registry_versions_from_url(url)
|
122
|
+
end
|
123
|
+
|
124
|
+
@registry_version_details.uniq! { |version_details| version_details["version"] }
|
125
|
+
@registry_version_details
|
126
|
+
end
|
127
|
+
|
128
|
+
sig { params(url: String).returns(T::Array[T::Hash[String, T.untyped]]) }
|
129
|
+
def fetch_registry_versions_from_url(url)
|
130
|
+
url_host = URI(url).host
|
131
|
+
cred = registry_credentials.find { |c| url_host == c["registry"] || url_host == URI(T.must(c["registry"])).host } # rubocop:disable Layout/LineLength
|
132
|
+
|
133
|
+
response = Dependabot::RegistryClient.get(
|
134
|
+
url: url,
|
135
|
+
options: {
|
136
|
+
user: cred&.fetch("username", nil),
|
137
|
+
password: cred&.fetch("password", nil)
|
138
|
+
}
|
139
|
+
)
|
140
|
+
|
141
|
+
parse_registry_response(response, url)
|
142
|
+
rescue Excon::Error::Socket, Excon::Error::Timeout
|
143
|
+
[]
|
144
|
+
end
|
145
|
+
|
146
|
+
sig { params(response: T.untyped, url: String).returns(T::Array[T::Hash[String, T.untyped]]) }
|
147
|
+
def parse_registry_response(response, url)
|
148
|
+
return [] unless response.status == 200
|
149
|
+
|
150
|
+
listing = JSON.parse(response.body)
|
151
|
+
return [] if listing.nil?
|
152
|
+
return [] unless listing.is_a?(Hash)
|
153
|
+
return [] if listing.fetch("packages", []) == []
|
154
|
+
return [] unless listing.dig("packages", dependency.name.downcase)
|
155
|
+
|
156
|
+
extract_versions(listing)
|
157
|
+
rescue JSON::ParserError
|
158
|
+
msg = "'#{url}' does not contain valid JSON"
|
159
|
+
raise DependencyFileNotResolvable, msg
|
160
|
+
end
|
161
|
+
|
162
|
+
sig { params(listing: T::Hash[String, T.untyped]).returns(T::Array[T::Hash[String, T.untyped]]) }
|
163
|
+
def extract_versions(listing)
|
164
|
+
# Packagist's Metadata API format:
|
165
|
+
# v1: "packages": {<package name>: {<version_number>: {hash of metadata for a particular release version}}}
|
166
|
+
# v2: "packages": {<package name>: [{hash of metadata for a particular release version}]}
|
167
|
+
version_listings = listing.dig("packages", dependency.name.downcase)
|
168
|
+
|
169
|
+
if version_listings.is_a?(Hash) # some private registries are still using the v1 format
|
170
|
+
# Regardless of API version, composer always reads the version from the metadata hash. So for the v1 API,
|
171
|
+
# ignore the keys as repositories other than packagist.org could be using different keys. Instead, coerce
|
172
|
+
# to an array of metadata hashes to match v2 format.
|
173
|
+
version_listings = version_listings.values
|
174
|
+
end
|
175
|
+
|
176
|
+
if version_listings.is_a?(Array)
|
177
|
+
version_listings
|
178
|
+
else
|
179
|
+
[]
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
sig do
|
184
|
+
params(
|
185
|
+
release_data: T::Hash[String, T.untyped]
|
186
|
+
)
|
187
|
+
.returns(Dependabot::Package::PackageRelease)
|
188
|
+
end
|
189
|
+
def format_version_release(release_data)
|
190
|
+
version = release_data["version"].gsub(/^v/, "")
|
191
|
+
released_at = release_data["time"] ? Time.parse(release_data["time"]) : nil # this will return nil if the time key is missing, avoiding error # rubocop:disable Layout/LineLength
|
192
|
+
url = release_data["dist"] ? release_data["dist"]["url"] : nil
|
193
|
+
package_type = PACKAGE_TYPE
|
194
|
+
|
195
|
+
package_release(
|
196
|
+
version: version,
|
197
|
+
released_at: released_at,
|
198
|
+
url: url,
|
199
|
+
package_type: package_type
|
200
|
+
)
|
201
|
+
end
|
202
|
+
|
203
|
+
sig do
|
204
|
+
params(
|
205
|
+
version: String,
|
206
|
+
released_at: T.nilable(Time),
|
207
|
+
downloads: T.nilable(Integer),
|
208
|
+
url: T.nilable(String),
|
209
|
+
yanked: T::Boolean,
|
210
|
+
package_type: T.nilable(String)
|
211
|
+
).returns(Dependabot::Package::PackageRelease)
|
212
|
+
end
|
213
|
+
def package_release(version:, released_at:, downloads: nil, url: nil, yanked: false, package_type: nil)
|
214
|
+
Dependabot::Package::PackageRelease.new(
|
215
|
+
version: Composer::Version.new(version),
|
216
|
+
released_at: released_at,
|
217
|
+
yanked: yanked,
|
218
|
+
yanked_reason: nil,
|
219
|
+
downloads: downloads,
|
220
|
+
url: url,
|
221
|
+
package_type: package_type,
|
222
|
+
language: nil
|
223
|
+
)
|
224
|
+
end
|
225
|
+
|
226
|
+
sig { returns(Dependabot::DependencyFile) }
|
227
|
+
def composer_file
|
228
|
+
composer_file =
|
229
|
+
dependency_files.find do |f|
|
230
|
+
f.name == PackageManager::MANIFEST_FILENAME
|
231
|
+
end
|
232
|
+
raise "No #{PackageManager::MANIFEST_FILENAME}!" unless composer_file
|
233
|
+
|
234
|
+
composer_file
|
235
|
+
end
|
236
|
+
|
237
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
238
|
+
def registry_credentials
|
239
|
+
credentials.select { |cred| cred["type"] == PackageManager::REPOSITORY_KEY } +
|
240
|
+
auth_json_credentials
|
241
|
+
end
|
242
|
+
|
243
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
244
|
+
def auth_json_credentials
|
245
|
+
json = auth_json
|
246
|
+
return [] unless json
|
247
|
+
|
248
|
+
parsed_auth_json = JSON.parse(T.must(json.content))
|
249
|
+
parsed_auth_json.fetch("http-basic", {}).map do |reg, details|
|
250
|
+
Dependabot::Credential.new({
|
251
|
+
"registry" => reg,
|
252
|
+
"username" => details["username"],
|
253
|
+
"password" => details["password"]
|
254
|
+
})
|
255
|
+
end
|
256
|
+
rescue JSON::ParserError
|
257
|
+
raise Dependabot::DependencyFileNotParseable, json.path if json
|
258
|
+
|
259
|
+
raise Dependabot::DependencyFileNotParseable, "Unknown path"
|
260
|
+
end
|
261
|
+
|
262
|
+
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
263
|
+
def auth_json
|
264
|
+
dependency_files.find { |f| f.name == PackageManager::AUTH_FILENAME }
|
265
|
+
end
|
266
|
+
|
267
|
+
sig { returns(T::Array[Dependabot::Requirement]) }
|
268
|
+
def ignore_requirements
|
269
|
+
ignored_versions.map { |req| requirement_class.new(req.split(",")) }
|
270
|
+
end
|
271
|
+
|
272
|
+
sig { returns(T.class_of(Dependabot::Version)) }
|
273
|
+
def version_class
|
274
|
+
dependency.version_class
|
275
|
+
end
|
276
|
+
|
277
|
+
sig { returns(T.class_of(Dependabot::Requirement)) }
|
278
|
+
def requirement_class
|
279
|
+
dependency.requirement_class
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
@@ -9,112 +9,61 @@ require "dependabot/composer/update_checker"
|
|
9
9
|
require "dependabot/update_checkers/version_filters"
|
10
10
|
require "dependabot/shared_helpers"
|
11
11
|
require "dependabot/errors"
|
12
|
+
require "dependabot/composer/package/package_details_fetcher"
|
13
|
+
require "dependabot/package/package_latest_version_finder"
|
12
14
|
|
13
15
|
module Dependabot
|
14
16
|
module Composer
|
15
17
|
class UpdateChecker
|
16
|
-
class LatestVersionFinder
|
18
|
+
class LatestVersionFinder < Dependabot::Package::PackageLatestVersionFinder
|
17
19
|
extend T::Sig
|
18
20
|
|
19
|
-
sig
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
).void
|
28
|
-
end
|
29
|
-
def initialize(dependency:, dependency_files:, credentials:, ignored_versions:, security_advisories:,
|
30
|
-
raise_on_ignored: false)
|
31
|
-
@dependency = dependency
|
32
|
-
@dependency_files = dependency_files
|
33
|
-
@credentials = credentials
|
34
|
-
@ignored_versions = ignored_versions
|
35
|
-
@raise_on_ignored = raise_on_ignored
|
36
|
-
@security_advisories = security_advisories
|
37
|
-
end
|
38
|
-
|
39
|
-
sig { returns(T.nilable(Dependabot::Version)) }
|
40
|
-
def latest_version
|
41
|
-
@latest_version ||= T.let(
|
42
|
-
fetch_latest_version,
|
43
|
-
T.nilable(Dependabot::Version)
|
21
|
+
sig { returns(Package::PackageDetailsFetcher) }
|
22
|
+
def fetcher
|
23
|
+
Package::PackageDetailsFetcher.new(
|
24
|
+
dependency: dependency,
|
25
|
+
dependency_files: dependency_files,
|
26
|
+
credentials: credentials,
|
27
|
+
ignored_versions: ignored_versions,
|
28
|
+
security_advisories: security_advisories
|
44
29
|
)
|
45
30
|
end
|
46
31
|
|
47
|
-
sig
|
48
|
-
|
49
|
-
@lowest_security_fix_version ||= T.let(
|
50
|
-
fetch_lowest_security_fix_version,
|
51
|
-
T.nilable(Dependabot::Version)
|
52
|
-
)
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
sig { returns(Dependabot::Dependency) }
|
58
|
-
attr_reader :dependency
|
59
|
-
|
60
|
-
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
61
|
-
attr_reader :dependency_files
|
62
|
-
|
63
|
-
sig { returns(T::Array[Dependabot::Credential]) }
|
64
|
-
attr_reader :credentials
|
65
|
-
|
66
|
-
sig { returns(T::Array[String]) }
|
67
|
-
attr_reader :ignored_versions
|
68
|
-
|
69
|
-
sig { returns(T::Array[Dependabot::SecurityAdvisory]) }
|
70
|
-
attr_reader :security_advisories
|
71
|
-
|
72
|
-
sig { returns(T.nilable(Dependabot::Version)) }
|
73
|
-
def fetch_latest_version
|
74
|
-
versions = available_versions
|
75
|
-
versions = filter_prerelease_versions(versions)
|
76
|
-
versions = filter_ignored_versions(versions)
|
77
|
-
versions.max
|
32
|
+
sig do
|
33
|
+
override.returns(T.nilable(Dependabot::Package::PackageDetails))
|
78
34
|
end
|
79
|
-
|
80
|
-
|
81
|
-
def fetch_lowest_security_fix_version
|
82
|
-
versions = available_versions
|
83
|
-
versions = filter_prerelease_versions(versions)
|
84
|
-
versions = Dependabot::UpdateCheckers::VersionFilters.filter_vulnerable_versions(versions,
|
85
|
-
security_advisories)
|
86
|
-
versions = filter_ignored_versions(versions)
|
87
|
-
versions = filter_lower_versions(versions)
|
88
|
-
|
89
|
-
versions.min
|
35
|
+
def package_details
|
36
|
+
@package_details ||= fetcher.fetch
|
90
37
|
end
|
91
38
|
|
92
|
-
|
93
|
-
def filter_prerelease_versions(versions_array)
|
94
|
-
return versions_array if wants_prerelease?
|
39
|
+
private
|
95
40
|
|
96
|
-
|
41
|
+
sig do
|
42
|
+
override
|
43
|
+
.params(language_version: T.nilable(T.any(String, Dependabot::Version)))
|
44
|
+
.returns(T.nilable(Dependabot::Version))
|
97
45
|
end
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
if @raise_on_ignored && filter_lower_versions(filtered).empty? && filter_lower_versions(versions_array).any?
|
106
|
-
raise AllVersionsIgnored
|
107
|
-
end
|
108
|
-
|
109
|
-
filtered
|
46
|
+
def fetch_latest_version(language_version: nil) # rubocop:disable Lint/UnusedMethodArgument
|
47
|
+
releases = available_versions
|
48
|
+
releases = filter_prerelease_versions(releases)
|
49
|
+
releases = filter_ignored_versions(releases)
|
50
|
+
releases = filter_by_cooldown(releases)
|
51
|
+
releases.max_by(&:version)&.version
|
110
52
|
end
|
111
53
|
|
112
|
-
sig
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
54
|
+
sig do
|
55
|
+
override
|
56
|
+
.params(language_version: T.nilable(T.any(String, Dependabot::Version)))
|
57
|
+
.returns(T.nilable(Dependabot::Version))
|
58
|
+
end
|
59
|
+
def fetch_lowest_security_fix_version(language_version: nil) # rubocop:disable Lint/UnusedMethodArgument
|
60
|
+
releases = available_versions
|
61
|
+
releases = filter_prerelease_versions(releases)
|
62
|
+
releases = Dependabot::UpdateCheckers::VersionFilters.filter_vulnerable_versions(releases,
|
63
|
+
security_advisories)
|
64
|
+
releases = filter_ignored_versions(releases)
|
65
|
+
releases = filter_lower_versions(releases)
|
66
|
+
releases.min_by(&:version)&.version
|
118
67
|
end
|
119
68
|
|
120
69
|
sig { returns(T::Boolean) }
|
@@ -127,150 +76,29 @@ module Dependabot
|
|
127
76
|
end
|
128
77
|
end
|
129
78
|
|
130
|
-
sig { returns(T::
|
131
|
-
def
|
132
|
-
|
133
|
-
.select { |version| version_class.correct?(version.gsub(/^v/, "")) }
|
134
|
-
.map { |version| version_class.new(version.gsub(/^v/, "")) }
|
135
|
-
end
|
136
|
-
|
137
|
-
sig { returns(T::Array[String]) }
|
138
|
-
def registry_version_details
|
139
|
-
return @registry_version_details unless @registry_version_details.nil?
|
140
|
-
|
141
|
-
repositories =
|
142
|
-
JSON.parse(T.must(composer_file.content))
|
143
|
-
.fetch("repositories", [])
|
144
|
-
.select { |r| r.is_a?(Hash) }
|
145
|
-
|
146
|
-
urls = repositories
|
147
|
-
.select { |h| h["type"] == PackageManager::NAME }
|
148
|
-
.filter_map { |h| h["url"] }
|
149
|
-
.map { |url| url.gsub(%r{\/$}, "") + "/packages.json" }
|
150
|
-
|
151
|
-
unless repositories.any? { |rep| rep["packagist.org"] == false }
|
152
|
-
urls << "https://repo.packagist.org/p2/#{dependency.name.downcase}.json"
|
153
|
-
end
|
154
|
-
|
155
|
-
@registry_version_details ||= T.let([], T.nilable(T::Array[String]))
|
156
|
-
urls.each do |url|
|
157
|
-
@registry_version_details += fetch_registry_versions_from_url(url)
|
158
|
-
end
|
159
|
-
@registry_version_details.uniq
|
79
|
+
sig { returns(T::Boolean) }
|
80
|
+
def cooldown_enabled?
|
81
|
+
Dependabot::Experiments.enabled?(:enable_cooldown_for_composer)
|
160
82
|
end
|
161
83
|
|
162
|
-
sig {
|
163
|
-
def
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
parse_registry_response(response, url)
|
84
|
+
sig { returns(T::Array[Dependabot::Package::PackageRelease]) }
|
85
|
+
def available_versions
|
86
|
+
Package::PackageDetailsFetcher.new(
|
87
|
+
dependency: dependency,
|
88
|
+
dependency_files: dependency_files,
|
89
|
+
credentials: credentials,
|
90
|
+
ignored_versions: ignored_versions,
|
91
|
+
security_advisories: security_advisories,
|
92
|
+
raise_on_ignored: false
|
93
|
+
).fetch_releases
|
94
|
+
end
|
95
|
+
|
96
|
+
sig { params(_url: String).returns(T::Array[String]) }
|
97
|
+
def fetch_registry_versions_from_url(_url)
|
98
|
+
[]
|
178
99
|
rescue Excon::Error::Socket, Excon::Error::Timeout
|
179
100
|
[]
|
180
101
|
end
|
181
|
-
|
182
|
-
sig { params(response: T.untyped, url: String).returns(T::Array[String]) }
|
183
|
-
def parse_registry_response(response, url)
|
184
|
-
return [] unless response.status == 200
|
185
|
-
|
186
|
-
listing = JSON.parse(response.body)
|
187
|
-
return [] if listing.nil?
|
188
|
-
return [] unless listing.is_a?(Hash)
|
189
|
-
return [] if listing.fetch("packages", []) == []
|
190
|
-
return [] unless listing.dig("packages", dependency.name.downcase)
|
191
|
-
|
192
|
-
extract_versions(listing)
|
193
|
-
rescue JSON::ParserError
|
194
|
-
msg = "'#{url}' does not contain valid JSON"
|
195
|
-
raise DependencyFileNotResolvable, msg
|
196
|
-
end
|
197
|
-
|
198
|
-
sig { params(listing: T::Hash[String, T.untyped]).returns(T::Array[String]) }
|
199
|
-
def extract_versions(listing)
|
200
|
-
# Packagist's Metadata API format:
|
201
|
-
# v1: "packages": {<package name>: {<version_number>: {hash of metadata for a particular release version}}}
|
202
|
-
# v2: "packages": {<package name>: [{hash of metadata for a particular release version}]}
|
203
|
-
version_listings = listing.dig("packages", dependency.name.downcase)
|
204
|
-
|
205
|
-
if version_listings.is_a?(Hash) # some private registries are still using the v1 format
|
206
|
-
# Regardless of API version, composer always reads the version from the metadata hash. So for the v1 API,
|
207
|
-
# ignore the keys as repositories other than packagist.org could be using different keys. Instead, coerce
|
208
|
-
# to an array of metadata hashes to match v2 format.
|
209
|
-
version_listings = version_listings.values
|
210
|
-
end
|
211
|
-
|
212
|
-
if version_listings.is_a?(Array)
|
213
|
-
version_listings.map { |i| i.fetch("version") }
|
214
|
-
else
|
215
|
-
[]
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
sig { returns(T::Array[Dependabot::Credential]) }
|
220
|
-
def registry_credentials
|
221
|
-
credentials.select { |cred| cred["type"] == PackageManager::REPOSITORY_KEY } +
|
222
|
-
auth_json_credentials
|
223
|
-
end
|
224
|
-
|
225
|
-
sig { returns(T::Array[Dependabot::Credential]) }
|
226
|
-
def auth_json_credentials
|
227
|
-
json = auth_json
|
228
|
-
return [] unless json
|
229
|
-
|
230
|
-
parsed_auth_json = JSON.parse(T.must(json.content))
|
231
|
-
parsed_auth_json.fetch("http-basic", {}).map do |reg, details|
|
232
|
-
Dependabot::Credential.new({
|
233
|
-
"registry" => reg,
|
234
|
-
"username" => details["username"],
|
235
|
-
"password" => details["password"]
|
236
|
-
})
|
237
|
-
end
|
238
|
-
rescue JSON::ParserError
|
239
|
-
raise Dependabot::DependencyFileNotParseable, json.path if json
|
240
|
-
|
241
|
-
raise Dependabot::DependencyFileNotParseable, "Unknown path"
|
242
|
-
end
|
243
|
-
|
244
|
-
sig { returns(Dependabot::DependencyFile) }
|
245
|
-
def composer_file
|
246
|
-
composer_file =
|
247
|
-
dependency_files.find do |f|
|
248
|
-
f.name == PackageManager::MANIFEST_FILENAME
|
249
|
-
end
|
250
|
-
raise "No #{PackageManager::MANIFEST_FILENAME}!" unless composer_file
|
251
|
-
|
252
|
-
composer_file
|
253
|
-
end
|
254
|
-
|
255
|
-
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
256
|
-
def auth_json
|
257
|
-
dependency_files.find { |f| f.name == PackageManager::AUTH_FILENAME }
|
258
|
-
end
|
259
|
-
|
260
|
-
sig { returns(T::Array[Dependabot::Requirement]) }
|
261
|
-
def ignore_requirements
|
262
|
-
ignored_versions.map { |req| requirement_class.new(req.split(",")) }
|
263
|
-
end
|
264
|
-
|
265
|
-
sig { returns(T.class_of(Dependabot::Version)) }
|
266
|
-
def version_class
|
267
|
-
dependency.version_class
|
268
|
-
end
|
269
|
-
|
270
|
-
sig { returns(T.class_of(Dependabot::Requirement)) }
|
271
|
-
def requirement_class
|
272
|
-
dependency.requirement_class
|
273
|
-
end
|
274
102
|
end
|
275
103
|
end
|
276
104
|
end
|
@@ -125,7 +125,8 @@ module Dependabot
|
|
125
125
|
credentials: credentials,
|
126
126
|
ignored_versions: ignored_versions,
|
127
127
|
raise_on_ignored: raise_on_ignored,
|
128
|
-
security_advisories: security_advisories
|
128
|
+
security_advisories: security_advisories,
|
129
|
+
cooldown_options: update_cooldown
|
129
130
|
),
|
130
131
|
T.nilable(Dependabot::Composer::UpdateChecker::LatestVersionFinder)
|
131
132
|
)
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dependabot-composer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.314.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dependabot
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-05-
|
10
|
+
date: 2025-05-22 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: dependabot-common
|
@@ -15,14 +15,14 @@ dependencies:
|
|
15
15
|
requirements:
|
16
16
|
- - '='
|
17
17
|
- !ruby/object:Gem::Version
|
18
|
-
version: 0.
|
18
|
+
version: 0.314.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.
|
25
|
+
version: 0.314.0
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: debug
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
@@ -267,6 +267,7 @@ files:
|
|
267
267
|
- lib/dependabot/composer/language.rb
|
268
268
|
- lib/dependabot/composer/metadata_finder.rb
|
269
269
|
- lib/dependabot/composer/native_helpers.rb
|
270
|
+
- lib/dependabot/composer/package/package_details_fetcher.rb
|
270
271
|
- lib/dependabot/composer/package_manager.rb
|
271
272
|
- lib/dependabot/composer/requirement.rb
|
272
273
|
- lib/dependabot/composer/update_checker.rb
|
@@ -279,7 +280,7 @@ licenses:
|
|
279
280
|
- MIT
|
280
281
|
metadata:
|
281
282
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
282
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
283
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.314.0
|
283
284
|
rdoc_options: []
|
284
285
|
require_paths:
|
285
286
|
- lib
|