dependabot-nuget 0.247.0 → 0.248.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9e8dda5e47b38dec152ba8797986aaaca62fde7dbed194960864b779932d6ff7
4
- data.tar.gz: 4f1cb76b3dafc332d90ddf7acec0b39c6295d2d9749741e3229af6ad7d7e363d
3
+ metadata.gz: 60679d8e50f3e96aa05400b03ccc9e0dd491c1a7cf340c4c7a39bcb48675c3f6
4
+ data.tar.gz: 235eb5b57423534578945568766179c2805c6c1e19b5bdb806cc4fd5a5e78dc7
5
5
  SHA512:
6
- metadata.gz: c350131e183da643b7caf57a76acc2cb954e9d7f0a4532b340db90a064f0e1b7d735a531d2bea8efea6ee483060b3dbb8efb4a8e1567d2c9d30d88bc907848f2
7
- data.tar.gz: 9f2a6505e1eca5a2fbe8369e8e21ce0b5eabc4c658bec9d628b5250c16f78f40a7c8b19bc0778b2b7fe6e0c3b215a71b2282407544eb0f6808bdfde3da35d8e0
6
+ metadata.gz: 1976d20f2b23920eb44176098e89109ee5e969f7e12eaa959e06948e543b9383dcf08c7521eeb9f69602fab37f17ffaafc937e203cce68439327d9735590e1b9
7
+ data.tar.gz: d240a0489a0ab0dc72283ea736a55965cb13a2fe375cb7eb5a98beb473f9e227bf6ec52a07fba05f2177ee228c716197f60d5fe35d3170b1687aaa07648915eb
@@ -25,7 +25,7 @@ module Dependabot
25
25
  return true if filenames.any? { |f| f.match?("^src$") }
26
26
  return true if filenames.any? { |f| f.end_with?(".proj") }
27
27
 
28
- filenames.any? { |name| name.match?(/\.[a-z]{2}proj$/) }
28
+ filenames.any? { |name| name.match?(/\.(cs|vb|fs)proj$/) }
29
29
  end
30
30
 
31
31
  sig { override.returns(String) }
@@ -53,7 +53,7 @@ module Dependabot
53
53
  end
54
54
 
55
55
  sig { override.returns(T::Array[DependencyFile]) }
56
- def fetch_files # rubocop:disable Metrics/AbcSize
56
+ def fetch_files
57
57
  fetched_files = []
58
58
  fetched_files += project_files
59
59
  fetched_files += directory_build_files
@@ -73,10 +73,7 @@ module Dependabot
73
73
  if project_files.none? && packages_config_files.none?
74
74
  raise T.must(@missing_sln_project_file_errors.first) if @missing_sln_project_file_errors&.any?
75
75
 
76
- raise(
77
- Dependabot::DependencyFileNotFound,
78
- File.join(directory, "<anything>.(cs|vb|fs)proj")
79
- )
76
+ raise_dependency_file_not_found
80
77
  end
81
78
 
82
79
  fetched_files
@@ -102,9 +99,16 @@ module Dependabot
102
99
  project_files
103
100
  end
104
101
  rescue Octokit::NotFound, Gitlab::Error::NotFound
102
+ raise_dependency_file_not_found
103
+ end
104
+
105
+ sig { returns(T.noreturn) }
106
+ def raise_dependency_file_not_found
105
107
  raise(
106
- Dependabot::DependencyFileNotFound,
107
- File.join(directory, "<anything>.(cs|vb|fs)proj")
108
+ Dependabot::DependencyFileNotFound.new(
109
+ File.join(directory, "*.(sln|csproj|vbproj|fsproj|proj)"),
110
+ "Unable to find `*.sln`, `*.(cs|vb|fs)proj`, or `*.proj` in directory `#{directory}`"
111
+ )
108
112
  )
109
113
  end
110
114
 
@@ -44,6 +44,16 @@ module Dependabot
44
44
  Dependabot.logger.warn "Dependency '#{d.name}' excluded due to unparsable version: #{d.version}"
45
45
  end
46
46
 
47
+ dependency_info = dependencies.map do |d|
48
+ requirements_info = d.requirements.filter_map { |r| " file: #{r[:file]}, metadata: #{r[:metadata]}" }
49
+ .join("\n")
50
+ " name: #{d.name}, version: #{d.version}\n#{requirements_info}"
51
+ end.join("\n")
52
+
53
+ if dependencies.length.positive?
54
+ Dependabot.logger.info "The following dependencies were found:\n#{dependency_info}"
55
+ end
56
+
47
57
  dependencies
48
58
  end
49
59
 
@@ -1,18 +1,25 @@
1
- # typed: true
1
+ # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
5
+
4
6
  module Dependabot
5
7
  module Nuget
6
8
  module NuGetConfigCredentialHelpers
9
+ extend T::Sig
10
+
11
+ sig { returns(String) }
7
12
  def self.user_nuget_config_path
8
13
  home_directory = Dir.home
9
14
  File.join(home_directory, ".nuget", "NuGet", "NuGet.Config")
10
15
  end
11
16
 
17
+ sig { returns(String) }
12
18
  def self.temporary_nuget_config_path
13
19
  user_nuget_config_path + "_ORIGINAL"
14
20
  end
15
21
 
22
+ sig { params(credentials: T::Array[Dependabot::Credential]).void }
16
23
  def self.add_credentials_to_nuget_config(credentials)
17
24
  return unless File.exist?(user_nuget_config_path)
18
25
 
@@ -48,6 +55,7 @@ module Dependabot
48
55
  File.write(user_nuget_config_path, nuget_config)
49
56
  end
50
57
 
58
+ sig { void }
51
59
  def self.restore_user_nuget_config
52
60
  return unless File.exist?(temporary_nuget_config_path)
53
61
 
@@ -55,6 +63,7 @@ module Dependabot
55
63
  File.rename(temporary_nuget_config_path, user_nuget_config_path)
56
64
  end
57
65
 
66
+ sig { params(credentials: T::Array[Dependabot::Credential], _block: T.proc.void).void }
58
67
  def self.patch_nuget_config_for_action(credentials, &_block)
59
68
  add_credentials_to_nuget_config(credentials)
