Class: Dependabot::Maven::Shared::SharedPackageDetailsFetcher
- Inherits:
-
Object
- Object
- Dependabot::Maven::Shared::SharedPackageDetailsFetcher
show all
- Extended by:
- T::Helpers, T::Sig
- Defined in:
- lib/dependabot/maven/shared/shared_package_details_fetcher.rb
Constant Summary
collapse
- MAVEN_METADATA_XML =
T.let("maven-metadata.xml", String)
- REPOSITORY_TYPE =
T.let("maven_repository", String)
- URL_KEY =
T.let("url", String)
T.let("auth_headers", String)
- DEFAULT_CENTRAL_REPO_URL =
T.let("https://repo.maven.apache.org/maven2", String)
Instance Method Summary
collapse
Instance Method Details
354
355
356
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 354
def (maven_repo_url)
.(maven_repo_url)
end
|
#central_repo_url ⇒ Object
335
336
337
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 335
def central_repo_url
DEFAULT_CENTRAL_REPO_URL
end
|
#central_repo_urls ⇒ Object
341
342
343
344
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 341
def central_repo_urls
central_url_without_protocol = central_repo_url.gsub(%r{^.*://}, "")
%w(http:// https://).map { |p| p + central_url_without_protocol }
end
|
#check_response(response, repository_url) ⇒ Object
178
179
180
181
182
183
184
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 178
def check_response(response, repository_url)
return unless [401, 403].include?(response.status)
return if forbidden_urls.include?(repository_url)
return if central_repo_urls.include?(repository_url)
forbidden_urls << repository_url
end
|
#credentials ⇒ Object
30
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 30
def credentials; end
|
#credentials_repository_details ⇒ Object
320
321
322
323
324
325
326
327
328
329
330
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 320
def credentials_repository_details
credentials
.select { |cred| cred["type"] == REPOSITORY_TYPE && cred[URL_KEY] }
.map do |cred|
url_value = cred.fetch(URL_KEY).gsub(%r{/+$}, "")
{
URL_KEY => url_value,
AUTH_HEADERS_KEY => (url_value)
}
end
end
|
#dependency ⇒ Object
27
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 27
def dependency; end
|
#dependency_base_url(repository_url) ⇒ Object
58
59
60
61
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 58
def dependency_base_url(repository_url)
group_path, artifact_id = dependency_parts
"#{repository_url}/#{group_path}/#{artifact_id}"
end
|
#dependency_files_url(repository_url, version) ⇒ Object
74
75
76
77
78
79
80
81
82
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 74
def dependency_files_url(repository_url, version)
_, artifact_id = dependency_parts
base_url = dependency_base_url(repository_url)
type = dependency.requirements.first&.dig(:metadata, :packaging_type) || "jar"
classifier = dependency.requirements.first&.dig(:metadata, :classifier)
actual_classifier = classifier.nil? ? "" : "-#{classifier}"
"#{base_url}/#{version}/#{artifact_id}-#{version}#{actual_classifier}.#{type}"
end
|
367
368
369
370
371
372
373
374
375
376
377
378
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 367
def dependency_metadata(repository_details)
@dependency_metadata = T.let(
@dependency_metadata, T.nilable(T::Hash[T.untyped, Nokogiri::XML::Document])
)
@dependency_metadata ||= {}
repository_key = repository_details.hash
return @dependency_metadata[repository_key] if @dependency_metadata.key?(repository_key)
xml_document = fetch_dependency_metadata(repository_details)
@dependency_metadata[repository_key] ||= xml_document if xml_document
@dependency_metadata[repository_key]
end
|
382
383
384
385
386
387
388
389
390
391
392
393
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 382
def dependency_metadata_from_html(repository_details)
@dependency_metadata_from_html = T.let(
@dependency_metadata_from_html, T.nilable(T::Hash[T.untyped, Nokogiri::HTML::Document])
)
@dependency_metadata_from_html ||= {}
repository_key = repository_details.hash
return @dependency_metadata_from_html[repository_key] if @dependency_metadata_from_html.key?(repository_key)
html_document = fetch_dependency_metadata_from_html(repository_details)
@dependency_metadata_from_html[repository_key] ||= html_document if html_document
@dependency_metadata_from_html[repository_key]
end
|
65
66
67
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 65
def dependency_metadata_url(repository_url)
"#{dependency_base_url(repository_url)}/#{MAVEN_METADATA_XML}"
end
|
#dependency_parts ⇒ Object
44
45
46
47
48
49
50
51
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 44
def dependency_parts
@dependency_parts = T.let(@dependency_parts, T.nilable([String, String]))
return @dependency_parts if @dependency_parts
group_id, artifact_id = dependency.name.split(":")
group_path = T.must(group_id).tr(".", "/")
@dependency_parts = [group_path, T.must(artifact_id)]
end
|
114
115
116
117
118
119
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 114
def (xml, url)
xml.css("versions > version")
.select { |node| version_class.correct?(node.content) }
.map { |node| version_class.new(node.content) }
.map { |version| { version: version, source_url: url } }
end
|
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 151
def (html_doc)
versions_detail_hash = T.let({}, T::Hash[String, T::Hash[Symbol, T.untyped]])
html_doc.css("a[title]").each do |link|
version_string = link["title"]
version = version_string.gsub(%r{/$}, "")
raw_date_text = link.next.text.strip.split("\n").last.strip
release_date = begin
Time.parse(raw_date_text)
rescue StandardError
nil
end
next unless version && version_class.correct?(version)
versions_detail_hash[version] = { release_date: release_date }
end
versions_detail_hash
end
|
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 88
def fetch_dependency_metadata(repository_details)
url = repository_details.fetch(URL_KEY)
= repository_details.fetch(AUTH_HEADERS_KEY)
response = Dependabot::RegistryClient.get(
url: dependency_metadata_url(url),
headers:
)
check_response(response, url)
return unless response.status < 400
Nokogiri::XML(response.body)
rescue URI::InvalidURIError
nil
rescue Excon::Error::Socket, Excon::Error::Timeout,
Excon::Error::TooManyRedirects => e
handle_registry_error(url, e, response)
nil
end
|
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 127
def fetch_dependency_metadata_from_html(repository_details)
url = repository_details.fetch(URL_KEY)
= repository_details.fetch(AUTH_HEADERS_KEY)
response = Dependabot::RegistryClient.get(
url: dependency_base_url(url),
headers:
)
check_response(response, url)
return unless response.status < 400
Nokogiri::HTML(response.body)
rescue URI::InvalidURIError
nil
rescue Excon::Error::Socket, Excon::Error::Timeout,
Excon::Error::TooManyRedirects => e
handle_registry_error(url, e, response)
nil
end
|
#forbidden_urls ⇒ Object
347
348
349
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 347
def forbidden_urls
@forbidden_urls ||= T.let([], T.nilable(T::Array[String]))
end
|
#handle_registry_error(url, error, response) ⇒ Object
194
195
196
197
198
199
200
201
202
203
204
205
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 194
def handle_registry_error(url, error, response)
return unless central_repo_urls.include?(url)
response_status = response&.status || 0
response_body = if response
"RegistryError: #{response.status} response status with body #{response.body}"
else
"RegistryError: #{error.message}"
end
raise RegistryError.new(response_status, response_body)
end
|
#released?(version) ⇒ Boolean
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 294
def released?(version)
@released_check = T.let(@released_check, T.nilable(T::Hash[Dependabot::Version, T::Boolean]))
@released_check ||= {}
return T.must(@released_check[version]) if @released_check.key?(version)
@released_check[version] =
repositories.any? do |repository_details|
url = repository_details.fetch(URL_KEY)
= repository_details.fetch(AUTH_HEADERS_KEY)
response = Dependabot::RegistryClient.head(
url: dependency_files_url(url, version),
headers:
)
response.status < 400
rescue Excon::Error::Socket, Excon::Error::Timeout,
Excon::Error::TooManyRedirects
false
rescue URI::InvalidURIError => e
raise DependencyFileNotResolvable, e.message
end
end
|
#repositories ⇒ Object
35
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 35
def repositories; end
|
#version_class ⇒ Object
398
399
400
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 398
def version_class
dependency.version_class
end
|
#versions ⇒ Object
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 213
def versions
@version_details = T.let(@version_details, T.nilable(T::Array[T::Hash[Symbol, T.untyped]]))
return @version_details if @version_details
@version_details = versions_details_from_xml
begin
versions_details_hash = versions_details_hash_from_html if @version_details.any?
if versions_details_hash
@version_details = @version_details.map do |vd|
html_details = versions_details_hash[vd[:version].to_s]
next vd unless html_details
release_date = html_details[:release_date]
next vd unless release_date
vd.merge(
release_date: html_details[:release_date],
source_url: vd[:source_url]
)
end
end
rescue StandardError => e
Dependabot.logger.error(
"Error fetching version details from HTML: #{e.message}"
)
end
@version_details = @version_details.sort_by { |d| d.fetch(:version) }
@version_details
end
|
#versions_details_from_xml ⇒ Object
250
251
252
253
254
255
256
257
258
259
260
261
262
263
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 250
def versions_details_from_xml
forbidden_urls.clear
version_details = repositories.flat_map do |repository_details|
url = repository_details.fetch(URL_KEY)
xml = dependency_metadata(repository_details)
next [] if xml.nil?
(xml, url)
end
raise PrivateSourceAuthenticationFailure, forbidden_urls.first if version_details.none? && forbidden_urls.any?
version_details
end
|
#versions_details_hash_from_html ⇒ Object
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 267
def versions_details_hash_from_html
forbidden_urls.clear
versions_detail_hash = T.let(
{}, T::Hash[String, T::Hash[Symbol, T.untyped]]
)
repositories.each do |repository_details|
html = dependency_metadata_from_html(repository_details)
next if html.nil?
versions_detail_hash = (html)
break if versions_detail_hash.any?
end
if versions_detail_hash.any? && forbidden_urls.any?
raise PrivateSourceAuthenticationFailure,
forbidden_urls.first
end
versions_detail_hash
end
|