dependabot-npm_and_yarn 0.308.0 → 0.310.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.
@@ -77,7 +77,7 @@ module Dependabot
77
77
  def latest_version_with_no_unlock(language_version: nil)
78
78
  with_custom_registry_rescue do
79
79
  return unless valid_npm_details?
80
- return version_from_dist_tags if specified_dist_tag_requirement?
80
+ return version_from_dist_tags&.version if specified_dist_tag_requirement?
81
81
 
82
82
  super
83
83
  end
@@ -100,8 +100,8 @@ module Dependabot
100
100
  with_custom_registry_rescue do
101
101
  return unless valid_npm_details?
102
102
 
103
- tag_version = version_from_dist_tags
104
- return tag_version if tag_version
103
+ tag_release = version_from_dist_tags
104
+ return tag_release.version if tag_release
105
105
 
106
106
  return if specified_dist_tag_requirement?
107
107
 
@@ -117,16 +117,20 @@ module Dependabot
117
117
  def fetch_latest_version_with_no_unlock(language_version: nil)
118
118
  with_custom_registry_rescue do
119
119
  return unless valid_npm_details?
120
- return version_from_dist_tags if specified_dist_tag_requirement?
120
+ return version_from_dist_tags&.version if specified_dist_tag_requirement?
121
121
 
122
122
  super
123
123
  end
124
124
  end
125
125
 
126
- sig { override.params(versions: T::Array[Dependabot::Version]).returns(T::Array[Dependabot::Version]) }
127
- def apply_post_fetch_latest_versions_filter(versions)
128
- original_count = versions.count
129
- filtered_versions = lazy_filter_yanked_versions_by_min_max(versions, check_max: true)
126
+ sig do
127
+ override
128
+ .params(releases: T::Array[Dependabot::Package::PackageRelease])
129
+ .returns(T::Array[Dependabot::Package::PackageRelease])
130
+ end
131
+ def apply_post_fetch_latest_versions_filter(releases)
132
+ original_count = releases.count
133
+ filtered_versions = lazy_filter_yanked_versions_by_min_max(releases, check_max: true)
130
134
 
131
135
  # Log the filter if any versions were removed
132
136
  if original_count > filtered_versions.count
@@ -141,26 +145,30 @@ module Dependabot
141
145
 
142
146
  sig do
143
147
  params(
144
- versions: T::Array[Dependabot::Version],
148
+ releases: T::Array[Dependabot::Package::PackageRelease],
145
149
  check_max: T::Boolean
146
- ).returns(T::Array[Dependabot::Version])
150
+ ).returns(T::Array[Dependabot::Package::PackageRelease])
147
151
  end
148
- def lazy_filter_yanked_versions_by_min_max(versions, check_max: true)
152
+ def lazy_filter_yanked_versions_by_min_max(releases, check_max: true)
149
153
  # Sort the versions based on the check_max flag (max -> descending, min -> ascending)
150
- sorted_versions = check_max ? versions.sort.reverse : versions.sort
154
+ sorted_releases = if check_max
155
+ releases.sort_by(&:version).reverse
156
+ else
157
+ releases.sort_by(&:version)
158
+ end
151
159
 
152
160
  filtered_versions = []
153
161
 
154
162
  not_yanked = T.let(false, T::Boolean)
155
163
 
156
164
  # Iterate through the sorted versions lazily, filtering out yanked versions
157
- sorted_versions.each do |version|
158
- next if !not_yanked && yanked_version?(version)
165
+ sorted_releases.each do |release|
166
+ next if !not_yanked && yanked_version?(release.version)
159
167
 
160
168
  not_yanked = true
161
169
 
162
170
  # Once we find a valid (non-yanked) version, add it to the filtered list
163
- filtered_versions << version
171
+ filtered_versions << release
164
172
  break
165
173
  end
166
174
 
@@ -172,7 +180,7 @@ module Dependabot
172
180
  .params(language_version: T.nilable(T.any(String, Dependabot::Version)))
173
181
  .returns(T.nilable(Dependabot::Version))