60
69
  begin
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "sorbet-runtime"
@@ -12,6 +12,9 @@ require "dependabot/nuget/version"
12
12
  module Dependabot
13
13
  module Nuget
14
14
  class Requirement < Dependabot::Requirement
15
+ extend T::Sig
16
+
17
+ sig { override.params(obj: T.any(Gem::Version, String)).returns([String, Gem::Version]) }
15
18
  def self.parse(obj)
16
19
  return ["=", Nuget::Version.new(obj.to_s)] if obj.is_a?(Gem::Version)
17
20
 
@@ -28,11 +31,12 @@ module Dependabot
28
31
  # For consistency with other languages, we define a requirements array.
29
32
  # Dotnet doesn't have an `OR` separator for requirements, so it always
30
33
  # contains a single element.
31
- sig { override.params(requirement_string: T.nilable(String)).returns(T::Array[Requirement]) }
34
+ sig { override.params(requirement_string: T.nilable(String)).returns(T::Array[Dependabot::Requirement]) }
32
35
  def self.requirements_array(requirement_string)
33
36
  [new(requirement_string)]
34
37
  end
35
38
 
39
+ sig { params(requirements: T.any(T.nilable(String), T::Array[T.nilable(String)])).void }
36
40
  def initialize(*requirements)
37
41
  requirements = requirements.flatten.flat_map do |req_string|
38
42
  convert_dotnet_constraint_to_ruby_constraint(req_string)
@@ -41,6 +45,7 @@ module Dependabot
41
45
  super(requirements)
42
46
  end
43
47
 
48
+ sig { override.params(version: Gem::Version).returns(T::Boolean) }
44
49
  def satisfied_by?(version)
45
50
  version = Nuget::Version.new(version.to_s)
46
51
  super
@@ -48,10 +53,11 @@ module Dependabot
48
53
 
49
54
  private
50
55
 
56
+ sig { params(req_string: T.nilable(String)).returns(T.nilable(T.any(String, T::Array[String]))) }
51
57
  def convert_dotnet_constraint_to_ruby_constraint(req_string)
52
58
  return unless req_string
53
59
 
54
- return convert_dotnet_range_to_ruby_range(req_string) if req_string&.start_with?("(", "[")
60
+ return convert_dotnet_range_to_ruby_range(req_string) if req_string.start_with?("(", "[")
55
61
 
56
62
  return req_string.split(",").map(&:strip) if req_string.include?(",")
57
63
 
@@ -61,6 +67,7 @@ module Dependabot
61
67
  end
62
68
 
63
69
  # rubocop:disable Metrics/PerceivedComplexity
70
+ sig { params(req_string: String).returns(T::Array[String]) }
64
71
  def convert_dotnet_range_to_ruby_range(req_string)
65
72
  lower_b, upper_b = req_string.split(",").map(&:strip).map do |bound|
66
73
  next convert_range_wildcard_req(bound) if bound.include?("*")
@@ -70,9 +77,9 @@ module Dependabot
70
77
 
71
78
  lower_b =
72
79
  if ["(", "["].include?(lower_b) then nil
73
- elsif lower_b.start_with?("(") then "> #{lower_b.sub(/\(\s*/, '')}"
80
+ elsif T.must(lower_b).start_with?("(") then "> #{T.must(lower_b).sub(/\(\s*/, '')}"
74
81
  else
75
- ">= #{lower_b.sub(/\[\s*/, '').strip}"
82
+ ">= #{T.must(lower_b).sub(/\[\s*/, '').strip}"
76
83
  end
77
84
 
78
85
  upper_b =
@@ -87,20 +94,22 @@ module Dependabot
87
94
  end
88
95
  # rubocop:enable Metrics/PerceivedComplexity
89
96
 
97
+ sig { params(req_string: String).returns(String) }
90
98
  def convert_range_wildcard_req(req_string)
91
- range_end = req_string[-1]
92
- defined_part = req_string.split("*").first
99
+ range_end = T.must(req_string[-1])
100
+ defined_part = T.must(req_string.split("*").first)
93
101
  version = defined_part + "0"
94
102
  version += range_end if [")", "]"].include?(range_end)
95
103
  version
96
104
  end
97
105
 
106
+ sig { params(req_string: String).returns(String) }
98
107
  def convert_wildcard_req(req_string)
99
108
  return ">= 0-a" if req_string == "*-*"
100
109
 
101
110
  return ">= 0" if req_string.start_with?("*")
102
111
 
103
- defined_part = req_string.split("*").first
112
+ defined_part = T.must(req_string.split("*").first)
104
113
  suffix = defined_part.end_with?(".") ? "0" : "a"
105
114
  version = defined_part + suffix
106
115
  "~> #{version}"
@@ -1,23 +1,43 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "nokogiri"
5
- require "zip"
6
5
  require "stringio"
6
+ require "sorbet-runtime"
7
+ require "zip"
8
+
7
9
  require "dependabot/nuget/http_response_helpers"
8
10
 
9
11
  module Dependabot
10
12
  module Nuget
11
13
  class NupkgFetcher
14
+ extend T::Sig
15
+
12
16
  require_relative "repository_finder"
13
17
 
18
+ sig do
19
+ params(
20
+ dependency_urls: T::Array[T::Hash[Symbol, String]],
21
+ package_id: String,
22
+ package_version: String
23
+ )
24
+ .returns(T.nilable(String))
25
+ end
14
26
  def self.fetch_nupkg_buffer(dependency_urls, package_id, package_version)
15
27
  # check all repositories for the first one that has the nupkg
16
- dependency_urls.reduce(nil) do |nupkg_buffer, repository_details|
28
+ dependency_urls.reduce(T.let(nil, T.nilable(String))) do |nupkg_buffer, repository_details|
17
29
  nupkg_buffer || fetch_nupkg_buffer_from_repository(repository_details, package_id, package_version)
18
30
  end
19
31
  end
20
32
 
33
+ sig do
34
+ params(
35
+ repository_details: T::Hash[Symbol, T.untyped],
36
+ package_id: T.nilable(String),
37
+ package_version: T.nilable(String)
38
+ )
39
+ .returns(T.nilable(String))
40
+ end
21
41
  def self.fetch_nupkg_url_from_repository(repository_details, package_id, package_version)
22
42
  return unless package_id && package_version && !package_version.empty?
