dependabot-nuget 0.246.0 → 0.248.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/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +40 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +27 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs +18 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +110 -0
- data/lib/dependabot/nuget/cache_manager.rb +9 -3
- data/lib/dependabot/nuget/file_fetcher/import_paths_finder.rb +15 -12
- data/lib/dependabot/nuget/file_fetcher/sln_project_paths_finder.rb +13 -3
- data/lib/dependabot/nuget/file_fetcher.rb +89 -37
- data/lib/dependabot/nuget/file_parser/dotnet_tools_json_parser.rb +10 -2
- data/lib/dependabot/nuget/file_parser/global_json_parser.rb +10 -2
- data/lib/dependabot/nuget/file_parser/packages_config_parser.rb +11 -2
- data/lib/dependabot/nuget/file_parser/project_file_parser.rb +140 -41
- data/lib/dependabot/nuget/file_parser/property_value_finder.rb +57 -5
- data/lib/dependabot/nuget/file_parser.rb +13 -3
- data/lib/dependabot/nuget/file_updater/property_value_updater.rb +25 -8
- data/lib/dependabot/nuget/file_updater.rb +74 -38
- data/lib/dependabot/nuget/http_response_helpers.rb +6 -1
- data/lib/dependabot/nuget/metadata_finder.rb +27 -3
- data/lib/dependabot/nuget/nuget_client.rb +23 -0
- data/lib/dependabot/nuget/nuget_config_credential_helpers.rb +10 -1
- data/lib/dependabot/nuget/requirement.rb +21 -9
- data/lib/dependabot/nuget/update_checker/compatibility_checker.rb +26 -15
- data/lib/dependabot/nuget/update_checker/nupkg_fetcher.rb +87 -21
- data/lib/dependabot/nuget/update_checker/nuspec_fetcher.rb +25 -3
- data/lib/dependabot/nuget/update_checker/repository_finder.rb +25 -3
- data/lib/dependabot/nuget/update_checker/requirements_updater.rb +32 -9
- data/lib/dependabot/nuget/update_checker/tfm_finder.rb +2 -2
- data/lib/dependabot/nuget/update_checker/version_finder.rb +178 -64
- data/lib/dependabot/nuget/update_checker.rb +76 -32
- data/lib/dependabot/nuget/version.rb +7 -2
- metadata +19 -5
@@ -1,6 +1,8 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
4
6
|
require "dependabot/nuget/version"
|
5
7
|
require "dependabot/nuget/requirement"
|
6
8
|
require "dependabot/update_checkers/base"
|
@@ -10,16 +12,33 @@ require "dependabot/nuget/nuget_client"
|
|
10
12
|
module Dependabot
|
11
13
|
module Nuget
|
12
14
|
class UpdateChecker < Dependabot::UpdateCheckers::Base
|
15
|
+
# rubocop:disable Metrics/ClassLength
|
13
16
|
class VersionFinder
|
17
|
+
extend T::Sig
|
18
|
+
|
14
19
|
require_relative "compatibility_checker"
|
15
20
|
require_relative "repository_finder"
|
16
21
|
|
17
22
|
NUGET_RANGE_REGEX = /[\(\[].*,.*[\)\]]/
|
18
23
|
|
19
|
-
|
20
|
-
|
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
|
+
repo_contents_path: T.nilable(String),
|
32
|
+
raise_on_ignored: T::Boolean
|
33
|
+
).void
|
34
|
+
end
|
35
|
+
def initialize(dependency:,
|
36
|
+
dependency_files:,
|
37
|
+
credentials:,
|
38
|
+
ignored_versions:,
|
21
39
|
security_advisories:,
|
22
|
-
repo_contents_path
|
40
|
+
repo_contents_path:,
|
41
|
+
raise_on_ignored: false)
|
23
42
|
@dependency = dependency
|
24
43
|
@dependency_files = dependency_files
|
25
44
|
@credentials = credentials
|
@@ -29,53 +48,89 @@ module Dependabot
|
|
29
48
|
@repo_contents_path = repo_contents_path
|
30
49
|
end
|
31
50
|
|
51
|
+
sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
32
52
|
def latest_version_details
|
33
53
|
@latest_version_details ||=
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
54
|
+
T.let(
|
55
|
+
begin
|
56
|
+
possible_versions = versions
|
57
|
+
possible_versions = filter_prereleases(possible_versions)
|
58
|
+
possible_versions = filter_ignored_versions(possible_versions)
|
59
|
+
|
60
|
+
find_highest_compatible_version(possible_versions)
|
61
|
+
end,
|
62
|
+
T.nilable(T::Hash[Symbol, T.untyped])
|
63
|
+
)
|
41
64
|
end
|
42
65
|
|
66
|
+
sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
43
67
|
def lowest_security_fix_version_details
|
44
68
|
@lowest_security_fix_version_details ||=
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
possible_versions
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
69
|
+
T.let(
|
70
|
+
begin
|
71
|
+
possible_versions = versions
|
72
|
+
possible_versions = filter_prereleases(possible_versions)
|
73
|
+
possible_versions = Dependabot::UpdateCheckers::VersionFilters.filter_vulnerable_versions(
|
74
|
+
possible_versions, security_advisories
|
75
|
+
)
|
76
|
+
possible_versions = filter_ignored_versions(possible_versions)
|
77
|
+
possible_versions = filter_lower_versions(possible_versions)
|
78
|
+
|
79
|
+
find_lowest_compatible_version(possible_versions)
|
80
|
+
end,
|
81
|
+
T.nilable(T::Hash[Symbol, T.untyped])
|
82
|
+
)
|
56
83
|
end
|
57
84
|
|
85
|
+
sig { returns(T::Array[T::Hash[Symbol, T.nilable(T.any(Dependabot::Version, String))]]) }
|
58
86
|
def versions
|
59
87
|
available_v3_versions + available_v2_versions
|
60
88
|
end
|
61
89
|
|
62
|
-
|
63
|
-
|
90
|
+
sig { returns(Dependabot::Dependency) }
|
91
|
+
attr_reader :dependency
|
92
|
+
|
93
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
94
|
+
attr_reader :dependency_files
|
95
|
+
|
96
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
97
|
+
attr_reader :credentials
|
98
|
+
|
99
|
+
sig { returns(T::Array[String]) }
|
100
|
+
attr_reader :ignored_versions
|
101
|
+
|
102
|
+
sig { returns(T::Array[Dependabot::SecurityAdvisory]) }
|
103
|
+
attr_reader :security_advisories
|
104
|
+
|
105
|
+
sig { returns(T.nilable(String)) }
|
106
|
+
attr_reader :repo_contents_path
|
64
107
|
|
65
108
|
private
|
66
109
|
|
110
|
+
sig do
|
111
|
+
params(possible_versions: T::Array[T::Hash[Symbol, T.untyped]])
|
112
|
+
.returns(T.nilable(T::Hash[Symbol, T.untyped]))
|
113
|
+
end
|
67
114
|
def find_highest_compatible_version(possible_versions)
|
68
115
|
# sorted versions descending
|
69
116
|
sorted_versions = possible_versions.sort_by { |v| v.fetch(:version) }.reverse
|
70
117
|
find_compatible_version(sorted_versions)
|
71
118
|
end
|
72
119
|
|
120
|
+
sig do
|
121
|
+
params(possible_versions: T::Array[T::Hash[Symbol, T.untyped]])
|
122
|
+
.returns(T.nilable(T::Hash[Symbol, T.untyped]))
|
123
|
+
end
|
73
124
|
def find_lowest_compatible_version(possible_versions)
|
74
125
|
# sorted versions ascending
|
75
126
|
sorted_versions = possible_versions.sort_by { |v| v.fetch(:version) }
|
76
127
|
find_compatible_version(sorted_versions)
|
77
128
|
end
|
78
129
|
|
130
|
+
sig do
|
131
|
+
params(sorted_versions: T::Array[T::Hash[Symbol, T.untyped]])
|
132
|
+
.returns(T.nilable(T::Hash[Symbol, T.untyped]))
|
133
|
+
end
|
79
134
|
def find_compatible_version(sorted_versions)
|
80
135
|
# By checking the first version separately, we can avoid additional network requests
|
81
136
|
first_version = sorted_versions.first
|
@@ -89,33 +144,52 @@ module Dependabot
|
|
89
144
|
sorted_versions.find { |v| version_compatible?(v.fetch(:version)) }
|
90
145
|
end
|
91
146
|
|
147
|
+
sig { params(version: T.nilable(T.any(Dependabot::Version, String))).returns(T::Boolean) }
|
92
148
|
def version_compatible?(version)
|
93
149
|
str_version_compatible?(version.to_s)
|
94
150
|
end
|
95
151
|
|
152
|
+
sig { params(version: String).returns(T::Boolean) }
|
96
153
|
def str_version_compatible?(version)
|
97
154
|
compatibility_checker.compatible?(version)
|
98
155
|
end
|
99
156
|
|
157
|
+
sig { returns(Dependabot::Nuget::CompatibilityChecker) }
|
100
158
|
def compatibility_checker
|
101
|
-
@compatibility_checker ||=
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
159
|
+
@compatibility_checker ||=
|
160
|
+
T.let(
|
161
|
+
CompatibilityChecker.new(
|
162
|
+
dependency_urls: dependency_urls,
|
163
|
+
dependency: dependency,
|
164
|
+
tfm_finder: TfmFinder.new(
|
165
|
+
dependency_files: dependency_files,
|
166
|
+
credentials: credentials,
|
167
|
+
repo_contents_path: repo_contents_path
|
168
|
+
)
|
169
|
+
),
|
170
|
+
T.nilable(Dependabot::Nuget::CompatibilityChecker)
|
108
171
|
)
|
109
|
-
)
|
110
172
|
end
|
111
173
|
|
174
|
+
sig do
|
175
|
+
params(possible_versions: T::Array[T::Hash[Symbol, T.untyped]])
|
176
|
+
.returns(T::Array[T::Hash[Symbol, T.untyped]])
|
177
|
+
end
|
112
178
|
def filter_prereleases(possible_versions)
|
113
|
-
possible_versions.reject do |d|
|
179
|
+
filtered = possible_versions.reject do |d|
|
114
180
|
version = d.fetch(:version)
|
115
181
|
version.prerelease? && !related_to_current_pre?(version)
|
116
182
|
end
|
183
|
+
if possible_versions.count > filtered.count
|
184
|
+
Dependabot.logger.info("Filtered out #{possible_versions.count - filtered.count} pre-release versions")
|
185
|
+
end
|
186
|
+
filtered
|
117
187
|
end
|
118
188
|
|
189
|
+
sig do
|
190
|
+
params(possible_versions: T::Array[T::Hash[Symbol, T.untyped]])
|
191
|
+
.returns(T::Array[T::Hash[Symbol, T.untyped]])
|
192
|
+
end
|
119
193
|
def filter_ignored_versions(possible_versions)
|
120
194
|
filtered = possible_versions
|
121
195
|
|
@@ -131,9 +205,17 @@ module Dependabot
|
|
131
205
|
raise AllVersionsIgnored
|
132
206
|
end
|
133
207
|
|
208
|
+
if possible_versions.count > filtered.count
|
209
|
+
Dependabot.logger.info("Filtered out #{possible_versions.count - filtered.count} ignored versions")
|
210
|
+
end
|
211
|
+
|
134
212
|
filtered
|
135
213
|
end
|
136
214
|
|
215
|
+
sig do
|
216
|
+
params(possible_versions: T::Array[T::Hash[Symbol, T.untyped]])
|
217
|
+
.returns(T::Array[T::Hash[Symbol, T.untyped]])
|
218
|
+
end
|
137
219
|
def filter_lower_versions(possible_versions)
|
138
220
|
return possible_versions unless dependency.numeric_version
|
139
221
|
|
@@ -142,12 +224,14 @@ module Dependabot
|
|
142
224
|
end
|
143
225
|
end
|
144
226
|
|
227
|
+
sig { params(string: String).returns(T::Array[String]) }
|
145
228
|
def parse_requirement_string(string)
|
146
229
|
return [string] if string.match?(NUGET_RANGE_REGEX)
|
147
230
|
|
148
231
|
string.split(",").map(&:strip)
|
149
232
|
end
|
150
233
|
|
234
|
+
sig { returns(T::Array[T::Hash[Symbol, T.any(Dependabot::Version, String, NilClass)]]) }
|
151
235
|
def available_v3_versions
|
152
236
|
v3_nuget_listings.flat_map do |listing|
|
153
237
|
listing
|
@@ -168,6 +252,7 @@ module Dependabot
|
|
168
252
|
end
|
169
253
|
end
|
170
254
|
|
255
|
+
sig { returns(T::Array[T::Hash[Symbol, T.any(Dependabot::Version, String, NilClass)]]) }
|
171
256
|
def available_v2_versions
|
172
257
|
v2_nuget_listings.flat_map do |listing|
|
173
258
|
body = listing.fetch("xml_body", [])
|
@@ -187,6 +272,10 @@ module Dependabot
|
|
187
272
|
end
|
188
273
|
end
|
189
274
|
|
275
|
+
sig do
|
276
|
+
params(entry: Nokogiri::XML::Element)
|
277
|
+
.returns(T::Hash[Symbol, T.any(Dependabot::Version, String, NilClass)])
|
278
|
+
end
|
190
279
|
def dependency_details_from_v2_entry(entry)
|
191
280
|
version = entry.at_xpath("./properties/Version").content.strip
|
192
281
|
source_urls = []
|
@@ -208,10 +297,11 @@ module Dependabot
|
|
208
297
|
end
|
209
298
|
|
210
299
|
# rubocop:disable Metrics/PerceivedComplexity
|
300
|
+
sig { params(version: Dependabot::Version).returns(T::Boolean) }
|
211
301
|
def related_to_current_pre?(version)
|
212
302
|
current_version = dependency.numeric_version
|
213
303
|
if current_version&.prerelease? &&
|
214
|
-
current_version
|
304
|
+
current_version.release == version.release
|
215
305
|
return true
|
216
306
|
end
|
217
307
|
|
@@ -229,40 +319,50 @@ module Dependabot
|
|
229
319
|
false
|
230
320
|
end
|
231
321
|
end
|
232
|
-
|
233
322
|
# rubocop:enable Metrics/PerceivedComplexity
|
234
323
|
|
324
|
+
sig { returns(T::Array[T::Hash[String, T.untyped]]) }
|
235
325
|
def v3_nuget_listings
|
236
|
-
return @v3_nuget_listings unless @v3_nuget_listings.nil?
|
237
|
-
|
238
326
|
@v3_nuget_listings ||=
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
327
|
+
T.let(
|
328
|
+
dependency_urls
|
329
|
+
.select { |details| details.fetch(:repository_type) == "v3" }
|
330
|
+
.filter_map do |url_details|
|
331
|
+
versions = NugetClient.get_package_versions(dependency.name, url_details)
|
332
|
+
next unless versions
|
333
|
+
|
334
|
+
{ "versions" => versions, "listing_details" => url_details }
|
335
|
+
end,
|
336
|
+
T.nilable(T::Array[T::Hash[String, T.untyped]])
|
337
|
+
)
|
247
338
|
end
|
248
339
|
|
340
|
+
sig { returns(T::Array[T::Hash[String, T.untyped]]) }
|
249
341
|
def v2_nuget_listings
|
250
|
-
return @v2_nuget_listings unless @v2_nuget_listings.nil?
|
251
|
-
|
252
342
|
@v2_nuget_listings ||=
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
343
|
+
T.let(
|
344
|
+
dependency_urls
|
345
|
+
.select { |details| details.fetch(:repository_type) == "v2" }
|
346
|
+
.flat_map { |url_details| fetch_paginated_v2_nuget_listings(url_details) }
|
347
|
+
.filter_map do |url_details, response|
|
348
|
+
next unless response.status == 200
|
349
|
+
|
350
|
+
{
|
351
|
+
"xml_body" => response.body,
|
352
|
+
"listing_details" => url_details
|
353
|
+
}
|
354
|
+
end,
|
355
|
+
T.nilable(T::Array[T::Hash[String, T.untyped]])
|
356
|
+
)
|
264
357
|
end
|
265
358
|
|
359
|
+
sig do
|
360
|
+
params(
|
361
|
+
url_details: T::Hash[Symbol, T.untyped],
|
362
|
+
results: T::Hash[T::Hash[Symbol, T.untyped], Excon::Response]
|
363
|
+
)
|
364
|
+
.returns(T::Array[T::Array[T.untyped]])
|
365
|
+
end
|
266
366
|
def fetch_paginated_v2_nuget_listings(url_details, results = {})
|
267
367
|
response = Dependabot::RegistryClient.get(
|
268
368
|
url: url_details[:versions_url],
|
@@ -286,6 +386,7 @@ module Dependabot
|
|
286
386
|
results.to_a
|
287
387
|
end
|
288
388
|
|
389
|
+
sig { params(xml_body: String).returns(T.nilable(String)) }
|
289
390
|
def fetch_v2_next_link_href(xml_body)
|
290
391
|
doc = Nokogiri::XML(xml_body)
|
291
392
|
doc.remove_namespaces!
|
@@ -298,32 +399,44 @@ module Dependabot
|
|
298
399
|
nil
|
299
400
|
end
|
300
401
|
|
402
|
+
sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
301
403
|
def dependency_urls
|
302
404
|
@dependency_urls ||=
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
405
|
+
T.let(
|
406
|
+
RepositoryFinder.new(
|
407
|
+
dependency: dependency,
|
408
|
+
credentials: credentials,
|
409
|
+
config_files: nuget_configs
|
410
|
+
).dependency_urls,
|
411
|
+
T.nilable(T::Array[T::Hash[Symbol, T.untyped]])
|
412
|
+
)
|
308
413
|
end
|
309
414
|
|
415
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
310
416
|
def nuget_configs
|
311
417
|
@nuget_configs ||=
|
312
|
-
|
418
|
+
T.let(
|
419
|
+
dependency_files.select { |f| f.name.match?(/nuget\.config$/i) },
|
420
|
+
T.nilable(T::Array[Dependabot::DependencyFile])
|
421
|
+
)
|
313
422
|
end
|
314
423
|
|
424
|
+
sig { returns(String) }
|
315
425
|
def sanitized_name
|
316
426
|
dependency.name.downcase
|
317
427
|
end
|
318
428
|
|
429
|
+
sig { returns(T.class_of(Gem::Version)) }
|
319
430
|
def version_class
|
320
431
|
dependency.version_class
|
321
432
|
end
|
322
433
|
|
434
|
+
sig { returns(T.class_of(Dependabot::Requirement)) }
|
323
435
|
def requirement_class
|
324
436
|
dependency.requirement_class
|
325
437
|
end
|
326
438
|
|
439
|
+
sig { returns(T::Hash[Symbol, Integer]) }
|
327
440
|
def excon_options
|
328
441
|
# For large JSON files we sometimes need a little longer than for
|
329
442
|
# other languages. For example, see:
|
@@ -336,6 +449,7 @@ module Dependabot
|
|
336
449
|
}
|
337
450
|
end
|
338
451
|
end
|
452
|
+
# rubocop:enable Metrics/ClassLength
|
339
453
|
end
|
340
454
|
end
|
341
455
|
end
|
@@ -1,55 +1,68 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "dependabot/nuget/file_parser"
|
5
5
|
require "dependabot/update_checkers"
|
6
6
|
require "dependabot/update_checkers/base"
|
7
|
+
require "sorbet-runtime"
|
7
8
|
|
8
9
|
module Dependabot
|
9
10
|
module Nuget
|
10
11
|
class UpdateChecker < Dependabot::UpdateCheckers::Base
|
12
|
+
extend T::Sig
|
13
|
+
|
11
14
|
require_relative "update_checker/version_finder"
|
12
15
|
require_relative "update_checker/property_updater"
|
13
16
|
require_relative "update_checker/requirements_updater"
|
14
17
|
require_relative "update_checker/dependency_finder"
|
15
18
|
|
19
|
+
sig { override.returns(T.nilable(String)) }
|
16
20
|
def latest_version
|
17
21
|
# No need to find latest version for transitive dependencies unless they have a vulnerability.
|
18
22
|
return dependency.version if !dependency.top_level? && !vulnerable?
|
19
23
|
|
20
|
-
|
24
|
+
# if no update sources have the requisite package, then we can only assume that the current version is correct
|
25
|
+
@latest_version = T.let(
|
26
|
+
latest_version_details&.fetch(:version)&.to_s || dependency.version,
|
27
|
+
T.nilable(String)
|
28
|
+
)
|
21
29
|
end
|
22
30
|
|
31
|
+
sig { override.returns(T.nilable(T.any(String, Gem::Version))) }
|
23
32
|
def latest_resolvable_version
|
24
33
|
# We always want a full unlock since any package update could update peer dependencies as well.
|
25
34
|
# To force a full unlock instead of an own unlock, we return nil.
|
26
35
|
nil
|
27
36
|
end
|
28
37
|
|
38
|
+
sig { override.returns(Dependabot::Nuget::Version) }
|
29
39
|
def lowest_security_fix_version
|
30
40
|
lowest_security_fix_version_details&.fetch(:version)
|
31
41
|
end
|
32
42
|
|
43
|
+
sig { override.returns(T.nilable(Dependabot::Version)) }
|
33
44
|
def lowest_resolvable_security_fix_version
|
34
45
|
return nil if version_comes_from_multi_dependency_property?
|
35
46
|
|
36
47
|
lowest_security_fix_version
|
37
48
|
end
|
38
49
|
|
50
|
+
sig { override.returns(NilClass) }
|
39
51
|
def latest_resolvable_version_with_no_unlock
|
40
52
|
# Irrelevant, since Nuget has a single dependency file
|
41
53
|
nil
|
42
54
|
end
|
43
55
|
|
56
|
+
sig { override.returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
44
57
|
def updated_requirements
|
45
58
|
RequirementsUpdater.new(
|
46
59
|
requirements: dependency.requirements,
|
47
|
-
latest_version: preferred_resolvable_version_details
|
48
|
-
source_details: preferred_resolvable_version_details
|
49
|
-
&.slice(:nuspec_url, :repo_url, :source_url)
|
60
|
+
latest_version: preferred_resolvable_version_details&.fetch(:version, nil)&.to_s,
|
61
|
+
source_details: preferred_resolvable_version_details&.slice(:nuspec_url, :repo_url, :source_url)
|
50
62
|
).updated_requirements
|
51
63
|
end
|
52
64
|
|
65
|
+
sig { returns(T::Boolean) }
|
53
66
|
def up_to_date?
|
54
67
|
# No need to update transitive dependencies unless they have a vulnerability.
|
55
68
|
return true if !dependency.top_level? && !vulnerable?
|
@@ -62,6 +75,7 @@ module Dependabot
|
|
62
75
|
super
|
63
76
|
end
|
64
77
|
|
78
|
+
sig { returns(T::Boolean) }
|
65
79
|
def requirements_unlocked_or_can_be?
|
66
80
|
# If any requirements have an uninterpolated property in them then
|
67
81
|
# that property couldn't be found, and the requirement therefore
|
@@ -73,6 +87,7 @@ module Dependabot
|
|
73
87
|
|
74
88
|
private
|
75
89
|
|
90
|
+
sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
76
91
|
def preferred_resolvable_version_details
|
77
92
|
# If this dependency is vulnerable, prefer trying to update to the
|
78
93
|
# lowest_resolvable_security_fix_version. Otherwise update all the way
|
@@ -82,6 +97,7 @@ module Dependabot
|
|
82
97
|
latest_version_details
|
83
98
|
end
|
84
99
|
|
100
|
+
sig { override.returns(T::Boolean) }
|
85
101
|
def latest_version_resolvable_with_full_unlock?
|
86
102
|
# We always want a full unlock since any package update could update peer dependencies as well.
|
87
103
|
return true unless version_comes_from_multi_dependency_property?
|
@@ -89,6 +105,7 @@ module Dependabot
|
|
89
105
|
property_updater.update_possible?
|
90
106
|
end
|
91
107
|
|
108
|
+
sig { override.returns(T::Array[Dependabot::Dependency]) }
|
92
109
|
def updated_dependencies_after_full_unlock
|
93
110
|
return property_updater.updated_dependencies if version_comes_from_multi_dependency_property?
|
94
111
|
|
@@ -96,7 +113,7 @@ module Dependabot
|
|
96
113
|
|
97
114
|
updated_dependency = Dependency.new(
|
98
115
|
name: dependency.name,
|
99
|
-
version: latest_version
|
116
|
+
version: latest_version,
|
100
117
|
requirements: updated_requirements,
|
101
118
|
previous_version: dependency.version,
|
102
119
|
previous_requirements: dependency.requirements,
|
@@ -112,47 +129,66 @@ module Dependabot
|
|
112
129
|
updated_dependencies
|
113
130
|
end
|
114
131
|
|
132
|
+
sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
115
133
|
def preferred_version_details
|
116
134
|
return lowest_security_fix_version_details if vulnerable?
|
117
135
|
|
118
136
|
latest_version_details
|
119
137
|
end
|
120
138
|
|
139
|
+
sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
121
140
|
def latest_version_details
|
122
|
-
@latest_version_details ||=
|
141
|
+
@latest_version_details ||=
|
142
|
+
T.let(
|
143
|
+
version_finder.latest_version_details,
|
144
|
+
T.nilable(T::Hash[Symbol, T.untyped])
|
145
|
+
)
|
123
146
|
end
|
124
147
|
|
148
|
+
sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
125
149
|
def lowest_security_fix_version_details
|
126
150
|
@lowest_security_fix_version_details ||=
|
127
|
-
|
151
|
+
T.let(
|
152
|
+
version_finder.lowest_security_fix_version_details,
|
153
|
+
T.nilable(T::Hash[Symbol, T.untyped])
|
154
|
+
)
|
128
155
|
end
|
129
156
|
|
157
|
+
sig { returns(Dependabot::Nuget::UpdateChecker::VersionFinder) }
|
130
158
|
def version_finder
|
131
159
|
@version_finder ||=
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
160
|
+
T.let(
|
161
|
+
VersionFinder.new(
|
162
|
+
dependency: dependency,
|
163
|
+
dependency_files: dependency_files,
|
164
|
+
credentials: credentials,
|
165
|
+
ignored_versions: ignored_versions,
|
166
|
+
raise_on_ignored: @raise_on_ignored,
|
167
|
+
security_advisories: security_advisories,
|
168
|
+
repo_contents_path: @repo_contents_path
|
169
|
+
),
|
170
|
+
T.nilable(Dependabot::Nuget::UpdateChecker::VersionFinder)
|
140
171
|
)
|
141
172
|
end
|
142
173
|
|
174
|
+
sig { returns(Dependabot::Nuget::UpdateChecker::PropertyUpdater) }
|
143
175
|
def property_updater
|
144
176
|
@property_updater ||=
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
177
|
+
T.let(
|
178
|
+
PropertyUpdater.new(
|
179
|
+
dependency: dependency,
|
180
|
+
dependency_files: dependency_files,
|
181
|
+
target_version_details: latest_version_details,
|
182
|
+
credentials: credentials,
|
183
|
+
ignored_versions: ignored_versions,
|
184
|
+
raise_on_ignored: @raise_on_ignored,
|
185
|
+
repo_contents_path: @repo_contents_path
|
186
|
+
),
|
187
|
+
T.nilable(Dependabot::Nuget::UpdateChecker::PropertyUpdater)
|
153
188
|
)
|
154
189
|
end
|
155
190
|
|
191
|
+
sig { returns(T::Boolean) }
|
156
192
|
def version_comes_from_multi_dependency_property?
|
157
193
|
declarations_using_a_property.any? do |requirement|
|
158
194
|
property_name = requirement.fetch(:metadata).fetch(:property_name)
|
@@ -167,20 +203,28 @@ module Dependabot
|
|
167
203
|
end
|
168
204
|
end
|
169
205
|
|
206
|
+
sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
170
207
|
def declarations_using_a_property
|
171
208
|
@declarations_using_a_property ||=
|
172
|
-
|
173
|
-
|
209
|
+
T.let(
|
210
|
+
dependency.requirements
|
211
|
+
.select { |req| req.dig(:metadata, :property_name) },
|
212
|
+
T.nilable(T::Array[T::Hash[Symbol, T.untyped]])
|
213
|
+
)
|
174
214
|
end
|
175
215
|
|
216
|
+
sig { returns(T::Array[Dependabot::Dependency]) }
|
176
217
|
def all_property_based_dependencies
|
177
218
|
@all_property_based_dependencies ||=
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
219
|
+
T.let(
|
220
|
+
Nuget::FileParser.new(
|
221
|
+
dependency_files: dependency_files,
|
222
|
+
source: nil
|
223
|
+
).parse.select do |dep|
|
224
|
+
dep.requirements.any? { |req| req.dig(:metadata, :property_name) }
|
225
|
+
end,
|
226
|
+
T.nilable(T::Array[Dependabot::Dependency])
|
227
|
+
)
|
184
228
|
end
|
185
229
|
end
|
186
230
|
end
|
@@ -17,14 +17,14 @@ module Dependabot
|
|
17
17
|
VERSION_PATTERN = T.let(Gem::Version::VERSION_PATTERN + '(\+[0-9a-zA-Z\-.]+)?', String)
|
18
18
|
ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})?\s*\z/
|
19
19
|
|
20
|
-
sig { override.params(version:
|
20
|
+
sig { override.params(version: VersionParameter).returns(T::Boolean) }
|
21
21
|
def self.correct?(version)
|
22
22
|
return false if version.nil?
|
23
23
|
|
24
24
|
version.to_s.match?(ANCHORED_VERSION_PATTERN)
|
25
25
|
end
|
26
26
|
|
27
|
-
sig { override.params(version:
|
27
|
+
sig { override.params(version: VersionParameter).void }
|
28
28
|
def initialize(version)
|
29
29
|
version = version.to_s.split("+").first || ""
|
30
30
|
@version_string = T.let(version, String)
|
@@ -32,6 +32,11 @@ module Dependabot
|
|
32
32
|
super
|
33
33
|
end
|
34
34
|
|
35
|
+
sig { override.params(version: VersionParameter).returns(Dependabot::Nuget::Version) }
|
36
|
+
def self.new(version)
|
37
|
+
T.cast(super, Dependabot::Nuget::Version)
|
38
|
+
end
|
39
|
+
|
35
40
|
sig { returns(String) }
|
36
41
|
def to_s
|
37
42
|
@version_string
|