174
182
  end
175
- def fetch_lowest_security_fix_version(language_version:) # rubocop:disable Lint/UnusedMethodArgument
183
+ def fetch_lowest_security_fix_version(language_version: nil) # rubocop:disable Lint/UnusedMethodArgument
176
184
  with_custom_registry_rescue do
177
185
  return unless valid_npm_details?
178
186
 
@@ -180,7 +188,7 @@ module Dependabot
180
188
  if specified_dist_tag_requirement?
181
189
  [version_from_dist_tags].compact
182
190
  else
183
- possible_versions(filter_ignored: false)
191
+ possible_releases(filter_ignored: false)
184
192
  end
185
193
 
186
194
  secure_versions =
@@ -196,22 +204,22 @@ module Dependabot
196
204
  secure_versions = lazy_filter_yanked_versions_by_min_max(secure_versions, check_max: false)
197
205
 
198
206
  # Return the lowest non-yanked version
199
- secure_versions.max
207
+ secure_versions.max_by(&:version)&.version
200
208
  end
201
209
  end
202
210
 
203
211
  sig do
204
- params(versions_array: T::Array[Dependabot::Version])
205
- .returns(T::Array[Dependabot::Version])
212
+ params(releases: T::Array[Dependabot::Package::PackageRelease])
213
+ .returns(T::Array[Dependabot::Package::PackageRelease])
206
214
  end
207
- def filter_prerelease_versions(versions_array)
208
- filtered = versions_array.reject do |v|
209
- v.prerelease? && !related_to_current_pre?(v)
215
+ def filter_prerelease_versions(releases)
216
+ filtered = releases.reject do |release|
217
+ release.version.prerelease? && !related_to_current_pre?(release.version)
210
218
  end
211
219
 
212
- if versions_array.count > filtered.count
220
+ if releases.count > filtered.count
213
221
  Dependabot.logger.info(
214
- "Filtered out #{versions_array.count - filtered.count} unrelated pre-release versions"
222
+ "Filtered out #{releases.count - filtered.count} unrelated pre-release versions"
215
223
  )
216
224
  end
217
225
 
@@ -317,7 +325,7 @@ module Dependabot
317
325
  !!package_details&.releases&.any?
318
326
  end
319
327
 
320
- sig { returns(T.nilable(Dependabot::Version)) }
328
+ sig { returns(T.nilable(Dependabot::Package::PackageRelease)) }
321
329
  def version_from_dist_tags # rubocop:disable Metrics/PerceivedComplexity
322
330
  dist_tags = package_details&.dist_tags
323
331
  return nil unless dist_tags
@@ -332,14 +340,14 @@ module Dependabot
332
340
 
333
341
  if dist_tag_req
334
342
  release = find_dist_tag_release(dist_tag_req, releases)
335
- return release.version if release && !release.yanked?
343
+ return release if release && !release.yanked?
336
344
  end
337
345
 
338
346
  latest_release = find_dist_tag_release("latest", releases)
339
347
 
340
348
  return nil unless latest_release
341
349
 
342
- return latest_release.version if wants_latest_dist_tag?(latest_release.version) && !latest_release.yanked?
350
+ return latest_release if wants_latest_dist_tag?(latest_release.version) && !latest_release.yanked?
343
351
 
344
352
  nil
345
353
  end
@@ -1,7 +1,9 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "excon"
5
+ require "sorbet-runtime"
6
+
5
7
  require "dependabot/npm_and_yarn/update_checker"
6
8
  require "dependabot/shared_helpers"
7
9
 
@@ -9,12 +11,23 @@ module Dependabot
9
11
  module NpmAndYarn
10
12
  class UpdateChecker
11
13
  class LibraryDetector
14
+ extend T::Sig
15
+
16
+ sig do
17
+ params(
18
+ package_json_file: Dependabot::DependencyFile,
19
+ credentials: T::Array[Dependabot::Credential],
20
+ dependency_files: T::Array[Dependabot::DependencyFile]
21
+ )
22
+ .void
23
+ end
12
24
  def initialize(package_json_file:, credentials:, dependency_files:)
13
25
  @package_json_file = package_json_file
14
26
  @credentials = credentials
15
27
  @dependency_files = dependency_files
16
28
  end
17
29
 
30
+ sig { returns(T::Boolean) }
18
31
  def library?
19
32
  return false unless package_json_may_be_for_library?
20
33
 
@@ -23,26 +36,36 @@ module Dependabot
23
36
 
24
37
  private
25
38
 
39
+ sig { returns(Dependabot::DependencyFile) }
26
40
  attr_reader :package_json_file
41
+
42
+ sig { returns(T::Array[Dependabot::Credential]) }
27
43
  attr_reader :credentials
44
+
45
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
28
46
  attr_reader :dependency_files
29
47
 
48
+ sig { returns(T::Boolean) }
30
49
  def package_json_may_be_for_library?
31
50
  return false unless project_name
32
- return false if project_name.match?(/\{\{.*\}\}/)
51
+ return false if T.must(project_name).match?(/\{\{.*\}\}/)
33
52
  return false unless parsed_package_json["version"]
34
53
  return false if parsed_package_json["private"]
35
54
 
36
55
  true
37
56
  end
38
57
 
58
+ sig { returns(T::Boolean) }
39
59
  def npm_response_matches_package_json?
40
60
  project_description = parsed_package_json["description"]
41
61
  return false unless project_description
42
62
 
43
63
  # Check if the project is listed on npm. If it is, it's a library
44
64
  url = "#{registry.chomp('/')}/#{escaped_project_name}"
45
- @project_npm_response ||= Dependabot::RegistryClient.get(url: url)
65
+ @project_npm_response ||= T.let(
66
+ Dependabot::RegistryClient.get(url: url),
67
+ T.nilable(Excon::Response)
68
+ )
46
69
  return false unless @project_npm_response.status == 200
47
70
 
48
71
  @project_npm_response.body.dup.force_encoding("UTF-8").encode
@@ -51,18 +74,25 @@ module Dependabot
51
74
  false
52
75
  end
53
76
 
77
+ sig { returns(T.nilable(String)) }
54
78
  def project_name
55
79
  parsed_package_json.fetch("name", nil)
56
80
  end
57
81
 
82
+ sig { returns(T.nilable(String)) }
58
83
  def escaped_project_name
59
84
  project_name&.gsub("/", "%2F")
60
85
  end
61
86
 
87
+ sig { returns(T::Hash[String, T.untyped]) }
62
88
  def parsed_package_json
63
- @parsed_package_json ||= JSON.parse(package_json_file.content)
89
+ @parsed_package_json ||= T.let(
90
+ JSON.parse(T.must(package_json_file.content)),
91
+ T.nilable(T::Hash[String, T.untyped])
92
+ )
64
93
  end
65
94
 
95
+ sig { returns(String) }
66
96
  def registry
67
97
  Package::RegistryFinder.new(
68
98
  dependency: nil,
@@ -70,7 +100,7 @@ module Dependabot
70
100
  npmrc_file: dependency_files.find { |f| f.name.end_with?(".npmrc") },
71
101
  yarnrc_file: dependency_files.find { |f| f.name.end_with?(".yarnrc") },
72
102
  yarnrc_yml_file: dependency_files.find { |f| f.name.end_with?(".yarnrc.yml") }
73
- ).registry_from_rc(project_name)
103
+ ).registry_from_rc(T.must(project_name))
74
104
  end
75
105
  end
76
106
  end
@@ -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.npmjs.com/misc/semver #
7
7
  ################################################################################
8
8
 
9
+ require "sorbet-runtime"
10
+
9
11
  require "dependabot/npm_and_yarn/requirement"
10
12
  require "dependabot/npm_and_yarn/update_checker"
11
13
  require "dependabot/npm_and_yarn/version"
@@ -15,6 +17,8 @@ module Dependabot
15
17
  module NpmAndYarn
16
18
  class UpdateChecker
17
19
  class RequirementsUpdater
