dependabot-nuget 0.272.0 → 0.273.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 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: