dependabot-npm_and_yarn 0.321.2 → 0.322.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/npm_and_yarn/file_parser.rb +1 -1
- data/lib/dependabot/npm_and_yarn/package/package_details_fetcher.rb +2 -4
- data/lib/dependabot/npm_and_yarn/update_checker/latest_version_finder.rb +40 -591
- data/lib/dependabot/npm_and_yarn/update_checker/version_resolver.rb +12 -32
- data/lib/dependabot/npm_and_yarn/update_checker.rb +12 -33
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5696d15f208114a1f4afe849864fd02e55b43b635ba5712ae75d0028d753c780
|
4
|
+
data.tar.gz: 3e3e0bca818a95047184b22c4ca282757cba9cf2e7c233cc7299bb737169c587
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 771b5ce91963efee5347d1810af25099e029d0176e8add5848078bfcf4f2b6c2d028f12dda1734e576025e849223909b204047c969d10114108aa2160c459955
|
7
|
+
data.tar.gz: 7ea48759951bca676405704fd02070e55ebee6816fdb5ca624155bb950373e7ca0fbc8aa357ed29f931a013ab6f7e153751d7f94c03269b0ac4264fb8dbdc949
|
@@ -173,13 +173,11 @@ module Dependabot
|
|
173
173
|
|
174
174
|
package_type = infer_package_type(details)
|
175
175
|
|
176
|
-
deprecated = fetch_value_from_hash(details, RELEASE_DEPRECATION_KEY)
|
177
|
-
|
178
176
|
Dependabot::Package::PackageRelease.new(
|
179
177
|
version: Version.new(version),
|
180
178
|
released_at: time_data[version] ? Time.parse(time_data[version]) : nil,
|
181
|
-
yanked:
|
182
|
-
yanked_reason:
|
179
|
+
yanked: false,
|
180
|
+
yanked_reason: nil,
|
183
181
|
downloads: nil,
|
184
182
|
latest: latest_version.to_s == version,
|
185
183
|
url: package_version_url(version),
|
@@ -74,12 +74,14 @@ module Dependabot
|
|
74
74
|
override.params(language_version: T.nilable(T.any(String, Dependabot::Version)))
|
75
75
|
.returns(T.nilable(Dependabot::Version))
|
76
76
|
end
|
77
|
-
def latest_version_with_no_unlock(language_version: nil)
|
77
|
+
def latest_version_with_no_unlock(language_version: nil) # rubocop:disable Lint/UnusedMethodArgument
|
78
78
|
with_custom_registry_rescue do
|
79
79
|
return unless valid_npm_details?
|
80
80
|
return version_from_dist_tags&.version if specified_dist_tag_requirement?
|
81
81
|
|
82
|
-
|
82
|
+
releases = possible_releases
|
83
|
+
in_range_versions = filter_out_of_range_versions(releases)
|
84
|
+
in_range_versions.find { |r| !yanked_version?(r.version) }&.version
|
83
85
|
end
|
84
86
|
end
|
85
87
|
|
@@ -96,7 +98,7 @@ module Dependabot
|
|
96
98
|
params(language_version: T.nilable(T.any(String, Dependabot::Version)))
|
97
99
|
.returns(T.nilable(Dependabot::Version))
|
98
100
|
end
|
99
|
-
def fetch_latest_version(language_version: nil)
|
101
|
+
def fetch_latest_version(language_version: nil) # rubocop:disable Lint/UnusedMethodArgument
|
100
102
|
with_custom_registry_rescue do
|
101
103
|
return unless valid_npm_details?
|
102
104
|
|
@@ -105,7 +107,7 @@ module Dependabot
|
|
105
107
|
|
106
108
|
return if specified_dist_tag_requirement?
|
107
109
|
|
108
|
-
|
110
|
+
possible_releases.find { |r| !yanked_version?(r.version) }&.version
|
109
111
|
end
|
110
112
|
end
|
111
113
|
|
@@ -114,65 +116,16 @@ module Dependabot
|
|
114
116
|
.params(language_version: T.nilable(T.any(String, Dependabot::Version)))
|
115
117
|
.returns(T.nilable(Dependabot::Version))
|
116
118
|
end
|
117
|
-
def fetch_latest_version_with_no_unlock(language_version: nil)
|
119
|
+
def fetch_latest_version_with_no_unlock(language_version: nil) # rubocop:disable Lint/UnusedMethodArgument
|
118
120
|
with_custom_registry_rescue do
|
119
121
|
return unless valid_npm_details?
|
120
122
|
return version_from_dist_tags&.version if specified_dist_tag_requirement?
|
121
123
|
|
122
|
-
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
sig do
|
127
|
-
override
|
128
|
-
.params(releases: T::Array[Dependabot::Package::PackageRelease])
|
129
|
-
.returns(T::Array[Dependabot::Package::PackageRelease])
|
130
|
-
end
|
131
|
-
def apply_post_fetch_latest_versions_filter(releases)
|
132
|
-
original_count = releases.count
|
133
|
-
filtered_versions = lazy_filter_yanked_versions_by_min_max(releases, check_max: true)
|
134
|
-
|
135
|
-
# Log the filter if any versions were removed
|
136
|
-
if original_count > filtered_versions.count
|
137
|
-
Dependabot.logger.info(
|
138
|
-
"Filtered out #{original_count - filtered_versions.count} " \
|
139
|
-
"yanked (not found) versions after fetching latest versions"
|
140
|
-
)
|
141
|
-
end
|
142
|
-
|
143
|
-
filtered_versions
|
144
|
-
end
|
145
|
-
|
146
|
-
sig do
|
147
|
-
params(
|
148
|
-
releases: T::Array[Dependabot::Package::PackageRelease],
|
149
|
-
check_max: T::Boolean
|
150
|
-
).returns(T::Array[Dependabot::Package::PackageRelease])
|
151
|
-
end
|
152
|
-
def lazy_filter_yanked_versions_by_min_max(releases, check_max: true)
|
153
|
-
# Sort the versions based on the check_max flag (max -> descending, min -> ascending)
|
154
|
-
sorted_releases = if check_max
|
155
|
-
releases.sort_by(&:version).reverse
|
156
|
-
else
|
157
|
-
releases.sort_by(&:version)
|
158
|
-
end
|
159
|
-
|
160
|
-
filtered_versions = []
|
124
|
+
releases = possible_releases
|
161
125
|
|
162
|
-
|
163
|
-
|
164
|
-
# Iterate through the sorted versions lazily, filtering out yanked versions
|
165
|
-
sorted_releases.each do |release|
|
166
|
-
next if !not_yanked && yanked_version?(release.version)
|
167
|
-
|
168
|
-
not_yanked = true
|
169
|
-
|
170
|
-
# Once we find a valid (non-yanked) version, add it to the filtered list
|
171
|
-
filtered_versions << release
|
172
|
-
break
|
126
|
+
in_range_versions = filter_out_of_range_versions(releases)
|
127
|
+
in_range_versions.find { |r| !yanked_version?(r.version) }&.version
|
173
128
|
end
|
174
|
-
|
175
|
-
filtered_versions
|
176
129
|
end
|
177
130
|
|
178
131
|
sig do
|
@@ -200,11 +153,10 @@ module Dependabot
|
|
200
153
|
secure_versions = filter_ignored_versions(secure_versions)
|
201
154
|
secure_versions = filter_lower_versions(secure_versions)
|
202
155
|
|
203
|
-
#
|
204
|
-
secure_versions
|
205
|
-
|
206
|
-
|
207
|
-
secure_versions.max_by(&:version)&.version
|
156
|
+
# Find first non-yanked version
|
157
|
+
secure_versions.sort_by(&:version).find do |version|
|
158
|
+
!yanked_version?(version.version)
|
159
|
+
end&.version
|
208
160
|
end
|
209
161
|
end
|
210
162
|
|
@@ -213,17 +165,16 @@ module Dependabot
|
|
213
165
|
.returns(T::Array[Dependabot::Package::PackageRelease])
|
214
166
|
end
|
215
167
|
def filter_prerelease_versions(releases)
|
216
|
-
|
168
|
+
releases.reject do |release|
|
217
169
|
release.version.prerelease? && !related_to_current_pre?(release.version)
|
218
170
|
end
|
171
|
+
end
|
219
172
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
filtered
|
173
|
+
sig do
|
174
|
+
override.returns(T.nilable(T::Array[Dependabot::Package::PackageRelease]))
|
175
|
+
end
|
176
|
+
def available_versions
|
177
|
+
possible_releases
|
227
178
|
end
|
228
179
|
|
229
180
|
sig do
|
@@ -271,7 +222,9 @@ module Dependabot
|
|
271
222
|
.returns(T::Array[Dependabot::Package::PackageRelease])
|
272
223
|
end
|
273
224
|
def possible_releases(filter_ignored: true)
|
274
|
-
releases = possible_previous_releases.reject
|
225
|
+
releases = possible_previous_releases.reject do |r|
|
226
|
+
r.details["deprecated"]
|
227
|
+
end
|
275
228
|
|
276
229
|
return filter_releases(releases) if filter_ignored
|
277
230
|
|
@@ -298,13 +251,13 @@ module Dependabot
|
|
298
251
|
sig { returns(T::Array[[Dependabot::Version, T::Hash[String, T.nilable(String)]]]) }
|
299
252
|
def possible_previous_versions_with_details
|
300
253
|
possible_previous_releases.map do |r|
|
301
|
-
[r.version,
|
254
|
+
[r.version, r.details]
|
302
255
|
end
|
303
256
|
end
|
304
257
|
|
305
258
|
sig { override.returns(T::Boolean) }
|
306
259
|
def cooldown_enabled?
|
307
|
-
|
260
|
+
true
|
308
261
|
end
|
309
262
|
|
310
263
|
private
|
@@ -334,20 +287,24 @@ module Dependabot
|
|
334
287
|
.find { |r| dist_tags.include?(r[:requirement]) }
|
335
288
|
&.fetch(:requirement)
|
336
289
|
|
337
|
-
|
290
|
+
# For cooldown filtering, use filtered releases
|
291
|
+
releases = available_versions
|
338
292
|
|
339
293
|
releases = filter_by_cooldown(releases) if releases
|
340
294
|
|
341
295
|
if dist_tag_req
|
342
296
|
release = find_dist_tag_release(dist_tag_req, releases)
|
343
|
-
return release
|
297
|
+
return release unless release&.version && yanked_version?(release.version)
|
344
298
|
end
|
345
299
|
|
346
|
-
|
300
|
+
return nil unless dist_tags["latest"]
|
347
301
|
|
348
|
-
|
302
|
+
latest_version = Version.new(dist_tags["latest"])
|
349
303
|
|
350
|
-
|
304
|
+
if wants_latest_dist_tag?(latest_version)
|
305
|
+
# Find the release object for this version, even if deprecated
|
306
|
+
return possible_previous_releases.find { |r| r.version == latest_version }
|
307
|
+
end
|
351
308
|
|
352
309
|
nil
|
353
310
|
end
|
@@ -440,527 +397,19 @@ module Dependabot
|
|
440
397
|
def yanked_version?(version)
|
441
398
|
package_fetcher.yanked?(version)
|
442
399
|
end
|
443
|
-
end
|
444
|
-
|
445
|
-
class LatestVersionFinder # rubocop:disable Metrics/ClassLength
|
446
|
-
extend T::Sig
|
447
|
-
|
448
|
-
sig do
|
449
|
-
params(
|
450
|
-
dependency: Dependabot::Dependency,
|
451
|
-
dependency_files: T::Array[Dependabot::DependencyFile],
|
452
|
-
credentials: T::Array[Dependabot::Credential],
|
453
|
-
ignored_versions: T::Array[String],
|
454
|
-
security_advisories: T::Array[Dependabot::SecurityAdvisory],
|
455
|
-
raise_on_ignored: T::Boolean
|
456
|
-
).void
|
457
|
-
end
|
458
|
-
def initialize(
|
459
|
-
dependency:,
|
460
|
-
dependency_files:,
|
461
|
-
credentials:,
|
462
|
-
ignored_versions:,
|
463
|
-
security_advisories:,
|
464
|
-
raise_on_ignored: false
|
465
|
-
)
|
466
|
-
@dependency = dependency
|
467
|
-
@credentials = credentials
|
468
|
-
@dependency_files = dependency_files
|
469
|
-
@ignored_versions = ignored_versions
|
470
|
-
@raise_on_ignored = raise_on_ignored
|
471
|
-
@security_advisories = security_advisories
|
472
|
-
|
473
|
-
@possible_previous_versions_with_details = T.let(nil, T.nilable(T::Array[T::Array[T.untyped]]))
|
474
|
-
@yanked = T.let({}, T::Hash[Version, T.nilable(T::Boolean)])
|
475
|
-
@npm_details = T.let(nil, T.nilable(T::Hash[String, T.untyped]))
|
476
|
-
@registry_finder = T.let(nil, T.nilable(Package::RegistryFinder))
|
477
|
-
@version_endpoint_working = T.let(nil, T.nilable(T::Boolean))
|
478
|
-
end
|
479
|
-
|
480
|
-
sig { returns(T.nilable(Version)) }
|
481
|
-
def latest_version_from_registry
|
482
|
-
return unless valid_npm_details?
|
483
|
-
return version_from_dist_tags if version_from_dist_tags
|
484
|
-
return if specified_dist_tag_requirement?
|
485
|
-
|
486
|
-
possible_versions.find { |v| !yanked?(v) }
|
487
|
-
rescue Excon::Error::Socket, Excon::Error::Timeout, RegistryError
|
488
|
-
raise if dependency_registry == "registry.npmjs.org"
|
489
|
-
# Custom registries can be flaky. We don't want to make that
|
490
|
-
# our problem, so we quietly return `nil` here.
|
491
|
-
end
|
492
|
-
|
493
|
-
sig { returns(T.nilable(Version)) }
|
494
|
-
def latest_version_with_no_unlock
|
495
|
-
return unless valid_npm_details?
|
496
|
-
return version_from_dist_tags if specified_dist_tag_requirement?
|
497
|
-
|
498
|
-
in_range_versions = filter_out_of_range_versions(possible_versions)
|
499
|
-
in_range_versions.find { |version| !yanked?(version) }
|
500
|
-
rescue Excon::Error::Socket, Excon::Error::Timeout
|
501
|
-
raise if dependency_registry == "registry.npmjs.org"
|
502
|
-
# Sometimes custom registries are flaky. We don't want to make that
|
503
|
-
# our problem, so we quietly return `nil` here.
|
504
|
-
end
|
505
|
-
|
506
|
-
sig { returns(T.nilable(Version)) }
|
507
|
-
def lowest_security_fix_version
|
508
|
-
return unless valid_npm_details?
|
509
|
-
|
510
|
-
secure_versions =
|
511
|
-
if specified_dist_tag_requirement?
|
512
|
-
[version_from_dist_tags].compact
|
513
|
-
else
|
514
|
-
possible_versions(filter_ignored: false)
|
515
|
-
end
|
516
|
-
|
517
|
-
secure_versions = Dependabot::UpdateCheckers::VersionFilters
|
518
|
-
.filter_vulnerable_versions(
|
519
|
-
secure_versions,
|
520
|
-
security_advisories
|
521
|
-
)
|
522
|
-
secure_versions = filter_ignored_versions(secure_versions)
|
523
|
-
secure_versions = filter_lower_versions(secure_versions)
|
524
|
-
|
525
|
-
secure_versions.reverse.find { |version| !yanked?(version) }
|
526
|
-
rescue Excon::Error::Socket, Excon::Error::Timeout
|
527
|
-
raise if dependency_registry == "registry.npmjs.org"
|
528
|
-
# Sometimes custom registries are flaky. We don't want to make that
|
529
|
-
# our problem, so we quietly return `nil` here.
|
530
|
-
end
|
531
|
-
|
532
|
-
sig { returns(T::Array[T::Array[T.untyped]]) }
|
533
|
-
def possible_previous_versions_with_details # rubocop:disable Metrics/PerceivedComplexity
|
534
|
-
return @possible_previous_versions_with_details if @possible_previous_versions_with_details
|
535
|
-
|
536
|
-
@possible_previous_versions_with_details =
|
537
|
-
npm_details&.fetch("versions", {})
|
538
|
-
&.transform_keys { |k| version_class.new(k) }
|
539
|
-
&.reject do |v, _|
|
540
|
-
v.prerelease? && !related_to_current_pre?(v)
|
541
|
-
end&.sort_by(&:first)&.reverse
|
542
|
-
@possible_previous_versions_with_details
|
543
|
-
end
|
544
|
-
|
545
|
-
sig do
|
546
|
-
params(filter_ignored: T::Boolean)
|
547
|
-
.returns(T::Array[T::Array[T.untyped]])
|
548
|
-
end
|
549
|
-
def possible_versions_with_details(filter_ignored: true)
|
550
|
-
versions = possible_previous_versions_with_details
|
551
|
-
.reject { |_, details| details["deprecated"] }
|
552
|
-
|
553
|
-
return filter_ignored_versions(versions) if filter_ignored
|
554
|
-
|
555
|
-
versions
|
556
|
-
end
|
557
400
|
|
558
401
|
sig do
|
559
|
-
params(
|
560
|
-
.returns(T::Array[
|
561
|
-
end
|
562
|
-
def possible_versions(filter_ignored: true)
|
563
|
-
possible_versions_with_details(filter_ignored: filter_ignored)
|
564
|
-
.map(&:first)
|
565
|
-
end
|
566
|
-
|
567
|
-
private
|
568
|
-
|
569
|
-
sig { returns(Dependabot::Dependency) }
|
570
|
-
attr_reader :dependency
|
571
|
-
sig { returns(T::Array[Dependabot::Credential]) }
|
572
|
-
attr_reader :credentials
|
573
|
-
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
574
|
-
attr_reader :dependency_files
|
575
|
-
sig { returns(T::Array[String]) }
|
576
|
-
attr_reader :ignored_versions
|
577
|
-
sig { returns(T::Array[Dependabot::SecurityAdvisory]) }
|
578
|
-
attr_reader :security_advisories
|
579
|
-
|
580
|
-
sig { returns(T::Boolean) }
|
581
|
-
def valid_npm_details?
|
582
|
-
!npm_details&.fetch("dist-tags", nil).nil?
|
583
|
-
end
|
584
|
-
|
585
|
-
sig { params(versions_array: T::Array[T.untyped]).returns(T::Array[T.untyped]) }
|
586
|
-
def filter_ignored_versions(versions_array)
|
587
|
-
filtered = versions_array.reject do |v, _|
|
588
|
-
ignore_requirements.any? { |r| r.satisfied_by?(v) }
|
589
|
-
end
|
590
|
-
|
591
|
-
if @raise_on_ignored && filter_lower_versions(filtered).empty? && filter_lower_versions(versions_array).any?
|
592
|
-
raise AllVersionsIgnored
|
593
|
-
end
|
594
|
-
|
595
|
-
if versions_array.count > filtered.count
|
596
|
-
diff = versions_array.count - filtered.count
|
597
|
-
Dependabot.logger.info("Filtered out #{diff} ignored versions")
|
598
|
-
end
|
599
|
-
|
600
|
-
filtered
|
402
|
+
params(releases: T::Array[Dependabot::Package::PackageRelease])
|
403
|
+
.returns(T::Array[Dependabot::Package::PackageRelease])
|
601
404
|
end
|
602
|
-
|
603
|
-
sig { params(versions_array: T::Array[T.untyped]).returns(T::Array[T.untyped]) }
|
604
|
-
def filter_out_of_range_versions(versions_array)
|
405
|
+
def filter_out_of_range_versions(releases)
|
605
406
|
reqs = dependency.requirements.filter_map do |r|
|
606
407
|
NpmAndYarn::Requirement.requirements_array(r.fetch(:requirement))
|
607
408
|
end
|
608
409
|
|
609
|
-
|
610
|
-
|
611
|
-
end
|
612
|
-
|
613
|
-
sig { params(versions_array: T::Array[T.untyped]).returns(T::Array[T.untyped]) }
|
614
|
-
def filter_lower_versions(versions_array)
|
615
|
-
return versions_array unless dependency.numeric_version
|
616
|
-
|
617
|
-
versions_array
|
618
|
-
.select { |version, _| version > dependency.numeric_version }
|
619
|
-
end
|
620
|
-
|
621
|
-
sig { returns(T.nilable(Version)) }
|
622
|
-
def version_from_dist_tags
|
623
|
-
details = npm_details
|
624
|
-
|
625
|
-
return nil unless details
|
626
|
-
|
627
|
-
dist_tags = details["dist-tags"].keys
|
628
|
-
|
629
|
-
# Check if a dist tag was specified as a requirement. If it was, and
|
630
|
-
# it exists, use it.
|
631
|
-
dist_tag_req = dependency.requirements
|
632
|
-
.find { |r| dist_tags.include?(r[:requirement]) }
|
633
|
-
&.fetch(:requirement)
|
634
|
-
|
635
|
-
if dist_tag_req
|
636
|
-
tag_vers =
|
637
|
-
version_class.new(details["dist-tags"][dist_tag_req])
|
638
|
-
return tag_vers unless yanked?(tag_vers)
|
639
|
-
end
|
640
|
-
|
641
|
-
# Use the latest dist tag unless there's a reason not to
|
642
|
-
return nil unless details["dist-tags"]["latest"]
|
643
|
-
|
644
|
-
latest = version_class.new(details["dist-tags"]["latest"])
|
645
|
-
|
646
|
-
wants_latest_dist_tag?(latest) ? latest : nil
|
647
|
-
end
|
648
|
-
|
649
|
-
sig { params(version: Version).returns(T::Boolean) }
|
650
|
-
def related_to_current_pre?(version)
|
651
|
-
current_version = dependency.numeric_version
|
652
|
-
if current_version&.prerelease? &&
|
653
|
-
current_version.release == version.release
|
654
|
-
return true
|
410
|
+
releases.select do |release|
|
411
|
+
reqs.all? { |r| r.any? { |o| o.satisfied_by?(release.version) } }
|
655
412
|
end
|
656
|
-
|
657
|
-
dependency.requirements.any? do |req|
|
658
|
-
next unless req[:requirement]&.match?(/\d-[A-Za-z]/)
|
659
|
-
|
660
|
-
NpmAndYarn::Requirement
|
661
|
-
.requirements_array(req.fetch(:requirement))
|
662
|
-
.any? do |r|
|
663
|
-
r.requirements.any? { |a| a.last.release == version.release }
|
664
|
-
end
|
665
|
-
rescue Gem::Requirement::BadRequirementError
|
666
|
-
false
|
667
|
-
end
|
668
|
-
end
|
669
|
-
|
670
|
-
sig { returns(T::Boolean) }
|
671
|
-
def specified_dist_tag_requirement?
|
672
|
-
dependency.requirements.any? do |req|
|
673
|
-
next false if req[:requirement].nil?
|
674
|
-
next false unless req[:requirement].match?(/^[A-Za-z]/)
|
675
|
-
|
676
|
-
!req[:requirement].match?(/^v\d/i)
|
677
|
-
end
|
678
|
-
end
|
679
|
-
|
680
|
-
sig { params(latest_version: Version).returns(T::Boolean) }
|
681
|
-
def wants_latest_dist_tag?(latest_version)
|
682
|
-
ver = latest_version
|
683
|
-
return false if related_to_current_pre?(ver) ^ ver.prerelease?
|
684
|
-
return false if current_version_greater_than?(ver)
|
685
|
-
return false if current_requirement_greater_than?(ver)
|
686
|
-
return false if ignore_requirements.any? { |r| r.satisfied_by?(ver) }
|
687
|
-
return false if yanked?(ver)
|
688
|
-
|
689
|
-
true
|
690
|
-
end
|
691
|
-
|
692
|
-
sig { params(version: Version).returns(T::Boolean) }
|
693
|
-
def current_version_greater_than?(version)
|
694
|
-
return false unless dependency.numeric_version
|
695
|
-
|
696
|
-
T.must(dependency.numeric_version) > version
|
697
|
-
end
|
698
|
-
|
699
|
-
sig { params(version: Version).returns(T::Boolean) }
|
700
|
-
def current_requirement_greater_than?(version)
|
701
|
-
dependency.requirements.any? do |req|
|
702
|
-
next false unless req[:requirement]
|
703
|
-
|
704
|
-
req_version = req[:requirement].sub(/^\^|~|>=?/, "")
|
705
|
-
next false unless version_class.correct?(req_version)
|
706
|
-
|
707
|
-
version_class.new(req_version) > version
|
708
|
-
end
|
709
|
-
end
|
710
|
-
|
711
|
-
sig { params(version: Version).returns(T::Boolean) }
|
712
|
-
def yanked?(version)
|
713
|
-
return @yanked[version] || false if @yanked.key?(version)
|
714
|
-
|
715
|
-
@yanked[version] =
|
716
|
-
begin
|
717
|
-
if dependency_registry == "registry.npmjs.org"
|
718
|
-
status = Dependabot::RegistryClient.head(
|
719
|
-
url: registry_finder.tarball_url(version),
|
720
|
-
headers: registry_auth_headers
|
721
|
-
).status
|
722
|
-
else
|
723
|
-
status = Dependabot::RegistryClient.get(
|
724
|
-
url: dependency_url + "/#{version}",
|
725
|
-
headers: registry_auth_headers
|
726
|
-
).status
|
727
|
-
|
728
|
-
if status == 404
|
729
|
-
# Some registries don't handle escaped package names properly
|
730
|
-
status = Dependabot::RegistryClient.get(
|
731
|
-
url: dependency_url.gsub("%2F", "/") + "/#{version}",
|
732
|
-
headers: registry_auth_headers
|
733
|
-
).status
|
734
|
-
end
|
735
|
-
end
|
736
|
-
|
737
|
-
version_not_found = status == 404
|
738
|
-
version_not_found && version_endpoint_working?
|
739
|
-
rescue Excon::Error::Timeout, Excon::Error::Socket
|
740
|
-
# Give the benefit of the doubt if the registry is playing up
|
741
|
-
false
|
742
|
-
end
|
743
|
-
|
744
|
-
@yanked[version] || false
|
745
|
-
end
|
746
|
-
|
747
|
-
sig { returns(T.nilable(T::Boolean)) }
|
748
|
-
def version_endpoint_working?
|
749
|
-
return true if dependency_registry == "registry.npmjs.org"
|
750
|
-
|
751
|
-
return @version_endpoint_working if @version_endpoint_working
|
752
|
-
|
753
|
-
@version_endpoint_working =
|
754
|
-
begin
|
755
|
-
Dependabot::RegistryClient.get(
|
756
|
-
url: dependency_url + "/latest",
|
757
|
-
headers: registry_auth_headers
|
758
|
-
).status < 400
|
759
|
-
rescue Excon::Error::Timeout, Excon::Error::Socket
|
760
|
-
# Give the benefit of the doubt if the registry is playing up
|
761
|
-
true
|
762
|
-
end
|
763
|
-
@version_endpoint_working
|
764
|
-
end
|
765
|
-
|
766
|
-
sig { returns(T.nilable(T::Hash[String, T.untyped])) }
|
767
|
-
def npm_details
|
768
|
-
return @npm_details if @npm_details
|
769
|
-
|
770
|
-
@npm_details = fetch_npm_details
|
771
|
-
end
|
772
|
-
|
773
|
-
sig { returns(T.nilable(T::Hash[String, T.untyped])) }
|
774
|
-
def fetch_npm_details
|
775
|
-
npm_response = fetch_npm_response
|
776
|
-
|
777
|
-
return nil unless npm_response
|
778
|
-
|
779
|
-
check_npm_response(npm_response)
|
780
|
-
JSON.parse(npm_response.body)
|
781
|
-
rescue JSON::ParserError,
|
782
|
-
Excon::Error::Timeout,
|
783
|
-
Excon::Error::Socket,
|
784
|
-
RegistryError => e
|
785
|
-
if git_dependency?
|
786
|
-
nil
|
787
|
-
else
|
788
|
-
raise_npm_details_error(e)
|
789
|
-
end
|
790
|
-
end
|
791
|
-
|
792
|
-
sig { returns(T.nilable(Excon::Response)) }
|
793
|
-
def fetch_npm_response
|
794
|
-
response = Dependabot::RegistryClient.get(
|
795
|
-
url: dependency_url,
|
796
|
-
headers: registry_auth_headers
|
797
|
-
)
|
798
|
-
return response unless response.status == 500
|
799
|
-
return response unless registry_auth_headers["Authorization"]
|
800
|
-
|
801
|
-
auth = registry_auth_headers["Authorization"]
|
802
|
-
return response unless auth&.start_with?("Basic")
|
803
|
-
|
804
|
-
decoded_token = Base64.decode64(auth.gsub("Basic ", ""))
|
805
|
-
return unless decoded_token.include?(":")
|
806
|
-
|
807
|
-
username, password = decoded_token.split(":")
|
808
|
-
Dependabot::RegistryClient.get(
|
809
|
-
url: dependency_url,
|
810
|
-
options: {
|
811
|
-
user: username,
|
812
|
-
password: password
|
813
|
-
}
|
814
|
-
)
|
815
|
-
rescue URI::InvalidURIError => e
|
816
|
-
raise DependencyFileNotResolvable, e.message
|
817
|
-
end
|
818
|
-
|
819
|
-
sig { params(npm_response: Excon::Response).void }
|
820
|
-
def check_npm_response(npm_response)
|
821
|
-
return if git_dependency?
|
822
|
-
|
823
|
-
if private_dependency_not_reachable?(npm_response)
|
824
|
-
raise PrivateSourceAuthenticationFailure, dependency_registry
|
825
|
-
end
|
826
|
-
|
827
|
-
# handles scenario when private registry returns a server error 5xx
|
828
|
-
if private_dependency_server_error?(npm_response)
|
829
|
-
msg = "Server error #{npm_response.status} returned while accessing registry" \
|
830
|
-
" #{dependency_registry}."
|
831
|
-
raise DependencyFileNotResolvable, msg
|
832
|
-
end
|
833
|
-
|
834
|
-
status = npm_response.status
|
835
|
-
|
836
|
-
# handles issue when status 200 is returned from registry but with an invalid JSON object
|
837
|
-
if status.to_s.start_with?("2") && response_invalid_json?(npm_response)
|
838
|
-
msg = "Invalid JSON object returned from registry #{dependency_registry}."
|
839
|
-
Dependabot.logger.warn("#{msg} Response body (truncated) : #{npm_response.body[0..500]}...")
|
840
|
-
raise DependencyFileNotResolvable, msg
|
841
|
-
end
|
842
|
-
|
843
|
-
return if status.to_s.start_with?("2")
|
844
|
-
|
845
|
-
# Ignore 404s from the registry for updates where a lockfile doesn't
|
846
|
-
# need to be generated. The 404 won't cause problems later.
|
847
|
-
return if status == 404 && dependency.version.nil?
|
848
|
-
|
849
|
-
msg = "Got #{status} response with body #{npm_response.body}"
|
850
|
-
raise RegistryError.new(status, msg)
|
851
|
-
end
|
852
|
-
|
853
|
-
sig { params(error: Exception).void }
|
854
|
-
def raise_npm_details_error(error)
|
855
|
-
raise if dependency_registry == "registry.npmjs.org"
|
856
|
-
raise unless error.is_a?(Excon::Error::Timeout)
|
857
|
-
|
858
|
-
raise PrivateSourceTimedOut, dependency_registry
|
859
|
-
end
|
860
|
-
|
861
|
-
sig { params(npm_response: Excon::Response).returns(T::Boolean) }
|
862
|
-
def private_dependency_not_reachable?(npm_response)
|
863
|
-
return true if npm_response.body.start_with?(/user ".*?" is not a /)
|
864
|
-
return false unless [401, 402, 403, 404].include?(npm_response.status)
|
865
|
-
|
866
|
-
# Check whether this dependency is (likely to be) private
|
867
|
-
if dependency_registry == "registry.npmjs.org"
|
868
|
-
return false unless dependency.name.start_with?("@")
|
869
|
-
|
870
|
-
web_response = Dependabot::RegistryClient.get(url: "https://www.npmjs.com/package/#{dependency.name}")
|
871
|
-
# NOTE: returns 429 when the login page is rate limited
|
872
|
-
return web_response.body.include?("Forgot password?") ||
|
873
|
-
web_response.status == 429
|
874
|
-
end
|
875
|
-
|
876
|
-
true
|
877
|
-
end
|
878
|
-
|
879
|
-
sig { params(npm_response: Excon::Response).returns(T::Boolean) }
|
880
|
-
def private_dependency_server_error?(npm_response)
|
881
|
-
if [500, 501, 502, 503].include?(npm_response.status)
|
882
|
-
Dependabot.logger.warn("#{dependency_registry} returned code #{npm_response.status} with " \
|
883
|
-
"body #{npm_response.body}.")
|
884
|
-
return true
|
885
|
-
end
|
886
|
-
false
|
887
|
-
end
|
888
|
-
|
889
|
-
sig { params(npm_response: Excon::Response).returns(T::Boolean) }
|
890
|
-
def response_invalid_json?(npm_response)
|
891
|
-
result = JSON.parse(npm_response.body)
|
892
|
-
result.is_a?(Hash) || result.is_a?(Array)
|
893
|
-
false
|
894
|
-
rescue JSON::ParserError, TypeError
|
895
|
-
true
|
896
|
-
end
|
897
|
-
|
898
|
-
sig { returns(String) }
|
899
|
-
def dependency_url
|
900
|
-
registry_finder.dependency_url
|
901
|
-
end
|
902
|
-
|
903
|
-
sig { returns(String) }
|
904
|
-
def dependency_registry
|
905
|
-
registry_finder.registry
|
906
|
-
end
|
907
|
-
|
908
|
-
sig { returns(T::Hash[String, String]) }
|
909
|
-
def registry_auth_headers
|
910
|
-
registry_finder.auth_headers
|
911
|
-
end
|
912
|
-
|
913
|
-
sig { returns(Package::RegistryFinder) }
|
914
|
-
def registry_finder
|
915
|
-
return @registry_finder if @registry_finder
|
916
|
-
|
917
|
-
@registry_finder = Package::RegistryFinder.new(
|
918
|
-
dependency: dependency,
|
919
|
-
credentials: credentials,
|
920
|
-
npmrc_file: npmrc_file,
|
921
|
-
yarnrc_file: yarnrc_file,
|
922
|
-
yarnrc_yml_file: yarnrc_yml_file
|
923
|
-
)
|
924
|
-
@registry_finder
|
925
|
-
end
|
926
|
-
|
927
|
-
sig { returns(T::Array[Dependabot::Requirement]) }
|
928
|
-
def ignore_requirements
|
929
|
-
ignored_versions.flat_map { |req| requirement_class.requirements_array(req) }
|
930
|
-
end
|
931
|
-
|
932
|
-
sig { returns(T.class_of(Version)) }
|
933
|
-
def version_class
|
934
|
-
Dependabot::NpmAndYarn::Version
|
935
|
-
end
|
936
|
-
|
937
|
-
sig { returns(T.class_of(Requirement)) }
|
938
|
-
def requirement_class
|
939
|
-
Dependabot::NpmAndYarn::Requirement
|
940
|
-
end
|
941
|
-
|
942
|
-
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
943
|
-
def npmrc_file
|
944
|
-
dependency_files.find { |f| f.name.end_with?(".npmrc") }
|
945
|
-
end
|
946
|
-
|
947
|
-
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
948
|
-
def yarnrc_file
|
949
|
-
dependency_files.find { |f| f.name.end_with?(".yarnrc") }
|
950
|
-
end
|
951
|
-
|
952
|
-
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
953
|
-
def yarnrc_yml_file
|
954
|
-
dependency_files.find { |f| f.name.end_with?(".yarnrc.yml") }
|
955
|
-
end
|
956
|
-
|
957
|
-
sig { returns(T::Boolean) }
|
958
|
-
def git_dependency?
|
959
|
-
# ignored_version/raise_on_ignored are irrelevant.
|
960
|
-
GitCommitChecker.new(
|
961
|
-
dependency: dependency,
|
962
|
-
credentials: credentials
|
963
|
-
).git_dependency?
|
964
413
|
end
|
965
414
|
end
|
966
415
|
end
|
@@ -97,7 +97,7 @@ module Dependabot
|
|
97
97
|
dependency_files: T::Array[Dependabot::DependencyFile],
|
98
98
|
credentials: T::Array[Dependabot::Credential],
|
99
99
|
latest_allowable_version: T.nilable(T.any(String, Gem::Version)),
|
100
|
-
latest_version_finder:
|
100
|
+
latest_version_finder: PackageLatestVersionFinder,
|
101
101
|
repo_contents_path: T.nilable(String),
|
102
102
|
dependency_group: T.nilable(Dependabot::DependencyGroup),
|
103
103
|
raise_on_ignored: T::Boolean,
|
@@ -116,11 +116,7 @@ module Dependabot
|
|
116
116
|
@latest_allowable_version = latest_allowable_version
|
117
117
|
@dependency_group = dependency_group
|
118
118
|
|
119
|
-
@latest_version_finder = T.let(
|
120
|
-
{},
|
121
|
-
T::Hash[Dependabot::Dependency, T.any(LatestVersionFinder, PackageLatestVersionFinder)
|
122
|
-
]
|
123
|
-
)
|
119
|
+
@latest_version_finder = T.let({}, T::Hash[Dependabot::Dependency, PackageLatestVersionFinder])
|
124
120
|
@latest_version_finder[dependency] = latest_version_finder
|
125
121
|
@repo_contents_path = repo_contents_path
|
126
122
|
@raise_on_ignored = raise_on_ignored
|
@@ -228,34 +224,18 @@ module Dependabot
|
|
228
224
|
sig { returns(T::Boolean) }
|
229
225
|
attr_reader :raise_on_ignored
|
230
226
|
|
231
|
-
sig { params(dep: Dependabot::Dependency) .returns(
|
227
|
+
sig { params(dep: Dependabot::Dependency) .returns(PackageLatestVersionFinder) }
|
232
228
|
def latest_version_finder(dep)
|
233
229
|
@latest_version_finder[dep] ||=
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
)
|
244
|
-
else
|
245
|
-
LatestVersionFinder.new(
|
246
|
-
dependency: dep,
|
247
|
-
credentials: credentials,
|
248
|
-
dependency_files: dependency_files,
|
249
|
-
ignored_versions: [],
|
250
|
-
security_advisories: [],
|
251
|
-
raise_on_ignored: raise_on_ignored
|
252
|
-
)
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
sig { returns(T::Boolean) }
|
257
|
-
def enable_cooldown?
|
258
|
-
Dependabot::Experiments.enabled?(:enable_cooldown_for_npm_and_yarn)
|
230
|
+
PackageLatestVersionFinder.new(
|
231
|
+
dependency: dep,
|
232
|
+
dependency_files: dependency_files,
|
233
|
+
credentials: credentials,
|
234
|
+
cooldown_options: update_cooldown,
|
235
|
+
ignored_versions: [],
|
236
|
+
security_advisories: [],
|
237
|
+
raise_on_ignored: raise_on_ignored
|
238
|
+
)
|
259
239
|
end
|
260
240
|
|
261
241
|
# rubocop:disable Metrics/PerceivedComplexity
|
@@ -49,9 +49,7 @@ module Dependabot
|
|
49
49
|
@latest_version_for_git_dependency = T.let(nil, T.nilable(T.any(String, Gem::Version)))
|
50
50
|
@latest_released_version = T.let(nil, T.nilable(Gem::Version))
|
51
51
|
@latest_version_details = T.let(nil, T.nilable(T::Hash[Symbol, T.untyped]))
|
52
|
-
@latest_version_finder = T.let(
|
53
|
-
nil, T.nilable(T.any(LatestVersionFinder, PackageLatestVersionFinder))
|
54
|
-
)
|
52
|
+
@latest_version_finder = T.let(nil, T.nilable(PackageLatestVersionFinder))
|
55
53
|
@version_resolver = T.let(nil, T.nilable(VersionResolver))
|
56
54
|
@subdependency_version_resolver = T.let(nil, T.nilable(SubdependencyVersionResolver))
|
57
55
|
@library = T.let(nil, T.nilable(T::Boolean))
|
@@ -138,9 +136,7 @@ module Dependabot
|
|
138
136
|
sig { override.returns(T.nilable(T.any(String, Dependabot::Version))) }
|
139
137
|
def latest_resolvable_version_with_no_unlock
|
140
138
|
unless dependency.top_level?
|
141
|
-
|
142
|
-
return T.cast(latest_resolvable_version,
|
143
|
-
T.nilable(T.any(String, Dependabot::Version)))
|
139
|
+
return T.cast(latest_resolvable_version, T.nilable(T.any(String, Dependabot::Version)))
|
144
140
|
end
|
145
141
|
|
146
142
|
return latest_resolvable_version_with_no_unlock_for_git_dependency if git_dependency?
|
@@ -411,34 +407,17 @@ module Dependabot
|
|
411
407
|
end
|
412
408
|
end
|
413
409
|
|
414
|
-
sig { returns(
|
410
|
+
sig { returns(PackageLatestVersionFinder) }
|
415
411
|
def latest_version_finder
|
416
|
-
@latest_version_finder ||=
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
cooldown_options: @update_cooldown
|
426
|
-
)
|
427
|
-
else
|
428
|
-
LatestVersionFinder.new(
|
429
|
-
dependency: dependency,
|
430
|
-
credentials: credentials,
|
431
|
-
dependency_files: dependency_files,
|
432
|
-
ignored_versions: ignored_versions,
|
433
|
-
raise_on_ignored: raise_on_ignored,
|
434
|
-
security_advisories: security_advisories
|
435
|
-
)
|
436
|
-
end
|
437
|
-
end
|
438
|
-
|
439
|
-
sig { returns(T::Boolean) }
|
440
|
-
def enable_cooldown?
|
441
|
-
Dependabot::Experiments.enabled?(:enable_cooldown_for_npm_and_yarn)
|
412
|
+
@latest_version_finder ||= PackageLatestVersionFinder.new(
|
413
|
+
dependency: dependency,
|
414
|
+
credentials: credentials,
|
415
|
+
dependency_files: dependency_files,
|
416
|
+
ignored_versions: ignored_versions,
|
417
|
+
raise_on_ignored: raise_on_ignored,
|
418
|
+
security_advisories: security_advisories,
|
419
|
+
cooldown_options: @update_cooldown
|
420
|
+
)
|
442
421
|
end
|
443
422
|
|
444
423
|
sig { returns(VersionResolver) }
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dependabot-npm_and_yarn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.322.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.
|
18
|
+
version: 0.322.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.322.0
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: debug
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
@@ -356,7 +356,7 @@ licenses:
|
|
356
356
|
- MIT
|
357
357
|
metadata:
|
358
358
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
359
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
359
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.322.0
|
360
360
|
rdoc_options: []
|
361
361
|
require_paths:
|
362
362
|
- lib
|