20
+ extend T::Sig
21
+
18
22
  VERSION_REGEX = /[0-9]+(?:\.[A-Za-z0-9\-_]+)*/
19
23
  SEPARATOR = /(?<=[a-zA-Z0-9*])[\s|]+(?![\s|-])/
20
24
  ALLOWED_UPDATE_STRATEGIES = T.let(
@@ -27,8 +31,16 @@ module Dependabot
27
31
  T::Array[Dependabot::RequirementsUpdateStrategy]
28
32
  )
29
33
 
30
- def initialize(requirements:, updated_source:, update_strategy:,
31
- latest_resolvable_version:)
34
+ sig do
35
+ params(
36
+ requirements: T::Array[T::Hash[Symbol, T.untyped]],
37
+ updated_source: T.nilable(T::Hash[Symbol, T.untyped]),
38
+ update_strategy: Dependabot::RequirementsUpdateStrategy,
39
+ latest_resolvable_version: T.nilable(T.any(String, Gem::Version))
40
+ )
41
+ .void
42
+ end
43
+ def initialize(requirements:, updated_source:, update_strategy:, latest_resolvable_version:)
32
44
  @requirements = requirements
33
45
  @updated_source = updated_source
34
46
  @update_strategy = update_strategy
@@ -37,10 +49,13 @@ module Dependabot
37
49
 
38
50
  return unless latest_resolvable_version
39
51
 
40
- @latest_resolvable_version =
41
- version_class.new(latest_resolvable_version)
52
+ @latest_resolvable_version = T.let(
53
+ version_class.new(latest_resolvable_version),
54
+ NpmAndYarn::Version
55
+ )
42
56
  end
43
57
 
58
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
44
59
  def updated_requirements
45
60
  return requirements if update_strategy.lockfile_only?
46
61
 
@@ -62,17 +77,26 @@ module Dependabot
62
77
 
63
78
  private
64
79
 
80
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
65
81
  attr_reader :requirements
82
+
83
+ sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
66
84
  attr_reader :updated_source
85
+
86
+ sig { returns(Dependabot::RequirementsUpdateStrategy) }
67
87
  attr_reader :update_strategy
88
+
89
+ sig { returns(T.nilable(NpmAndYarn::Version)) }
68
90
  attr_reader :latest_resolvable_version
69
91
 
92
+ sig { void }
70
93
  def check_update_strategy
71
94
  return if ALLOWED_UPDATE_STRATEGIES.include?(update_strategy)
72
95
 
73
96
  raise "Unknown update strategy: #{update_strategy}"
74
97
  end
75
98
 
99
+ sig { returns(T::Boolean) }
76
100
  def updating_from_git_to_npm?
77
101
  return false unless updated_source.nil?
78
102
 
@@ -80,6 +104,7 @@ module Dependabot
80
104
  original_source&.fetch(:type) == "git"
81
105
  end
82
106
 
107
+ sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
83
108
  def initial_req_after_source_change(req)
84
109
  return req unless updating_from_git_to_npm?
85
110
  return req unless req[:requirement].nil?
@@ -87,12 +112,13 @@ module Dependabot
87
112
  req.merge(requirement: "^#{latest_resolvable_version}")
88
113
  end
89
114
 
115
+ sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
90
116
  def update_version_requirement(req)
91
117
  current_requirement = req[:requirement]
92
118
 
93
119
  if current_requirement.match?(/(<|-\s)/i)
94
120
  ruby_req = ruby_requirements(current_requirement).first
95
- return req if ruby_req.satisfied_by?(latest_resolvable_version)
121
+ return req if ruby_req&.satisfied_by?(latest_resolvable_version)
96
122
 
97
123
  updated_req = update_range_requirement(current_requirement)
98
124
  return req.merge(requirement: updated_req)
@@ -102,6 +128,7 @@ module Dependabot
102
128
  req.merge(requirement: update_version_string(reqs.first))
103
129
  end
104
130
 
131
+ sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
105
132
  def update_version_requirement_if_needed(req)
106
133
  current_requirement = req[:requirement]
107
134
  version = latest_resolvable_version
@@ -113,6 +140,7 @@ module Dependabot
113
140
  update_version_requirement(req)
114
141
  end
115
142
 
143
+ sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
116
144
  def widen_requirement(req)
117
145
  current_requirement = req[:requirement]
118
146
  version = latest_resolvable_version
@@ -135,22 +163,25 @@ module Dependabot
135
163
  req.merge(requirement: updated_requirement)
136
164
  end
137
165
 
166
+ sig { params(requirement_string: String).returns(T::Array[NpmAndYarn::Requirement]) }
138
167
  def ruby_requirements(requirement_string)
139
168
  NpmAndYarn::Requirement
140
169
  .requirements_array(requirement_string)
141
170
  end
142
171
 
172
+ sig { params(req_string: String).returns(String) }
143
173
  def update_range_requirement(req_string)
144
174
  range_requirements =
145
175
  req_string.split(SEPARATOR).select { |r| r.match?(/<|(\s+-\s+)/) }
146
176
 
147
177
  if range_requirements.count == 1
148
- range_requirement = range_requirements.first
178
+ range_requirement = T.must(range_requirements.first)
149
179
  versions = range_requirement.scan(VERSION_REGEX)
150
- upper_bound = versions.map { |v| version_class.new(v) }.max
180
+ version_objects = versions.map { |v| version_class.new(v.to_s) }
181
+ upper_bound = T.must(version_objects.max)
151
182
  new_upper_bound = update_greatest_version(
152
- upper_bound,
153
- latest_resolvable_version
183
+ upper_bound.to_s,
184
+ T.must(latest_resolvable_version)
154
185
  )
155
186
 
156
187
  req_string.sub(
@@ -158,45 +189,51 @@ module Dependabot
158
189
  new_upper_bound.to_s
159
190
  )
160
191
  else
161
- req_string + " || ^#{latest_resolvable_version}"
192
+ req_string + " || ^#{T.must(latest_resolvable_version)}"
162
193
  end
163
194
  end
164
195
 
196
+ sig { params(req_string: String).returns(String) }
165
197
  def update_version_string(req_string)
166
198
  req_string
167
199
  .sub(VERSION_REGEX) do |old_version|
168
200
  if old_version.match?(/\d-/) ||
169
- latest_resolvable_version.to_s.match?(/\d-/)
170
- latest_resolvable_version.to_s
201
+ T.must(latest_resolvable_version).to_s.match?(/\d-/)
202
+ T.must(latest_resolvable_version).to_s
171
203
  else
172
204
  old_parts = old_version.split(".")
173
- new_parts = latest_resolvable_version.to_s.split(".")
174
- .first(old_parts.count)
205
+ new_parts = T.must(latest_resolvable_version).to_s.split(".")
206
+ .first(old_parts.count)
175
207
  new_parts.map.with_index do |part, i|
176
- old_parts[i].match?(/^x\b/) ? "x" : part
208
+ old_parts[i]&.match?(/^x\b/) ? "x" : part
177
209
  end.join(".")
178
210
  end
179
211
  end
180
212
  end
181
213
 
214
+ sig { params(old_version: String, version_to_be_permitted: NpmAndYarn::Version).returns(String) }
182
215
  def update_greatest_version(old_version, version_to_be_permitted)
183
216
  version = version_class.new(old_version)
184
217
  version = version.release if version.prerelease?
185
218
 
186
219
  index_to_update =
187
- version.segments.map.with_index { |seg, i| seg.zero? ? 0 : i }.max
220
+ version.segments.map.with_index { |seg, i| T.cast(seg, Integer).zero? ? 0 : i }.max || 0
188
221
 
189
222
  version.segments.map.with_index do |_, index|
190
- if index < index_to_update
191
- version_to_be_permitted.segments[index]
192
- elsif index == index_to_update
193
- version_to_be_permitted.segments[index] + 1
194
- else
195
- 0
196
- end
223
+ segment_value =
224
+ if index < index_to_update
225
+ T.cast(version_to_be_permitted.segments[index], Integer)
226
+ elsif index == index_to_update
227
+ # Cast to Integer before adding 1 to ensure correct type
228
+ T.cast(version_to_be_permitted.segments[index], Integer) + 1
229
+ else
230
+ 0
231
+ end
232
+ segment_value.to_s
197
233
  end.join(".")
198
234
  end
199
235
 
236
+ sig { returns(T.class_of(NpmAndYarn::Version)) }
200
237
  def version_class
201
238
  NpmAndYarn::Version
202
239
  end
@@ -1,7 +1,9 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "stringio"
5
+ require "sorbet-runtime"
6
+
5
7
  require "dependabot/dependency"
6
8
  require "dependabot/errors"
7
9
  require "dependabot/logger"
@@ -16,6 +18,15 @@ module Dependabot
16
18
  module NpmAndYarn
17
19
  class UpdateChecker < Dependabot::UpdateCheckers::Base
18
20
  class VulnerabilityAuditor
21
+ extend T::Sig
22
+
23
+ sig do
24
+ params(
25
+ dependency_files: T::Array[Dependabot::DependencyFile],
26
+ credentials: T::Array[Dependabot::Credential]
27
+ )
28
+ .void
29
+ end
19
30
  def initialize(dependency_files:, credentials:)
20
31
  @dependency_files = dependency_files
21
32
  @credentials = credentials
@@ -43,6 +54,13 @@ module Dependabot
43
54
  # * :top_level_ancestors [Array<String>] the names of all top-level dependencies with a transitive
44
55
  # dependency on the dependency
45
56
  # * :explanation [String] an explanation for why the project failed the vulnerability auditor run
57
+ sig do
58
+ params(
59
+ dependency: Dependabot::Dependency,
60
+ security_advisories: T::Array[Dependabot::SecurityAdvisory]
61
+ )
62
+ .returns(T::Hash[String, T.untyped])
63
+ end
46
64
  def audit(dependency:, security_advisories:)
47
65
  Dependabot.logger.info("VulnerabilityAuditor: starting audit")
48
66
 
@@ -76,10 +94,13 @@ module Dependabot
76
94
  }
77
95
  end
78
96
 
79
- audit_result = SharedHelpers.run_helper_subprocess(
80
- command: NativeHelpers.helper_path,
81
- function: "npm:vulnerabilityAuditor",
82
- args: [Dir.pwd, vuln_versions]
97
+ audit_result = T.cast(
98
+ SharedHelpers.run_helper_subprocess(
99
+ command: NativeHelpers.helper_path,
100
+ function: "npm:vulnerabilityAuditor",
101
+ args: [Dir.pwd, vuln_versions]
102
+ ),
103
+ T::Hash[String, T.untyped]
83
104
  )
84
105
 
85
106
  validation_result = validate_audit_result(audit_result, security_advisories)
@@ -94,24 +115,36 @@ module Dependabot
94
115
  end
95
116
  rescue SharedHelpers::HelperSubprocessFailed => e
96
117
  log_helper_subprocess_failure(dependency, e)
97
- fix_unavailable
118
+ T.must(fix_unavailable)
98
119
  end
99
120
  # rubocop:enable Metrics/MethodLength
100
121
 
101
122
  private
102
123
 
124
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
103
125
  attr_reader :dependency_files
126
+
127
+ sig { returns(T::Array[Dependabot::Credential]) }
104
128
  attr_reader :credentials
105
129
 
130
+ sig { params(validation_result: Symbol, dependency: Dependabot::Dependency).returns(String) }
106
131
  def explain_fix_unavailable(validation_result, dependency)
107
132
  case validation_result
108
133
  when :fix_unavailable, :dependency_still_vulnerable, :downgrades_dependencies
109
134
  "No patched version available for #{dependency.name}"
110
135
  when :fix_incomplete
111
136
  "The lockfile might be out of sync?"
137
+ else
138
+ raise "Unexpected validation result: #{validation_result}"
112
139
  end
113
140
  end
114
141
 
142
+ sig do
143
+ params(
144
+ audit_result: T::Hash[String, T.untyped],
145
+ security_advisories: T::Array[Dependabot::SecurityAdvisory]
146
+ ).returns(Symbol)
147
+ end
115
148
  def validate_audit_result(audit_result, security_advisories)
116
149
  return :fix_unavailable unless audit_result["fix_available"]
117
150
  return :dependency_still_vulnerable if dependency_still_vulnerable?(audit_result, security_advisories)
@@ -121,6 +154,13 @@ module Dependabot
121
154
  :viable
122
155
  end
123
156
 
157
+ sig do
158
+ params(
159
+ audit_result: T::Hash[String, T.untyped],
160
+ security_advisories: T::Array[Dependabot::SecurityAdvisory]
161
+ )
162
+ .returns(T::Boolean)
163
+ end
124
164
  def dependency_still_vulnerable?(audit_result, security_advisories)
125
165
  # vulnerable dependency is removed if the target version is nil
126
166
  return false unless audit_result["target_version"]
@@ -129,6 +169,7 @@ module Dependabot
129
169
  security_advisories.any? { |a| a.vulnerable?(version) }
130
170
  end
131
171
 
172
+ sig { params(audit_result: T::Hash[String, T.untyped]).returns(T::Boolean) }
132
173
  def downgrades_dependencies?(audit_result)
133
174
  return true if downgrades_version?(audit_result["current_version"], audit_result["target_version"])
134
175
 
@@ -137,6 +178,13 @@ module Dependabot
137
178
  end
138
179
  end
139
180
 
181
+ sig do
182
+ params(
183
+ current_version: T.nilable(T.any(String, Integer, Gem::Version)),
184
+ target_version: T.nilable(T.any(String, Integer, Gem::Version))
185
+ )
186
+ .returns(T::Boolean)
187
+ end
140
188
  def downgrades_version?(current_version, target_version)
141
189
  return false unless target_version
142
190
 
@@ -145,14 +193,19 @@ module Dependabot
145
193
  current > target
146
194
  end
147
195
 
196
+ sig { params(audit_result: T::Hash[String, T.untyped]).returns(T::Boolean) }
148
197
  def fix_incomplete?(audit_result)
149
198
  audit_result["fix_updates"].any? { |update| !update.key?("target_version") } ||
150
199
  audit_result["fix_updates"].empty?
151
200
  end
152
201
 
202
+ sig do
203
+ params(dependency: Dependabot::Dependency,
204
+ error: Dependabot::SharedHelpers::HelperSubprocessFailed).void
205
+ end
153
206
  def log_helper_subprocess_failure(dependency, error)
154
207
  # See `Dependabot::SharedHelpers.run_helper_subprocess` for details on error context
155
- context = error.error_context || {}
208
+ context = error.error_context
156
209
 
157
210
  builder = ::StringIO.new
158
211
  builder << "VulnerabilityAuditor: "
@@ -167,7 +167,7 @@ module Dependabot
167
167
  requirements: dependency.requirements,
168
168
  updated_source: updated_source,
169
169
  latest_resolvable_version: resolvable_version,
170
- update_strategy: requirements_update_strategy
170
+ update_strategy: T.must(requirements_update_strategy)
171
171
  ).updated_requirements
172
172
  end
173
173
 
@@ -326,7 +326,7 @@ module Dependabot
326
326
  requirements: original_dep.requirements,
327
327
  updated_source: original_dep == dependency ? updated_source : original_source(original_dep),
328
328
  latest_resolvable_version: version,
329
- update_strategy: requirements_update_strategy
329
+ update_strategy: T.must(requirements_update_strategy)
330
330
  ).updated_requirements,
331
331
  previous_version: previous_version,
332
332
  previous_requirements: original_dep.requirements,
@@ -516,7 +516,7 @@ module Dependabot
516
516
 
517
517
  @library =
518
518
  LibraryDetector.new(
519
- package_json_file: package_json,
519
+ package_json_file: T.must(package_json),
520
520
  credentials: credentials,
521
521
  dependency_files: dependency_files
522
522
  ).library?