23
43
 
@@ -35,6 +55,14 @@ module Dependabot
35
55
  package_url
36
56
  end
37
57
 
58
+ sig do
59
+ params(
60
+ repository_details: T::Hash[Symbol, T.untyped],
61
+ package_id: String,
62
+ package_version: String
63
+ )
64
+ .returns(T.nilable(String))
65
+ end
38
66
  def self.fetch_nupkg_buffer_from_repository(repository_details, package_id, package_version)
39
67
  package_url = fetch_nupkg_url_from_repository(repository_details, package_id, package_version)
40
68
  return unless package_url
@@ -43,6 +71,14 @@ module Dependabot
43
71
  fetch_stream(package_url, auth_header)
44
72
  end
45
73
 
74
+ sig do
75
+ params(
76
+ repository_details: T::Hash[Symbol, T.untyped],
77
+ package_id: String,
78
+ package_version: String
79
+ )
80
+ .returns(T.nilable(String))
81
+ end
46
82
  def self.get_nuget_v3_package_url(repository_details, package_id, package_version)
47
83
  base_url = repository_details[:base_url]
48
84
  unless base_url
@@ -57,15 +93,23 @@ module Dependabot
57
93
 
58
94
  # rubocop:disable Metrics/CyclomaticComplexity
59
95
  # rubocop:disable Metrics/PerceivedComplexity
96
+ sig do
97
+ params(
98
+ repository_details: T::Hash[Symbol, T.untyped],
99
+ package_id: String,
100
+ package_version: String
101
+ )
102
+ .returns(T.nilable(String))
103
+ end
60
104
  def self.get_nuget_v3_package_url_from_search(repository_details, package_id, package_version)
61
105
  search_url = repository_details[:search_url]
62
106
  return nil unless search_url
63
107
 
64
108
  # get search result
65
109
  search_result_response = fetch_url(search_url, repository_details)
66
- return nil unless search_result_response.status == 200
110
+ return nil unless search_result_response&.status == 200
67
111
 
68
- search_response_body = HttpResponseHelpers.remove_wrapping_zero_width_chars(search_result_response.body)
112
+ search_response_body = HttpResponseHelpers.remove_wrapping_zero_width_chars(T.must(search_result_response).body)
69
113
  search_results = JSON.parse(search_response_body)
70
114
 
71
115
  # find matching package and version
@@ -90,15 +134,23 @@ module Dependabot
90
134
  # rubocop:enable Metrics/PerceivedComplexity
91
135
  # rubocop:enable Metrics/CyclomaticComplexity
92
136
 
137
+ sig do
138
+ params(
139
+ repository_details: T::Hash[Symbol, T.untyped],
140
+ package_id: String,
141
+ package_version: String
142
+ )
143
+ .returns(T.nilable(String))
144
+ end
93
145
  def self.get_nuget_v2_package_url(repository_details, package_id, package_version)
94
146
  # get package XML
95
147
  base_url = repository_details[:base_url].delete_suffix("/")
96
148
  package_url = "#{base_url}/Packages(Id='#{package_id}',Version='#{package_version}')"
97
149
  response = fetch_url(package_url, repository_details)
98
- return nil unless response.status == 200
150
+ return nil unless response&.status == 200
99
151
 
100
152
  # find relevant element
101
- doc = Nokogiri::XML(response.body)
153
+ doc = Nokogiri::XML(T.must(response).body)
102
154
  doc.remove_namespaces!
103
155
 
104
156
  content_element = doc.xpath("/entry/content")
@@ -106,6 +158,14 @@ module Dependabot
106
158
  nupkg_url
107
159
  end
108
160
 
161
+ sig do
162
+ params(
163
+ stream_url: String,
164
+ auth_header: T::Hash[String, String],
165
+ max_redirects: Integer
166
+ )
167
+ .returns(T.nilable(String))
168
+ end
109
169
  def self.fetch_stream(stream_url, auth_header, max_redirects = 5)
110
170
  current_url = stream_url
111
171
  current_redirects = 0
@@ -128,17 +188,25 @@ module Dependabot
128
188
  current_redirects += 1
129
189
  return nil if current_redirects > max_redirects
130
190
 
131
- current_url = response.headers["Location"]
191
+ current_url = T.must(response.headers["Location"])
132
192
  else
133
193
  return nil
134
194
  end
135
195
  end
136
196
  end
137
197
 
198
+ sig do
199
+ params(
200
+ url: String,
201
+ repository_details: T::Hash[Symbol, T.untyped]
202
+ )
203
+ .returns(T.nilable(Excon::Response))
204
+ end
138
205
  def self.fetch_url(url, repository_details)
139
206
  fetch_url_with_auth(url, repository_details.fetch(:auth_header))
140
207
  end
141
208
 
209
+ sig { params(url: String, auth_header: T::Hash[T.any(String, Symbol), T.untyped]).returns(Excon::Response) }
142
210
  def self.fetch_url_with_auth(url, auth_header)
143
211
  cache = CacheManager.cache("nupkg_fetcher_cache")
