dependabot-nuget 0.272.0 → 0.273.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b33f6b0a817def66d738b6d998bedf0248881c225ddf6b97fa0a5405d92b9d23
4
- data.tar.gz: 9e736306b9d21e95639627ea2fe585d2e47a8979e1096545b4da2ed49e8dbd5f
3
+ metadata.gz: e74194b3b13f1f629b109a0dd66cff5e6063f898a0574b0af4a47204e2eaffa1
4
+ data.tar.gz: bb02d23751f1c81d9f0eaafd1e9afb1c1fd3ae3f48a0b31f902c62446d431905
5
5
  SHA512:
6
- metadata.gz: 4dddbe1b9c9cbf4fb9d7876c143cfbd713bf2f6ca501210ae40a7c37bb2076687ea75996042e9ccc6582a6cd535a24eb3b2caa3143b5e8c3ef8ff500455f7827
7
- data.tar.gz: f51748be257babb63de285cec8981ca84e580fa48b6d6fec2a89892f485f46ae237af86ab387a584c27c8f207ba1ae16167570bffdc59cf3cd4bb64ac27e9830
6
+ metadata.gz: 39c13b396b743cbda78796d1539e67d9d44b222a9ca16edbc79468f29afddd83648434f534feb5f61957be751ec1e5d06b6387ebd4bbcc1aaeb88a2049fee69a
7
+ data.tar.gz: 16e2fa90c7e2b9214f5b63d88d8591d17a74ccee2db0dd82b0439d07fcbdaa3483297cdd5611fc5fae440e6a2511d5f0d16890166acd1a5035ac375a209f950c
@@ -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 _UNLESS_ it's specifically vulnerable
385
- var relevantDependencies = projectsWithDependency.SelectMany(p => p.Dependencies)
386
- .Where(d =>
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
- # we only return top-level dependencies and requirements here
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
- expanded_dependency_details.each do |dep_details|
66
- file = T.let(dep_details.fetch(:file), String)
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
- # rubocop:disable Metrics/AbcSize
100
- sig { returns(T::Array[DependencyDetails]) }
101
- def expanded_dependency_details
102
- discovery_json_reader = NativeDiscoveryJsonReader.get_discovery_from_dependency_files(dependency_files)
103
- dependency_set = discovery_json_reader.dependency_set(dependency_files: dependency_files, top_level_only: false)
104
- all_dependencies = dependency_set.dependencies
105
- dependencies.map do |dep|
106
- # if vulnerable metadata is set, re-fetch all requirements from discovery
107
- is_vulnerable = T.let(dep.metadata.fetch(:is_vulnerable, false), T::Boolean)
108
- relevant_dependencies = all_dependencies.filter { |d| d.name.casecmp?(dep.name) }
109
- candidate_vulnerable_dependency = T.must(relevant_dependencies.first)
110
- relevant_dependency = is_vulnerable ? candidate_vulnerable_dependency : dep
111
- relevant_details = relevant_dependency.requirements.filter_map do |req|
112
- dependency_details_from_requirement(dep.name, req, is_vulnerable: is_vulnerable)
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
- next relevant_details if relevant_details.any?
116
-
117
- # If we didn't find anything to update, we're in a very specific corner case: we were explicitly asked to
118
- # (1) update a certain dependency, (2) it wasn't listed as a security update, but (3) it only exists as a
119
- # transitive dependency. In this case, we need to rebuild the dependency requirements as if this were a
120
- # security update so that we can perform the appropriate update.
121
- candidate_vulnerable_dependency.requirements.filter_map do |req|
122
- rebuilt_req = {
123
- file: req[:file], # simple copy
124
- requirement: relevant_dependency.version, # the newly available version
125
- metadata: {
126
- is_transitive: T.let(req[:metadata], T::Hash[Symbol, T.untyped])[:is_transitive], # simple copy
127
- previous_requirement: req[:requirement] # the old requirement's "current" version is now the "previous"
128
- }
129
- }
130
- dependency_details_from_requirement(dep.name, rebuilt_req, is_vulnerable: true)
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
- end.flatten
133
- end
134
- # rubocop:enable Metrics/AbcSize
135
-
136
- sig do
137
- params(
138
- name: String,
139
- requirement: T::Hash[Symbol, T.untyped],
140
- is_vulnerable: T::Boolean
141
- ).returns(T.nilable(DependencyDetails))
142
- end
143
- def dependency_details_from_requirement(name, requirement, is_vulnerable:)
144
- metadata = T.let(requirement.fetch(:metadata), T::Hash[Symbol, T.untyped])
145
- current_file = T.let(requirement.fetch(:file), String)
146
- return nil unless current_file.match?(/\.(cs|vb|fs)proj$/)
147
-
148
- is_transitive = T.let(metadata.fetch(:is_transitive), T::Boolean)
149
- return nil if !is_vulnerable && is_transitive
150
-
151
- version = T.let(requirement.fetch(:requirement), String)
152
- previous_version = T.let(metadata[:previous_requirement], String)
153
- return nil if version == previous_version
154
-
155
- {
156
- file: T.let(requirement.fetch(:file), String),
157
- name: name,
158
- version: version,
159
- previous_version: previous_version,
160
- is_transitive: is_transitive
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
- metadata[:property_name] = property_name if property_name
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
- repo_root: String,
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:, dependency_name:, version:, previous_version:,
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
- dependency_name,
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
- dependency_name: String,
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:, dependency_name:, version:, previous_version:,
248
- is_transitive:, credentials:)
249
- (command, fingerprint) = get_nuget_updater_tool_command(repo_root: repo_root,
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:, vulnerable:)
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.filter_map do |req|
44
- next if !@vulnerable && req[:metadata][:is_transitive]
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 previous_requirement.include?("*")
54
- update_wildcard_requirement(previous_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 == previous_requirement
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: dependency_version || dependency.version.to_s,
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(dependency_files: dependency_files, top_level_only: false)
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
- dep_metadata = T.let({}, T::Hash[Symbol, T.untyped])
160
+ metadata = {}
167
161
  # For peer dependencies, instruct updater to not directly update this dependency
168
- dep_metadata[:information_only] = true unless dependency.name.casecmp(dependency_details.name)&.zero?
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
- T.let(r[:metadata], T::Hash[Symbol, T.untyped])[:previous_requirement] = r[:requirement] # keep old version
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: max_updatable_version.to_s,
177
+ version: dependency_details.version,
209
178
  requirements: updated_reqs,
210
- previous_version: previous_version,
211
- previous_requirements: reqs,
179
+ previous_version: dep.version,
180
+ previous_requirements: dep.requirements,
212
181
  package_manager: dep.package_manager,
213
- metadata: dep_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.272.0
4
+ version: 0.273.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-08-22 00:00:00.000000000 Z
11
+ date: 2024-08-29 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.272.0
19
+ version: 0.273.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.272.0
26
+ version: 0.273.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.272.0
466
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.273.0
467
467
  post_install_message:
468
468
  rdoc_options: []
469
469
  require_paths: