dependabot-nuget 0.272.0 → 0.274.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +4 -19
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +0 -51
- data/lib/dependabot/nuget/file_parser.rb +1 -4
- data/lib/dependabot/nuget/file_updater.rb +97 -84
- data/lib/dependabot/nuget/native_discovery/native_dependency_file_discovery.rb +6 -4
- data/lib/dependabot/nuget/native_discovery/native_discovery_json_reader.rb +4 -78
- data/lib/dependabot/nuget/native_discovery/native_project_discovery.rb +0 -1
- data/lib/dependabot/nuget/native_helpers.rb +10 -25
- data/lib/dependabot/nuget/native_update_checker/native_requirements_updater.rb +8 -17
- data/lib/dependabot/nuget/native_update_checker/native_update_checker.rb +10 -45
- data/lib/dependabot/nuget/update_checker/requirements_updater.rb +4 -4
- data/lib/dependabot/nuget/update_checker.rb +1 -2
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8faf1e75a17d2bcd56f2396c6c0f9854b887e2bd1be7e89d3f869f5a2f923ce4
|
4
|
+
data.tar.gz: ab89e33d64147019f89d0625c4325c2edcd6079ddadd3af418bd1c1e999b9976
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 70e59e0078a18db33554fae631c5b4a78593ce97457956ad4ccd827ff6e76be6ee2eb112ac7ad72b91d29d2300496cad82e24d3b27457ea9f2c26cb27d6c82b2
|
7
|
+
data.tar.gz: 1768859035978b5f61b7d509a30de784273684e0949b6f7dccceda2d39321aa56796be6a4addce50d9aa011776ee02694691e60b9eedc409bd04adcede024e72
|
@@ -108,7 +108,6 @@ public partial class AnalyzeWorker
|
|
108
108
|
discovery,
|
109
109
|
dependenciesToUpdate,
|
110
110
|
updatedVersion,
|
111
|
-
dependencyInfo,
|
112
111
|
nugetContext,
|
113
112
|
_logger,
|
114
113
|
CancellationToken.None);
|
@@ -360,7 +359,6 @@ public partial class AnalyzeWorker
|
|
360
359
|
WorkspaceDiscoveryResult discovery,
|
361
360
|
ImmutableHashSet<string> packageIds,
|
362
361
|
NuGetVersion updatedVersion,
|
363
|
-
DependencyInfo dependencyInfo,
|
364
362
|
NuGetContext nugetContext,
|
365
363
|
Logger logger,
|
366
364
|
CancellationToken cancellationToken)
|
@@ -381,23 +379,10 @@ public partial class AnalyzeWorker
|
|
381
379
|
.Select(NuGetFramework.Parse)
|
382
380
|
.ToImmutableArray();
|
383
381
|
|
384
|
-
// When updating dependencies, we only need to consider top-level dependencies
|
385
|
-
var
|
386
|
-
.
|
387
|
-
|
388
|
-
if (string.Compare(d.Name, dependencyInfo.Name, StringComparison.OrdinalIgnoreCase) == 0 &&
|
389
|
-
dependencyInfo.IsVulnerable)
|
390
|
-
{
|
391
|
-
// if this dependency is one we're specifically updating _and_ if it's vulnerable, always update it
|
392
|
-
return true;
|
393
|
-
}
|
394
|
-
else
|
395
|
-
{
|
396
|
-
// otherwise only update if it's a top-level dependency
|
397
|
-
return !d.IsTransitive;
|
398
|
-
}
|
399
|
-
});
|
400
|
-
var projectDependencyNames = relevantDependencies
|
382
|
+
// When updating peer dependencies, we only need to consider top-level dependencies.
|
383
|
+
var projectDependencyNames = projectsWithDependency
|
384
|
+
.SelectMany(p => p.Dependencies)
|
385
|
+
.Where(d => !d.IsTransitive)
|
401
386
|
.Select(d => d.Name)
|
402
387
|
.ToImmutableHashSet(StringComparer.OrdinalIgnoreCase);
|
403
388
|
|
@@ -347,57 +347,6 @@ public partial class AnalyzeWorkerTests : AnalyzeWorkerTestBase
|
|
347
347
|
);
|
348
348
|
}
|
349
349
|
|
350
|
-
[Fact]
|
351
|
-
public async Task AnalyzeVulnerableTransitiveDependencies()
|
352
|
-
{
|
353
|
-
await TestAnalyzeAsync(
|
354
|
-
packages:
|
355
|
-
[
|
356
|
-
MockNuGetPackage.CreateSimplePackage("Some.Transitive.Dependency", "1.0.0", "net8.0"),
|
357
|
-
MockNuGetPackage.CreateSimplePackage("Some.Transitive.Dependency", "1.0.1", "net8.0"),
|
358
|
-
],
|
359
|
-
discovery: new()
|
360
|
-
{
|
361
|
-
Path = "/",
|
362
|
-
Projects = [
|
363
|
-
new()
|
364
|
-
{
|
365
|
-
FilePath = "project.csproj",
|
366
|
-
TargetFrameworks = ["net8.0"],
|
367
|
-
Dependencies = [
|
368
|
-
new("Some.Transitive.Dependency", "1.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true),
|
369
|
-
]
|
370
|
-
}
|
371
|
-
]
|
372
|
-
},
|
373
|
-
dependencyInfo: new()
|
374
|
-
{
|
375
|
-
Name = "Some.Transitive.Dependency",
|
376
|
-
Version = "1.0.0",
|
377
|
-
IsVulnerable = true,
|
378
|
-
IgnoredVersions = [],
|
379
|
-
Vulnerabilities = [
|
380
|
-
new()
|
381
|
-
{
|
382
|
-
DependencyName = "Some.Transitive.Dependency",
|
383
|
-
PackageManager = "nuget",
|
384
|
-
VulnerableVersions = [Requirement.Parse("<= 1.0.0")],
|
385
|
-
SafeVersions = [Requirement.Parse("= 1.0.1")],
|
386
|
-
}
|
387
|
-
]
|
388
|
-
},
|
389
|
-
expectedResult: new()
|
390
|
-
{
|
391
|
-
UpdatedVersion = "1.0.1",
|
392
|
-
CanUpdate = true,
|
393
|
-
VersionComesFromMultiDependencyProperty = false,
|
394
|
-
UpdatedDependencies = [
|
395
|
-
new("Some.Transitive.Dependency", "1.0.1", DependencyType.Unknown, TargetFrameworks: ["net8.0"]),
|
396
|
-
],
|
397
|
-
}
|
398
|
-
);
|
399
|
-
}
|
400
|
-
|
401
350
|
[Fact]
|
402
351
|
public async Task IgnoredVersionsCanHandleWildcardSpecification()
|
403
352
|
{
|
@@ -50,10 +50,7 @@ module Dependabot
|
|
50
50
|
# cache discovery results
|
51
51
|
NativeDiscoveryJsonReader.set_discovery_from_dependency_files(dependency_files: dependency_files,
|
52
52
|
discovery: discovery_json_reader)
|
53
|
-
|
54
|
-
dependency_set = discovery_json_reader.dependency_set(dependency_files: dependency_files,
|
55
|
-
top_level_only: true)
|
56
|
-
dependency_set.dependencies
|
53
|
+
discovery_json_reader.dependency_set.dependencies
|
57
54
|
end
|
58
55
|
|
59
56
|
T.must(self.class.file_dependency_cache[key])
|
@@ -16,16 +16,6 @@ module Dependabot
|
|
16
16
|
class FileUpdater < Dependabot::FileUpdaters::Base
|
17
17
|
extend T::Sig
|
18
18
|
|
19
|
-
DependencyDetails = T.type_alias do
|
20
|
-
{
|
21
|
-
file: String,
|
22
|
-
name: String,
|
23
|
-
version: String,
|
24
|
-
previous_version: String,
|
25
|
-
is_transitive: T::Boolean
|
26
|
-
}
|
27
|
-
end
|
28
|
-
|
29
19
|
sig { override.returns(T::Array[Regexp]) }
|
30
20
|
def self.updated_files_regex
|
31
21
|
[
|
@@ -62,21 +52,9 @@ module Dependabot
|
|
62
52
|
def updated_dependency_files
|
63
53
|
base_dir = "/"
|
64
54
|
SharedHelpers.in_a_temporary_repo_directory(base_dir, repo_contents_path) do
|
65
|
-
|
66
|
-
|
67
|
-
name = T.let(dep_details.fetch(:name), String)
|
68
|
-
version = T.let(dep_details.fetch(:version), String)
|
69
|
-
previous_version = T.let(dep_details.fetch(:previous_version), String)
|
70
|
-
is_transitive = T.let(dep_details.fetch(:is_transitive), T::Boolean)
|
71
|
-
NativeHelpers.run_nuget_updater_tool(repo_root: T.must(repo_contents_path),
|
72
|
-
proj_path: file,
|
73
|
-
dependency_name: name,
|
74
|
-
version: version,
|
75
|
-
previous_version: previous_version,
|
76
|
-
is_transitive: is_transitive,
|
77
|
-
credentials: credentials)
|
55
|
+
dependencies.each do |dependency|
|
56
|
+
try_update_projects(dependency) || try_update_json(dependency)
|
78
57
|
end
|
79
|
-
|
80
58
|
updated_files = dependency_files.filter_map do |f|
|
81
59
|
updated_content = File.read(dependency_file_path(f))
|
82
60
|
next if updated_content == f.content
|
@@ -96,69 +74,104 @@ module Dependabot
|
|
96
74
|
|
97
75
|
private
|
98
76
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
77
|
+
sig { params(dependency: Dependabot::Dependency).returns(T::Boolean) }
|
78
|
+
def try_update_projects(dependency)
|
79
|
+
update_ran = T.let(false, T::Boolean)
|
80
|
+
checked_files = Set.new
|
81
|
+
|
82
|
+
# run update for each project file
|
83
|
+
project_files.each do |project_file|
|
84
|
+
project_dependencies = project_dependencies(project_file)
|
85
|
+
proj_path = dependency_file_path(project_file)
|
86
|
+
|
87
|
+
next unless project_dependencies.any? { |dep| dep.name.casecmp?(dependency.name) }
|
88
|
+
|
89
|
+
next unless repo_contents_path
|
90
|
+
|
91
|
+
checked_key = "#{project_file.name}-#{dependency.name}#{dependency.version}"
|
92
|
+
call_nuget_updater_tool(dependency, proj_path) unless checked_files.include?(checked_key)
|
93
|
+
|
94
|
+
checked_files.add(checked_key)
|
95
|
+
# We need to check the downstream references even though we're already evaluated the file
|
96
|
+
downstream_files = referenced_project_paths(project_file)
|
97
|
+
downstream_files.each do |downstream_file|
|
98
|
+
checked_files.add("#{downstream_file}-#{dependency.name}#{dependency.version}")
|
113
99
|
end
|
100
|
+
update_ran = true
|
101
|
+
end
|
102
|
+
update_ran
|
103
|
+
end
|
104
|
+
|
105
|
+
sig { params(dependency: Dependabot::Dependency).returns(T::Boolean) }
|
106
|
+
def try_update_json(dependency)
|
107
|
+
if dotnet_tools_json_dependencies.any? { |dep| dep.name.casecmp?(dependency.name) } ||
|
108
|
+
global_json_dependencies.any? { |dep| dep.name.casecmp?(dependency.name) }
|
109
|
+
|
110
|
+
# We just need to feed the updater a project file, grab the first
|
111
|
+
project_file = T.must(project_files.first)
|
112
|
+
proj_path = dependency_file_path(project_file)
|
113
|
+
|
114
|
+
return false unless repo_contents_path
|
115
|
+
|
116
|
+
call_nuget_updater_tool(dependency, proj_path)
|
117
|
+
return true
|
118
|
+
end
|
114
119
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
120
|
+
false
|
121
|
+
end
|
122
|
+
|
123
|
+
sig { params(dependency: Dependency, proj_path: String).void }
|
124
|
+
def call_nuget_updater_tool(dependency, proj_path)
|
125
|
+
NativeHelpers.run_nuget_updater_tool(repo_root: T.must(repo_contents_path), proj_path: proj_path,
|
126
|
+
dependency: dependency, is_transitive: !dependency.top_level?,
|
127
|
+
credentials: credentials)
|
128
|
+
|
129
|
+
# Tests need to track how many times we call the tooling updater to ensure we don't recurse needlessly
|
130
|
+
# Ideally we should find a way to not run this code in prod
|
131
|
+
# (or a better way to track calls made to NativeHelpers)
|
132
|
+
@update_tooling_calls ||= T.let({}, T.nilable(T::Hash[String, Integer]))
|
133
|
+
key = "#{proj_path.delete_prefix(T.must(repo_contents_path))}+#{dependency.name}"
|
134
|
+
@update_tooling_calls[key] =
|
135
|
+
if @update_tooling_calls[key]
|
136
|
+
T.must(@update_tooling_calls[key]) + 1
|
137
|
+
else
|
138
|
+
1
|
131
139
|
end
|
132
|
-
|
133
|
-
|
134
|
-
#
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
140
|
+
end
|
141
|
+
|
142
|
+
# Don't call this from outside tests, we're only checking that we aren't recursing needlessly
|
143
|
+
sig { returns(T.nilable(T::Hash[String, Integer])) }
|
144
|
+
def testonly_update_tooling_calls
|
145
|
+
@update_tooling_calls
|
146
|
+
end
|
147
|
+
|
148
|
+
sig { returns(T.nilable(NativeWorkspaceDiscovery)) }
|
149
|
+
def workspace
|
150
|
+
discovery_json_reader = NativeDiscoveryJsonReader.get_discovery_from_dependency_files(dependency_files)
|
151
|
+
discovery_json_reader.workspace_discovery
|
152
|
+
end
|
153
|
+
|
154
|
+
sig { params(project_file: Dependabot::DependencyFile).returns(T::Array[String]) }
|
155
|
+
def referenced_project_paths(project_file)
|
156
|
+
workspace&.projects&.find { |p| p.file_path == project_file.name }&.referenced_project_paths || []
|
157
|
+
end
|
158
|
+
|
159
|
+
sig { params(project_file: Dependabot::DependencyFile).returns(T::Array[NativeDependencyDetails]) }
|
160
|
+
def project_dependencies(project_file)
|
161
|
+
workspace&.projects&.find do |p|
|
162
|
+
full_project_file_path = File.join(project_file.directory, project_file.name)
|
163
|
+
p.file_path == full_project_file_path
|
164
|
+
end&.dependencies || []
|
165
|
+
end
|
166
|
+
|
167
|
+
sig { returns(T::Array[NativeDependencyDetails]) }
|
168
|
+
def global_json_dependencies
|
169
|
+
workspace&.global_json&.dependencies || []
|
170
|
+
end
|
171
|
+
|
172
|
+
sig { returns(T::Array[NativeDependencyDetails]) }
|
173
|
+
def dotnet_tools_json_dependencies
|
174
|
+
workspace&.dotnet_tools_json&.dependencies || []
|
162
175
|
end
|
163
176
|
|
164
177
|
# rubocop:disable Metrics/PerceivedComplexity
|
@@ -106,20 +106,22 @@ module Dependabot
|
|
106
106
|
.returns(T.nilable(T::Hash[Symbol, T.untyped]))
|
107
107
|
end
|
108
108
|
def build_requirement(file_name, dependency_details)
|
109
|
+
return if dependency_details.is_transitive
|
110
|
+
|
109
111
|
version = dependency_details.version
|
110
112
|
version = nil if version&.empty?
|
111
|
-
metadata = { is_transitive: dependency_details.is_transitive }
|
112
113
|
|
113
114
|
requirement = {
|
114
115
|
requirement: version,
|
115
116
|
file: file_name,
|
116
117
|
groups: [dependency_details.is_dev_dependency ? "devDependencies" : "dependencies"],
|
117
|
-
source: nil
|
118
|
-
metadata: metadata
|
118
|
+
source: nil
|
119
119
|
}
|
120
120
|
|
121
121
|
property_name = dependency_details.evaluation&.root_property_name
|
122
|
-
|
122
|
+
return requirement unless property_name
|
123
|
+
|
124
|
+
requirement[:metadata] = { property_name: property_name }
|
123
125
|
requirement
|
124
126
|
end
|
125
127
|
end
|
@@ -125,90 +125,16 @@ module Dependabot
|
|
125
125
|
sig { returns(T.nilable(NativeWorkspaceDiscovery)) }
|
126
126
|
attr_reader :workspace_discovery
|
127
127
|
|
128
|
+
sig { returns(Dependabot::FileParsers::Base::DependencySet) }
|
129
|
+
attr_reader :dependency_set
|
130
|
+
|
128
131
|
sig { params(discovery_json: DependencyFile).void }
|
129
132
|
def initialize(discovery_json:)
|
130
133
|
@discovery_json = discovery_json
|
131
134
|
@workspace_discovery = T.let(read_workspace_discovery, T.nilable(Dependabot::Nuget::NativeWorkspaceDiscovery))
|
135
|
+
@dependency_set = T.let(read_dependency_set, Dependabot::FileParsers::Base::DependencySet)
|
132
136
|
end
|
133
137
|
|
134
|
-
# rubocop:disable Metrics/AbcSize
|
135
|
-
# rubocop:disable Metrics/MethodLength
|
136
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
137
|
-
sig do
|
138
|
-
params(
|
139
|
-
dependency_files: T::Array[Dependabot::DependencyFile],
|
140
|
-
top_level_only: T::Boolean
|
141
|
-
).returns(Dependabot::FileParsers::Base::DependencySet)
|
142
|
-
end
|
143
|
-
def dependency_set(dependency_files:, top_level_only:)
|
144
|
-
# dependencies must be recalculated so that we:
|
145
|
-
# 1. only return dependencies that are in the file set we reported earlier
|
146
|
-
# see https://github.com/dependabot/dependabot-core/issues/10303
|
147
|
-
# 2. the reported version is the minimum across all requirements; this ensures that we get the opportunity
|
148
|
-
# to update everything later
|
149
|
-
dependency_file_set = T.let(Set.new(dependency_files.map do |df|
|
150
|
-
Pathname.new(File.join(df.directory, df.name)).cleanpath.to_path
|
151
|
-
end), T::Set[String])
|
152
|
-
|
153
|
-
rebuilt_dependencies = read_dependency_set.dependencies.filter_map do |dep|
|
154
|
-
# only report requirements in files we know about
|
155
|
-
matching_requirements = dep.requirements.filter do |req|
|
156
|
-
file = T.let(req.fetch(:file), String)
|
157
|
-
dependency_file_set.include?(file)
|
158
|
-
end
|
159
|
-
|
160
|
-
# find the minimum version across all requirements
|
161
|
-
min_version = matching_requirements.filter_map do |req|
|
162
|
-
v = T.let(req.fetch(:requirement), T.nilable(String))
|
163
|
-
next unless v
|
164
|
-
|
165
|
-
Dependabot::Nuget::Version.new(v)
|
166
|
-
end.min
|
167
|
-
next unless min_version
|
168
|
-
|
169
|
-
# only return dependency requirements that are top-level
|
170
|
-
if top_level_only
|
171
|
-
matching_requirements.reject! do |req|
|
172
|
-
metadata = T.let(req.fetch(:metadata), T::Hash[Symbol, T.untyped])
|
173
|
-
T.let(metadata.fetch(:is_transitive), T::Boolean)
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
# we might need to return a dependency like this
|
178
|
-
dep_without_reqs = Dependabot::Dependency.new(
|
179
|
-
name: dep.name,
|
180
|
-
version: min_version.to_s,
|
181
|
-
package_manager: "nuget",
|
182
|
-
requirements: []
|
183
|
-
)
|
184
|
-
|
185
|
-
dep_with_reqs = matching_requirements.filter_map do |req|
|
186
|
-
version = T.let(req.fetch(:requirement, nil), T.nilable(String))
|
187
|
-
next unless version
|
188
|
-
|
189
|
-
Dependabot::Dependency.new(
|
190
|
-
name: dep.name,
|
191
|
-
version: min_version.to_s,
|
192
|
-
package_manager: "nuget",
|
193
|
-
requirements: [req]
|
194
|
-
)
|
195
|
-
end
|
196
|
-
|
197
|
-
# if only returning top-level dependencies and we had no non-transitive requirements, return an empty
|
198
|
-
# dependency so it can be tracked for security updates
|
199
|
-
matching_requirements.empty? && top_level_only ? [dep_without_reqs] : dep_with_reqs
|
200
|
-
end.flatten
|
201
|
-
|
202
|
-
final_dependency_set = Dependabot::FileParsers::Base::DependencySet.new
|
203
|
-
rebuilt_dependencies.each do |dep|
|
204
|
-
final_dependency_set << dep
|
205
|
-
end
|
206
|
-
final_dependency_set
|
207
|
-
end
|
208
|
-
# rubocop:enable Metrics/PerceivedComplexity
|
209
|
-
# rubocop:enable Metrics/MethodLength
|
210
|
-
# rubocop:enable Metrics/AbcSize
|
211
|
-
|
212
138
|
private
|
213
139
|
|
214
140
|
sig { returns(DependencyFile) }
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# typed: strong
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "dependabot/file_parsers/base/dependency_set"
|
5
4
|
require "dependabot/nuget/native_discovery/native_dependency_details"
|
6
5
|
require "dependabot/nuget/native_discovery/native_property_details"
|
7
6
|
require "sorbet-runtime"
|
@@ -171,18 +171,10 @@ module Dependabot
|
|
171
171
|
|
172
172
|
# rubocop:disable Metrics/MethodLength
|
173
173
|
sig do
|
174
|
-
params(
|
175
|
-
|
176
|
-
proj_path: String,
|
177
|
-
dependency_name: String,
|
178
|
-
version: String,
|
179
|
-
previous_version: String,
|
180
|
-
is_transitive: T::Boolean,
|
181
|
-
result_output_path: String
|
182
|
-
).returns([String, String])
|
174
|
+
params(repo_root: String, proj_path: String, dependency: Dependency,
|
175
|
+
is_transitive: T::Boolean, result_output_path: String).returns([String, String])
|
183
176
|
end
|
184
|
-
def self.get_nuget_updater_tool_command(repo_root:, proj_path:,
|
185
|
-
is_transitive:, result_output_path:)
|
177
|
+
def self.get_nuget_updater_tool_command(repo_root:, proj_path:, dependency:, is_transitive:, result_output_path:)
|
186
178
|
exe_path = File.join(native_helpers_root, "NuGetUpdater", "NuGetUpdater.Cli")
|
187
179
|
command_parts = [
|
188
180
|
exe_path,
|
@@ -192,11 +184,11 @@ module Dependabot
|
|
192
184
|
"--solution-or-project",
|
193
185
|
proj_path,
|
194
186
|
"--dependency",
|
195
|
-
|
187
|
+
dependency.name,
|
196
188
|
"--new-version",
|
197
|
-
version,
|
189
|
+
dependency.version,
|
198
190
|
"--previous-version",
|
199
|
-
previous_version,
|
191
|
+
dependency.previous_version,
|
200
192
|
is_transitive ? "--transitive" : nil,
|
201
193
|
"--result-output-path",
|
202
194
|
result_output_path,
|
@@ -237,21 +229,14 @@ module Dependabot
|
|
237
229
|
params(
|
238
230
|
repo_root: String,
|
239
231
|
proj_path: String,
|
240
|
-
|
241
|
-
version: String,
|
242
|
-
previous_version: String,
|
232
|
+
dependency: Dependency,
|
243
233
|
is_transitive: T::Boolean,
|
244
234
|
credentials: T::Array[Dependabot::Credential]
|
245
235
|
).void
|
246
236
|
end
|
247
|
-
def self.run_nuget_updater_tool(repo_root:, proj_path:,
|
248
|
-
|
249
|
-
|
250
|
-
proj_path: proj_path,
|
251
|
-
dependency_name: dependency_name,
|
252
|
-
version: version,
|
253
|
-
previous_version: previous_version,
|
254
|
-
is_transitive: is_transitive,
|
237
|
+
def self.run_nuget_updater_tool(repo_root:, proj_path:, dependency:, is_transitive:, credentials:)
|
238
|
+
(command, fingerprint) = get_nuget_updater_tool_command(repo_root: repo_root, proj_path: proj_path,
|
239
|
+
dependency: dependency, is_transitive: is_transitive,
|
255
240
|
result_output_path: update_result_file_path)
|
256
241
|
|
257
242
|
puts "running NuGet updater:\n" + command
|
@@ -21,18 +21,15 @@ module Dependabot
|
|
21
21
|
sig do
|
22
22
|
params(
|
23
23
|
requirements: T::Array[T::Hash[Symbol, T.untyped]],
|
24
|
-
dependency_details: T.nilable(Dependabot::Nuget::NativeDependencyDetails)
|
25
|
-
vulnerable: T::Boolean
|
24
|
+
dependency_details: T.nilable(Dependabot::Nuget::NativeDependencyDetails)
|
26
25
|
)
|
27
26
|
.void
|
28
27
|
end
|
29
|
-
def initialize(requirements:, dependency_details
|
28
|
+
def initialize(requirements:, dependency_details:)
|
30
29
|
@requirements = requirements
|
31
30
|
@dependency_details = dependency_details
|
32
|
-
@vulnerable = vulnerable
|
33
31
|
end
|
34
32
|
|
35
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
36
33
|
sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
37
34
|
def updated_requirements
|
38
35
|
return requirements unless clean_version
|
@@ -40,18 +37,13 @@ module Dependabot
|
|
40
37
|
# NOTE: Order is important here. The FileUpdater needs the updated
|
41
38
|
# requirement at index `i` to correspond to the previous requirement
|
42
39
|
# at the same index.
|
43
|
-
requirements.
|
44
|
-
next if
|
45
|
-
|
46
|
-
previous_requirement = req.fetch(:requirement)
|
47
|
-
req[:metadata][:previous_requirement] = previous_requirement
|
48
|
-
|
49
|
-
next req if previous_requirement.nil?
|
50
|
-
next req if previous_requirement.include?(",")
|
40
|
+
requirements.map do |req|
|
41
|
+
next req if req.fetch(:requirement).nil?
|
42
|
+
next req if req.fetch(:requirement).include?(",")
|
51
43
|
|
52
44
|
new_req =
|
53
|
-
if
|
54
|
-
update_wildcard_requirement(
|
45
|
+
if req.fetch(:requirement).include?("*")
|
46
|
+
update_wildcard_requirement(req.fetch(:requirement))
|
55
47
|
else
|
56
48
|
# Since range requirements are excluded by the line above we can
|
57
49
|
# replace anything that looks like a version with the new
|
@@ -62,7 +54,7 @@ module Dependabot
|
|
62
54
|
)
|
63
55
|
end
|
64
56
|
|
65
|
-
next req if new_req ==
|
57
|
+
next req if new_req == req.fetch(:requirement)
|
66
58
|
|
67
59
|
new_source = req[:source]&.dup
|
68
60
|
unless @dependency_details.nil?
|
@@ -75,7 +67,6 @@ module Dependabot
|
|
75
67
|
req.merge({ requirement: new_req, source: new_source })
|
76
68
|
end
|
77
69
|
end
|
78
|
-
# rubocop:enable Metrics/PerceivedComplexity
|
79
70
|
|
80
71
|
private
|
81
72
|
|
@@ -56,8 +56,7 @@ module Dependabot
|
|
56
56
|
dep_details = updated_dependency_details.find { |d| d.name.casecmp?(dependency.name) }
|
57
57
|
NativeRequirementsUpdater.new(
|
58
58
|
requirements: dependency.requirements,
|
59
|
-
dependency_details: dep_details
|
60
|
-
vulnerable: vulnerable?
|
59
|
+
dependency_details: dep_details
|
61
60
|
).updated_requirements
|
62
61
|
end
|
63
62
|
|
@@ -113,10 +112,9 @@ module Dependabot
|
|
113
112
|
|
114
113
|
sig { void }
|
115
114
|
def write_dependency_info
|
116
|
-
dependency_version = T.let(dependency.requirements.first&.fetch(:requirement, nil), T.nilable(String))
|
117
115
|
dependency_info = {
|
118
116
|
Name: dependency.name,
|
119
|
-
Version:
|
117
|
+
Version: dependency.version.to_s,
|
120
118
|
IsVulnerable: vulnerable?,
|
121
119
|
IgnoredVersions: ignored_versions,
|
122
120
|
Vulnerabilities: security_advisories.map do |vulnerability|
|
@@ -143,7 +141,7 @@ module Dependabot
|
|
143
141
|
sig { returns(Dependabot::FileParsers::Base::DependencySet) }
|
144
142
|
def discovered_dependencies
|
145
143
|
discovery_json_reader = NativeDiscoveryJsonReader.get_discovery_from_dependency_files(dependency_files)
|
146
|
-
discovery_json_reader.dependency_set
|
144
|
+
discovery_json_reader.dependency_set
|
147
145
|
end
|
148
146
|
|
149
147
|
sig { override.returns(T::Boolean) }
|
@@ -152,10 +150,6 @@ module Dependabot
|
|
152
150
|
true
|
153
151
|
end
|
154
152
|
|
155
|
-
# rubocop:disable Metrics/AbcSize
|
156
|
-
# rubocop:disable Metrics/BlockLength
|
157
|
-
# rubocop:disable Metrics/MethodLength
|
158
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
159
153
|
sig { override.returns(T::Array[Dependabot::Dependency]) }
|
160
154
|
def updated_dependencies_after_full_unlock
|
161
155
|
dependencies = discovered_dependencies.dependencies
|
@@ -163,16 +157,14 @@ module Dependabot
|
|
163
157
|
dep = dependencies.find { |d| d.name.casecmp(dependency_details.name)&.zero? }
|
164
158
|
next unless dep
|
165
159
|
|
166
|
-
|
160
|
+
metadata = {}
|
167
161
|
# For peer dependencies, instruct updater to not directly update this dependency
|
168
|
-
|
169
|
-
dep_metadata[:is_vulnerable] = vulnerable?
|
162
|
+
metadata = { information_only: true } unless dependency.name.casecmp(dependency_details.name)&.zero?
|
170
163
|
|
171
164
|
# rebuild the new requirements with the updated dependency details
|
172
165
|
updated_reqs = dep.requirements.map do |r|
|
173
166
|
r = r.clone
|
174
|
-
|
175
|
-
r[:requirement] = dependency_details.version # set new version
|
167
|
+
r[:requirement] = dependency_details.version
|
176
168
|
r[:source] = {
|
177
169
|
type: "nuget_repo",
|
178
170
|
source_url: dependency_details.info_url
|
@@ -180,44 +172,17 @@ module Dependabot
|
|
180
172
|
r
|
181
173
|
end
|
182
174
|
|
183
|
-
reqs = dep.requirements
|
184
|
-
unless vulnerable?
|
185
|
-
updated_reqs = updated_reqs.filter do |r|
|
186
|
-
req_metadata = T.let(r.fetch(:metadata, {}), T::Hash[Symbol, T.untyped])
|
187
|
-
!T.let(req_metadata[:is_transitive], T::Boolean)
|
188
|
-
end
|
189
|
-
reqs = reqs.filter do |r|
|
190
|
-
req_metadata = T.let(r.fetch(:metadata, {}), T::Hash[Symbol, T.untyped])
|
191
|
-
!T.let(req_metadata[:is_transitive], T::Boolean)
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
# report back the highest version that all of these dependencies can be updated to
|
196
|
-
# this will ensure that we get a chance to update all relevant dependencies
|
197
|
-
max_updatable_version = updated_reqs.filter_map do |r|
|
198
|
-
v = T.let(r.fetch(:requirement, nil), T.nilable(String))
|
199
|
-
next unless v
|
200
|
-
|
201
|
-
Dependabot::Nuget::Version.new(v)
|
202
|
-
end.max
|
203
|
-
next unless max_updatable_version
|
204
|
-
|
205
|
-
previous_version = T.let(dep.requirements.first&.fetch(:requirement, nil), T.nilable(String))
|
206
175
|
Dependency.new(
|
207
176
|
name: dep.name,
|
208
|
-
version:
|
177
|
+
version: dependency_details.version,
|
209
178
|
requirements: updated_reqs,
|
210
|
-
previous_version:
|
211
|
-
previous_requirements:
|
179
|
+
previous_version: dep.version,
|
180
|
+
previous_requirements: dep.requirements,
|
212
181
|
package_manager: dep.package_manager,
|
213
|
-
metadata:
|
182
|
+
metadata: metadata
|
214
183
|
)
|
215
184
|
end
|
216
185
|
end
|
217
|
-
# rubocop:enable Metrics/PerceivedComplexity
|
218
|
-
# rubocop:enable Metrics/MethodLength
|
219
|
-
# rubocop:enable Metrics/BlockLength
|
220
|
-
# rubocop:enable Metrics/AbcSize
|
221
186
|
|
222
187
|
sig { returns(T::Array[Dependabot::Nuget::NativeDependencyDetails]) }
|
223
188
|
def updated_dependency_details
|
@@ -37,11 +37,10 @@ module Dependabot
|
|
37
37
|
def updated_requirements
|
38
38
|
return requirements unless latest_version
|
39
39
|
|
40
|
+
# NOTE: Order is important here. The FileUpdater needs the updated
|
41
|
+
# requirement at index `i` to correspond to the previous requirement
|
42
|
+
# at the same index.
|
40
43
|
requirements.map do |req|
|
41
|
-
req[:metadata] ||= {}
|
42
|
-
req[:metadata][:is_transitive] = false
|
43
|
-
req[:metadata][:previous_requirement] = req[:requirement]
|
44
|
-
|
45
44
|
next req if req.fetch(:requirement).nil?
|
46
45
|
next req if req.fetch(:requirement).include?(",")
|
47
46
|
|
@@ -57,6 +56,7 @@ module Dependabot
|
|
57
56
|
latest_version.to_s
|
58
57
|
)
|
59
58
|
end
|
59
|
+
|
60
60
|
next req if new_req == req.fetch(:requirement)
|
61
61
|
|
62
62
|
req.merge(requirement: new_req, source: updated_source)
|
@@ -166,8 +166,7 @@ module Dependabot
|
|
166
166
|
requirements: updated_requirements,
|
167
167
|
previous_version: dependency.version,
|
168
168
|
previous_requirements: dependency.requirements,
|
169
|
-
package_manager: dependency.package_manager
|
170
|
-
metadata: { is_vulnerable: vulnerable? }
|
169
|
+
package_manager: dependency.package_manager
|
171
170
|
)
|
172
171
|
updated_dependencies = [updated_dependency]
|
173
172
|
updated_dependencies += DependencyFinder.new(
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dependabot-nuget
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.274.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dependabot
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dependabot-common
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.274.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.274.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rubyzip
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -463,7 +463,7 @@ licenses:
|
|
463
463
|
- MIT
|
464
464
|
metadata:
|
465
465
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
466
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
466
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.274.0
|
467
467
|
post_install_message:
|
468
468
|
rdoc_options: []
|
469
469
|
require_paths:
|