144
212
  cache[url] ||= Dependabot::RegistryClient.get(
@@ -1,23 +1,42 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "nokogiri"
5
- require "zip"
6
5
  require "stringio"
6
+ require "sorbet-runtime"
7
+ require "zip"
7
8
 
8
9
  module Dependabot
9
10
  module Nuget
10
11
  class NuspecFetcher
12
+ extend T::Sig
13
+
11
14
  require_relative "nupkg_fetcher"
12
15
  require_relative "repository_finder"
13
16
 
17
+ sig do
18
+ params(
19
+ dependency_urls: T::Array[T::Hash[Symbol, String]],
20
+ package_id: String,
21
+ package_version: String
22
+ )
23
+ .returns(T.nilable(Nokogiri::XML::Document))
24
+ end
14
25
  def self.fetch_nuspec(dependency_urls, package_id, package_version)
15
26
  # check all repositories for the first one that has the nuspec
16
- dependency_urls.reduce(nil) do |nuspec_xml, repository_details|
27
+ dependency_urls.reduce(T.let(nil, T.nilable(Nokogiri::XML::Document))) do |nuspec_xml, repository_details|
17
28
  nuspec_xml || fetch_nuspec_from_repository(repository_details, package_id, package_version)
18
29
  end
19
30
  end
20
31
 
32
+ sig do
33
+ params(
34
+ repository_details: T::Hash[Symbol, T.untyped],
35
+ package_id: T.nilable(String),
36
+ package_version: T.nilable(String)
37
+ )
38
+ .returns(T.nilable(Nokogiri::XML::Document))
39
+ end
21
40
  def self.fetch_nuspec_from_repository(repository_details, package_id, package_version)
22
41
  return unless package_id && package_version && !package_version.empty?
23
42
 
@@ -55,6 +74,7 @@ module Dependabot
55
74
  nuspec_xml
56
75
  end
57
76
 
77
+ sig { params(feed_url: String).returns(T::Boolean) }
58
78
  def self.feed_supports_nuspec_download?(feed_url)
59
79
  feed_regexs = [
60
80
  # nuget
@@ -67,6 +87,7 @@ module Dependabot
67
87
  feed_regexs.any? { |reg| reg.match(feed_url) }
68
88
  end
69
89
 
90
+ sig { params(zip_stream: String, package_id: String).returns(T.nilable(String)) }
70
91
  def self.extract_nuspec(zip_stream, package_id)
71
92
  Zip::File.open_buffer(zip_stream) do |zip|
72
93
  nuspec_entry = zip.find { |entry| entry.name == "#{package_id}.nuspec" }
@@ -75,6 +96,7 @@ module Dependabot
75
96
  nil
76
97
  end
77
98
 
99
+ sig { params(string: String).returns(String) }
78
100
  def self.remove_invalid_characters(string)
79
101
  string.dup
80
102
  .force_encoding(Encoding::UTF_8)
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  #######################################################################
@@ -6,6 +6,8 @@
6
6
  # https://docs.microsoft.com/en-us/nuget/reference/package-versioning #
7
7
  #######################################################################
8
8
 
9
+ require "sorbet-runtime"
10
+
9
11
  require "dependabot/update_checkers/base"
10
12
  require "dependabot/nuget/version"
11
13
 
@@ -13,14 +15,25 @@ module Dependabot
13
15
  module Nuget
14
16
  class UpdateChecker < Dependabot::UpdateCheckers::Base
15
17
  class RequirementsUpdater
18
+ extend T::Sig
19
+
20
+ sig do
21
+ params(
22
+ requirements: T::Array[T::Hash[Symbol, T.untyped]],
23
+ latest_version: T.nilable(T.any(String, Dependabot::Nuget::Version)),
24
+ source_details: T.nilable(T::Hash[Symbol, T.untyped])
25
+ )
26
+ .void
27
+ end
16
28
  def initialize(requirements:, latest_version:, source_details:)
17
29
  @requirements = requirements
18
30
  @source_details = source_details
19
31
  return unless latest_version
20
32
 
21
- @latest_version = version_class.new(latest_version)
33
+ @latest_version = T.let(version_class.new(latest_version), Dependabot::Nuget::Version)
22
34
  end
23
35
 
36
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
24
37
  def updated_requirements
25
38
  return requirements unless latest_version
26
39
 
@@ -52,32 +65,42 @@ module Dependabot
52
65
 
53
66
  private
54
67
 
55
- attr_reader :requirements, :latest_version, :source_details
68
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
69
+ attr_reader :requirements
70
+
71
+ sig { returns(T.nilable(Dependabot::Nuget::Version)) }
72
+ attr_reader :latest_version
73
+
74
+ sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
75
+ attr_reader :source_details
56
76
 
77
+ sig { returns(T.class_of(Dependabot::Nuget::Version)) }
57
78
  def version_class
58
- Nuget::Version
79
+ Dependabot::Nuget::Version
59
80
  end
60
81
 
82
+ sig { params(req_string: String).returns(String) }
61
83
  def update_wildcard_requirement(req_string)
62
84
  return req_string if req_string == "*-*"
63
85
 
64
86
  return req_string if req_string == "*"
65
87
 
66
- precision = req_string.split("*").first.split(/\.|\-/).count
88
+ precision = T.must(req_string.split("*").first).split(/\.|\-/).count
67
89
  wildcard_section = req_string.partition(/(?=[.\-]\*)/).last
68
90
 
69
- version_parts = latest_version.segments.first(precision)
91
+ version_parts = T.must(latest_version).segments.first(precision)
70
92
  version = version_parts.join(".")
71
93
 
72
94
  version + wildcard_section
73
95
  end
74
96
 
97
+ sig { returns(T::Hash[Symbol, T.untyped]) }
75
98
  def updated_source
76
99
  {
77
100
  type: "nuget_repo",
78
- url: source_details.fetch(:repo_url),
79
- nuspec_url: source_details.fetch(:nuspec_url),
80
- source_url: source_details.fetch(:source_url)
101
+ url: source_details&.fetch(:repo_url),
102
+ nuspec_url: source_details&.fetch(:nuspec_url),
103
+ source_url: source_details&.fetch(:source_url)
81
104
  }
82
105
  end
83
106
  end
@@ -1,16 +1,18 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
5
+
4
6
  require "dependabot/nuget/version"
5
7
  require "dependabot/nuget/requirement"
6
8
  require "dependabot/update_checkers/base"
7
9
  require "dependabot/update_checkers/version_filters"
8
10
  require "dependabot/nuget/nuget_client"
9
- require "sorbet-runtime"
10
11
 
11
12
  module Dependabot
12
13
  module Nuget
13
14
  class UpdateChecker < Dependabot::UpdateCheckers::Base
15
+ # rubocop:disable Metrics/ClassLength
14
16
  class VersionFinder
15
17
  extend T::Sig
16
18
 
@@ -19,10 +21,24 @@ module Dependabot
19
21
 
20
22
  NUGET_RANGE_REGEX = /[\(\[].*,.*[\)\]]/
21
23
 
22
- def initialize(dependency:, dependency_files:, credentials:,
23
- ignored_versions:, raise_on_ignored: false,
24
+ sig do
25
+ params(
26
+ dependency: Dependabot::Dependency,
27
+ dependency_files: T::Array[Dependabot::DependencyFile],
28
+ credentials: T::Array[Dependabot::Credential],
29
+ ignored_versions: T::Array[String],
30
+ security_advisories: T::Array[Dependabot::SecurityAdvisory],
31
+ repo_contents_path: T.nilable(String),
32
+ raise_on_ignored: T::Boolean
33
+ ).void
34
+ end
35
+ def initialize(dependency:,
36
+ dependency_files:,
37
+ credentials:,
38
+ ignored_versions:,
24
39
  security_advisories:,
25
- repo_contents_path:)
40
+ repo_contents_path:,
41
+ raise_on_ignored: false)
26
42
  @dependency = dependency
27
43
  @dependency_files = dependency_files
28
44
  @credentials = credentials
@@ -32,53 +48,89 @@ module Dependabot
32
48
  @repo_contents_path = repo_contents_path
33
49
  end
34
50
 
51
+ sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
35
52
  def latest_version_details
36
53
  @latest_version_details ||=
37
- begin
38
- possible_versions = versions
39
- possible_versions = filter_prereleases(possible_versions)
40
- possible_versions = filter_ignored_versions(possible_versions)
41
-
42
- find_highest_compatible_version(possible_versions)
43
- end
54
+ T.let(
55
+ begin
56
+ possible_versions = versions
57
+ possible_versions = filter_prereleases(possible_versions)
58
+ possible_versions = filter_ignored_versions(possible_versions)
59
+
60
+ find_highest_compatible_version(possible_versions)
61
+ end,
62
+ T.nilable(T::Hash[Symbol, T.untyped])
63
+ )
44
64
  end
45
65
 
66
+ sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
46
67
  def lowest_security_fix_version_details
47
68
  @lowest_security_fix_version_details ||=
48
- begin
49
- possible_versions = versions
50
- possible_versions = filter_prereleases(possible_versions)
51
- possible_versions = Dependabot::UpdateCheckers::VersionFilters.filter_vulnerable_versions(
52
- possible_versions, security_advisories
53
- )
54
- possible_versions = filter_ignored_versions(possible_versions)
55
- possible_versions = filter_lower_versions(possible_versions)
56
-
57
- find_lowest_compatible_version(possible_versions)
58
- end
69
+ T.let(
70
+ begin
71
+ possible_versions = versions
72
+ possible_versions = filter_prereleases(possible_versions)
73
+ possible_versions = Dependabot::UpdateCheckers::VersionFilters.filter_vulnerable_versions(
74
+ possible_versions, security_advisories
75
+ )
76
+ possible_versions = filter_ignored_versions(possible_versions)
77
+ possible_versions = filter_lower_versions(possible_versions)
78
+
79
+ find_lowest_compatible_version(possible_versions)
80
+ end,
81
+ T.nilable(T::Hash[Symbol, T.untyped])
82
+ )
59
83
  end
60
84
 
85
+ sig { returns(T::Array[T::Hash[Symbol, T.nilable(T.any(Dependabot::Version, String))]]) }
61
86
  def versions
62
87
  available_v3_versions + available_v2_versions
63
88
  end
64
89
 
65
- attr_reader :dependency, :dependency_files, :credentials,
66
- :ignored_versions, :security_advisories, :repo_contents_path
90
+ sig { returns(Dependabot::Dependency) }
91
+ attr_reader :dependency
92
+
93
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
94
+ attr_reader :dependency_files
95
+
96
+ sig { returns(T::Array[Dependabot::Credential]) }
97
+ attr_reader :credentials
98
+
99
+ sig { returns(T::Array[String]) }
100
+ attr_reader :ignored_versions
101
+
102
+ sig { returns(T::Array[Dependabot::SecurityAdvisory]) }
103
+ attr_reader :security_advisories
104
+
105
+ sig { returns(T.nilable(String)) }
106
+ attr_reader :repo_contents_path
67
107
 
68
108
  private
69
109
 
110
+ sig do
111
+ params(possible_versions: T::Array[T::Hash[Symbol, T.untyped]])
112
+ .returns(T.nilable(T::Hash[Symbol, T.untyped]))
113
+ end
70
114
  def find_highest_compatible_version(possible_versions)
71
115
  # sorted versions descending
72
116
  sorted_versions = possible_versions.sort_by { |v| v.fetch(:version) }.reverse
73
117
  find_compatible_version(sorted_versions)
74
118
  end
75
119
 
120
+ sig do
121
+ params(possible_versions: T::Array[T::Hash[Symbol, T.untyped]])
122
+ .returns(T.nilable(T::Hash[Symbol, T.untyped]))
123
+ end
76
124
  def find_lowest_compatible_version(possible_versions)
77
125
  # sorted versions ascending
78
126
  sorted_versions = possible_versions.sort_by { |v| v.fetch(:version) }
79
127
  find_compatible_version(sorted_versions)
80
128
  end
81
129
 
130
+ sig do
131
+ params(sorted_versions: T::Array[T::Hash[Symbol, T.untyped]])
132
+ .returns(T.nilable(T::Hash[Symbol, T.untyped]))
133
+ end
82
134
  def find_compatible_version(sorted_versions)
83
135
  # By checking the first version separately, we can avoid additional network requests
84
136
  first_version = sorted_versions.first
@@ -92,27 +144,37 @@ module Dependabot
92
144
  sorted_versions.find { |v| version_compatible?(v.fetch(:version)) }
93
145
  end
94
146
 
147
+ sig { params(version: T.nilable(T.any(Dependabot::Version, String))).returns(T::Boolean) }
95
148
  def version_compatible?(version)
96
149
  str_version_compatible?(version.to_s)
97
150
  end
98
151
 
152
+ sig { params(version: String).returns(T::Boolean) }
99
153
  def str_version_compatible?(version)
100
154
  compatibility_checker.compatible?(version)
101
155
  end
102
156
 
157
+ sig { returns(Dependabot::Nuget::CompatibilityChecker) }
103
158
  def compatibility_checker
104
- @compatibility_checker ||= CompatibilityChecker.new(
105
- dependency_urls: dependency_urls,
106
- dependency: dependency,
107
- tfm_finder: TfmFinder.new(
108
- dependency_files: dependency_files,
109
- credentials: credentials,
110
- repo_contents_path: repo_contents_path
159
+ @compatibility_checker ||=
160
+ T.let(
161
+ CompatibilityChecker.new(
162
+ dependency_urls: dependency_urls,
163
+ dependency: dependency,
164
+ tfm_finder: TfmFinder.new(
165
+ dependency_files: dependency_files,
166
+ credentials: credentials,
167
+ repo_contents_path: repo_contents_path
168
+ )
169
+ ),
170
+ T.nilable(Dependabot::Nuget::CompatibilityChecker)
111
171
  )
112
- )
113
172
  end
114
173
 
115
- sig { params(possible_versions: T::Array[T.untyped]).returns(T::Array[T.untyped]) }
174
+ sig do
175
+ params(possible_versions: T::Array[T::Hash[Symbol, T.untyped]])
176
+ .returns(T::Array[T::Hash[Symbol, T.untyped]])
177
+ end
116
178
  def filter_prereleases(possible_versions)
117
179
  filtered = possible_versions.reject do |d|
118
180
  version = d.fetch(:version)
@@ -124,7 +186,10 @@ module Dependabot
124
186
  filtered
125
187
  end
126
188
 
127
- sig { params(possible_versions: T::Array[T.untyped]).returns(T::Array[T.untyped]) }
189
+ sig do
190
+ params(possible_versions: T::Array[T::Hash[Symbol, T.untyped]])
191
+ .returns(T::Array[T::Hash[Symbol, T.untyped]])
192
+ end
128
193
  def filter_ignored_versions(possible_versions)
129
194
  filtered = possible_versions
130
195
 
@@ -147,6 +212,10 @@ module Dependabot
147
212
  filtered
148
213
  end
149
214
 
215
+ sig do
216
+ params(possible_versions: T::Array[T::Hash[Symbol, T.untyped]])
217
+ .returns(T::Array[T::Hash[Symbol, T.untyped]])
218
+ end
150
219
  def filter_lower_versions(possible_versions)
151
220
  return possible_versions unless dependency.numeric_version
152
221
 
@@ -155,12 +224,14 @@ module Dependabot
155
224
  end
156
225
  end
157
226
 
227
+ sig { params(string: String).returns(T::Array[String]) }
158
228
  def parse_requirement_string(string)
159
229
  return [string] if string.match?(NUGET_RANGE_REGEX)
160
230
 
161
231
  string.split(",").map(&:strip)
162
232
  end
163
233
 
234
+ sig { returns(T::Array[T::Hash[Symbol, T.any(Dependabot::Version, String, NilClass)]]) }
164
235
  def available_v3_versions
165
236
  v3_nuget_listings.flat_map do |listing|
166
237
  listing
@@ -181,6 +252,7 @@ module Dependabot
181
252
  end
182
253
  end
183
254
 
255
+ sig { returns(T::Array[T::Hash[Symbol, T.any(Dependabot::Version, String, NilClass)]]) }
184
256
  def available_v2_versions
185
257
  v2_nuget_listings.flat_map do |listing|
186
258
  body = listing.fetch("xml_body", [])
@@ -200,6 +272,10 @@ module Dependabot
200
272
  end
201
273
  end
202
274
 
275
+ sig do
276
+ params(entry: Nokogiri::XML::Element)
277
+ .returns(T::Hash[Symbol, T.any(Dependabot::Version, String, NilClass)])
278
+ end
203
279
  def dependency_details_from_v2_entry(entry)
204
280
  version = entry.at_xpath("./properties/Version").content.strip
205
281
  source_urls = []
@@ -221,10 +297,11 @@ module Dependabot
221
297
  end
222
298
 
223
299
  # rubocop:disable Metrics/PerceivedComplexity
300
+ sig { params(version: Dependabot::Version).returns(T::Boolean) }
224
301
  def related_to_current_pre?(version)
225
302
  current_version = dependency.numeric_version
226
303
  if current_version&.prerelease? &&
227
- current_version&.release == version.release
304
+ current_version.release == version.release
228
305
  return true
229
306
  end
230
307
 
@@ -242,36 +319,50 @@ module Dependabot
242
319
  false
243
320
  end
244
321
  end
245
-
246
322
  # rubocop:enable Metrics/PerceivedComplexity
247
323
 
324
+ sig { returns(T::Array[T::Hash[String, T.untyped]]) }
248
325
  def v3_nuget_listings
249
326
  @v3_nuget_listings ||=
250
- dependency_urls
251
- .select { |details| details.fetch(:repository_type) == "v3" }
252
- .filter_map do |url_details|
253
- versions = NugetClient.get_package_versions(dependency.name, url_details)
254
- next unless versions
255
-
256
- { "versions" => versions, "listing_details" => url_details }
257
- end
327
+ T.let(
328
+ dependency_urls
329
+ .select { |details| details.fetch(:repository_type) == "v3" }
330
+ .filter_map do |url_details|
331
+ versions = NugetClient.get_package_versions(dependency.name, url_details)
332
+ next unless versions
333
+
334
+ { "versions" => versions, "listing_details" => url_details }
335
+ end,
336
+ T.nilable(T::Array[T::Hash[String, T.untyped]])
337
+ )
258
338
  end
259
339
 
340
+ sig { returns(T::Array[T::Hash[String, T.untyped]]) }
260
341
  def v2_nuget_listings
261
342
  @v2_nuget_listings ||=
262
- dependency_urls
263
- .select { |details| details.fetch(:repository_type) == "v2" }
264
- .flat_map { |url_details| fetch_paginated_v2_nuget_listings(url_details) }
265
- .filter_map do |url_details, response|
266
- next unless response.status == 200
267
-
268
- {
269
- "xml_body" => response.body,
270
- "listing_details" => url_details
271
- }
272
- end
343
+ T.let(
344
+ dependency_urls
345
+ .select { |details| details.fetch(:repository_type) == "v2" }
346
+ .flat_map { |url_details| fetch_paginated_v2_nuget_listings(url_details) }
347
+ .filter_map do |url_details, response|
348
+ next unless response.status == 200
349
+
350
+ {
351
+ "xml_body" => response.body,
352
+ "listing_details" => url_details
353
+ }
354
+ end,
355
+ T.nilable(T::Array[T::Hash[String, T.untyped]])
356
+ )
273
357
  end
274
358
 
359
+ sig do
360
+ params(
361
+ url_details: T::Hash[Symbol, T.untyped],
362
+ results: T::Hash[T::Hash[Symbol, T.untyped], Excon::Response]
363
+ )
364
+ .returns(T::Array[T::Array[T.untyped]])
365
+ end
275
366
  def fetch_paginated_v2_nuget_listings(url_details, results = {})
276
367
  response = Dependabot::RegistryClient.get(
277
368
  url: url_details[:versions_url],
@@ -295,6 +386,7 @@ module Dependabot
295
386
  results.to_a
296
387
  end
297
388
 
389
+ sig { params(xml_body: String).returns(T.nilable(String)) }
298
390
  def fetch_v2_next_link_href(xml_body)
299
391
  doc = Nokogiri::XML(xml_body)
300
392
  doc.remove_namespaces!
@@ -307,32 +399,44 @@ module Dependabot
307
399
  nil
308
400
  end
309
401
 
402
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
310
403
  def dependency_urls
311
404
  @dependency_urls ||=
312
- RepositoryFinder.new(
313
- dependency: dependency,
314
- credentials: credentials,
315
- config_files: nuget_configs
316
- ).dependency_urls
405
+ T.let(
406
+ RepositoryFinder.new(
407
+ dependency: dependency,
408
+ credentials: credentials,
409
+ config_files: nuget_configs
410
+ ).dependency_urls,
411
+ T.nilable(T::Array[T::Hash[Symbol, T.untyped]])
412
+ )
317
413
  end
318
414
 
415
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
319
416
  def nuget_configs
320
417
  @nuget_configs ||=
321
- dependency_files.select { |f| f.name.match?(/nuget\.config$/i) }
418
+ T.let(
419
+ dependency_files.select { |f| f.name.match?(/nuget\.config$/i) },
420
+ T.nilable(T::Array[Dependabot::DependencyFile])
421
+ )
322
422
  end
323
423
 
424
+ sig { returns(String) }
324
425
  def sanitized_name
325
426
  dependency.name.downcase
326
427
  end
327
428
 
429
+ sig { returns(T.class_of(Gem::Version)) }
328
430
  def version_class
329
431
  dependency.version_class
330
432
  end
331
433
 
434
+ sig { returns(T.class_of(Dependabot::Requirement)) }
332
435
  def requirement_class
333
436
  dependency.requirement_class
334
437
  end
335
438
 
439
+ sig { returns(T::Hash[Symbol, Integer]) }
336
440
  def excon_options
337
441
  # For large JSON files we sometimes need a little longer than for
338
442
  # other languages. For example, see:
@@ -345,6 +449,7 @@ module Dependabot
345
449
  }
346
450
  end
347
451
  end
452
+ # rubocop:enable Metrics/ClassLength
348
453
  end
349
454
  end
350
455
  end
@@ -1,47 +1,59 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/nuget/file_parser"
5
5
  require "dependabot/update_checkers"
6
6
  require "dependabot/update_checkers/base"
7
+ require "sorbet-runtime"
7
8
 
8
9
  module Dependabot
9
10
  module Nuget
10
11
  class UpdateChecker < Dependabot::UpdateCheckers::Base
12
+ extend T::Sig
13
+
11
14
  require_relative "update_checker/version_finder"
12
15
  require_relative "update_checker/property_updater"
13
16
  require_relative "update_checker/requirements_updater"
14
17
  require_relative "update_checker/dependency_finder"
15
18
 
19
+ sig { override.returns(T.nilable(String)) }
16
20
  def latest_version
17
21
  # No need to find latest version for transitive dependencies unless they have a vulnerability.
18
22
  return dependency.version if !dependency.top_level? && !vulnerable?
19
23
 
20
24
  # if no update sources have the requisite package, then we can only assume that the current version is correct
21
- @latest_version = latest_version_details&.fetch(:version) || dependency.version
25
+ @latest_version = T.let(
26
+ latest_version_details&.fetch(:version)&.to_s || dependency.version,
27
+ T.nilable(String)
28
+ )
22
29
  end
23
30
 
31
+ sig { override.returns(T.nilable(T.any(String, Gem::Version))) }
24
32
  def latest_resolvable_version
25
33
  # We always want a full unlock since any package update could update peer dependencies as well.
26
34
  # To force a full unlock instead of an own unlock, we return nil.
27
35
  nil
28
36
  end
29
37
 
38
+ sig { override.returns(Dependabot::Nuget::Version) }
30
39
  def lowest_security_fix_version
31
40
  lowest_security_fix_version_details&.fetch(:version)
32
41
  end
33
42
 
43
+ sig { override.returns(T.nilable(Dependabot::Version)) }
34
44
  def lowest_resolvable_security_fix_version
35
45
  return nil if version_comes_from_multi_dependency_property?
36
46
 
37
47
  lowest_security_fix_version
38
48
  end
39
49
 
50
+ sig { override.returns(NilClass) }
40
51
  def latest_resolvable_version_with_no_unlock
41
52
  # Irrelevant, since Nuget has a single dependency file
42
53
  nil
43
54
  end
44
55
 
56
+ sig { override.returns(T::Array[T::Hash[Symbol, T.untyped]]) }
45
57
  def updated_requirements
46
58
  RequirementsUpdater.new(
47
59
  requirements: dependency.requirements,
@@ -50,6 +62,7 @@ module Dependabot
50
62
  ).updated_requirements
51
63
  end
52
64
 
65
+ sig { returns(T::Boolean) }
53
66
  def up_to_date?
54
67
  # No need to update transitive dependencies unless they have a vulnerability.
55
68
  return true if !dependency.top_level? && !vulnerable?
@@ -62,6 +75,7 @@ module Dependabot
62
75
  super
63
76
  end
64
77
 
78
+ sig { returns(T::Boolean) }
65
79
  def requirements_unlocked_or_can_be?
66
80
  # If any requirements have an uninterpolated property in them then
67
81
  # that property couldn't be found, and the requirement therefore
@@ -73,6 +87,7 @@ module Dependabot
73
87
 
74
88
  private
75
89
 
90
+ sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
76
91
  def preferred_resolvable_version_details
77
92
  # If this dependency is vulnerable, prefer trying to update to the
78
93
  # lowest_resolvable_security_fix_version. Otherwise update all the way
@@ -82,6 +97,7 @@ module Dependabot
82
97
  latest_version_details
83
98
  end
84
99
 
100
+ sig { override.returns(T::Boolean) }
85
101
  def latest_version_resolvable_with_full_unlock?
86
102
  # We always want a full unlock since any package update could update peer dependencies as well.
87
103
  return true unless version_comes_from_multi_dependency_property?
@@ -89,6 +105,7 @@ module Dependabot
89
105
  property_updater.update_possible?
90
106
  end
91
107
 
108
+ sig { override.returns(T::Array[Dependabot::Dependency]) }
92
109
  def updated_dependencies_after_full_unlock
93
110
  return property_updater.updated_dependencies if version_comes_from_multi_dependency_property?
94
111
 
@@ -96,7 +113,7 @@ module Dependabot
96
113
 
97
114
  updated_dependency = Dependency.new(
98
115
  name: dependency.name,
99
- version: latest_version&.to_s,
116
+ version: latest_version,
100
117
  requirements: updated_requirements,
101
118
  previous_version: dependency.version,
102
119
  previous_requirements: dependency.requirements,
@@ -112,47 +129,66 @@ module Dependabot
112
129
  updated_dependencies
113
130
  end
114
131
 
132
+ sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
115
133
  def preferred_version_details
116
134
  return lowest_security_fix_version_details if vulnerable?
117
135
 
118
136
  latest_version_details
119
137
  end
120
138
 
139
+ sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
121
140
  def latest_version_details
122
- @latest_version_details ||= version_finder.latest_version_details
141
+ @latest_version_details ||=
142
+ T.let(
143
+ version_finder.latest_version_details,
144
+ T.nilable(T::Hash[Symbol, T.untyped])
145
+ )
123
146
  end
124
147
 
148
+ sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
125
149
  def lowest_security_fix_version_details
126
150
  @lowest_security_fix_version_details ||=
127
- version_finder.lowest_security_fix_version_details
151
+ T.let(
152
+ version_finder.lowest_security_fix_version_details,
153
+ T.nilable(T::Hash[Symbol, T.untyped])
154
+ )
128
155
  end
129
156
 
157
+ sig { returns(Dependabot::Nuget::UpdateChecker::VersionFinder) }
130
158
  def version_finder
131
159
  @version_finder ||=
132
- VersionFinder.new(
133
- dependency: dependency,
134
- dependency_files: dependency_files,
135
- credentials: credentials,
136
- ignored_versions: ignored_versions,
137
- raise_on_ignored: @raise_on_ignored,
138
- security_advisories: security_advisories,
139
- repo_contents_path: @repo_contents_path
160
+ T.let(
161
+ VersionFinder.new(
162
+ dependency: dependency,
163
+ dependency_files: dependency_files,
164
+ credentials: credentials,
165
+ ignored_versions: ignored_versions,
166
+ raise_on_ignored: @raise_on_ignored,
167
+ security_advisories: security_advisories,
168
+ repo_contents_path: @repo_contents_path
169
+ ),
170
+ T.nilable(Dependabot::Nuget::UpdateChecker::VersionFinder)
140
171
  )
141
172
  end
142
173
 
174
+ sig { returns(Dependabot::Nuget::UpdateChecker::PropertyUpdater) }
143
175
  def property_updater
144
176
  @property_updater ||=
145
- PropertyUpdater.new(
146
- dependency: dependency,
147
- dependency_files: dependency_files,
148
- target_version_details: latest_version_details,
149
- credentials: credentials,
150
- ignored_versions: ignored_versions,
151
- raise_on_ignored: @raise_on_ignored,
152
- repo_contents_path: @repo_contents_path
177
+ T.let(
178
+ PropertyUpdater.new(
179
+ dependency: dependency,
180
+ dependency_files: dependency_files,
181
+ target_version_details: latest_version_details,
182
+ credentials: credentials,
183
+ ignored_versions: ignored_versions,
184
+ raise_on_ignored: @raise_on_ignored,
185
+ repo_contents_path: @repo_contents_path
186
+ ),
187
+ T.nilable(Dependabot::Nuget::UpdateChecker::PropertyUpdater)
153
188
  )
154
189
  end
155
190
 
191
+ sig { returns(T::Boolean) }
156
192
  def version_comes_from_multi_dependency_property?
157
193
  declarations_using_a_property.any? do |requirement|
158
194
  property_name = requirement.fetch(:metadata).fetch(:property_name)
@@ -167,20 +203,28 @@ module Dependabot
167
203
  end
168
204
  end
169
205
 
206
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
170
207
  def declarations_using_a_property
171
208
  @declarations_using_a_property ||=
172
- dependency.requirements
173
- .select { |req| req.dig(:metadata, :property_name) }
209
+ T.let(
210
+ dependency.requirements
211
+ .select { |req| req.dig(:metadata, :property_name) },
212
+ T.nilable(T::Array[T::Hash[Symbol, T.untyped]])
213
+ )
174
214
  end
175
215
 
216
+ sig { returns(T::Array[Dependabot::Dependency]) }
176
217
  def all_property_based_dependencies
177
218
  @all_property_based_dependencies ||=
178
- Nuget::FileParser.new(
179
- dependency_files: dependency_files,
180
- source: nil
181
- ).parse.select do |dep|
182
- dep.requirements.any? { |req| req.dig(:metadata, :property_name) }
183
- end
219
+ T.let(
220
+ Nuget::FileParser.new(
221
+ dependency_files: dependency_files,
222
+ source: nil
223
+ ).parse.select do |dep|
224
+ dep.requirements.any? { |req| req.dig(:metadata, :property_name) }
225
+ end,
226
+ T.nilable(T::Array[Dependabot::Dependency])
227
+ )
184
228
  end
185
229
  end
186
230
  end
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.247.0
4
+ version: 0.248.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-03-14 00:00:00.000000000 Z
11
+ date: 2024-03-21 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.247.0
19
+ version: 0.248.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.247.0
26
+ version: 0.248.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rubyzip
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -385,7 +385,7 @@ licenses:
385
385
  - Nonstandard
386
386
  metadata:
387
387
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
388
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.247.0
388
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.248.0
389
389
  post_install_message:
390
390
  rdoc_options: []
391
391
  require_paths: