dependabot-composer 0.310.0 → 0.312.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.
@@ -1,8 +1,9 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "json"
5
5
  require "uri"
6
+ require "sorbet-runtime"
6
7
 
7
8
  require "dependabot/errors"
8
9
  require "dependabot/shared_helpers"
@@ -17,30 +18,49 @@ module Dependabot
17
18
  module Composer
18
19
  class UpdateChecker
19
20
  class VersionResolver # rubocop:disable Metrics/ClassLength
21
+ extend T::Sig
22
+
20
23
  class MissingExtensions < StandardError
24
+ extend T::Sig
25
+
26
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
21
27
  attr_reader :extensions
22
28
 
29
+ sig { params(extensions: T::Array[T::Hash[Symbol, T.untyped]]).void }
23
30
  def initialize(extensions)
24
- @extensions = extensions
31
+ @extensions = T.let(extensions, T::Array[T::Hash[Symbol, T.untyped]])
25
32
  super
26
33
  end
27
34
  end
28
35
 
29
- MISSING_EXPLICIT_PLATFORM_REQ_REGEX =
36
+ MISSING_EXPLICIT_PLATFORM_REQ_REGEX = T.let(
30
37
  %r{
31
38
  (?<=PHP\sextension\s)ext\-[^\s\/]+\s.*?\s(?=is|but)|
32
39
  (?<=requires\s)php(?:\-[^\s\/]+)?\s.*?\s(?=but)
33
- }x
34
- MISSING_IMPLICIT_PLATFORM_REQ_REGEX =
40
+ }x,
41
+ Regexp
42
+ )
43
+ MISSING_IMPLICIT_PLATFORM_REQ_REGEX = T.let(
35
44
  %r{
36
45
  (?<!with|for|by)\sext\-[^\s\/]+\s.*?\s(?=->)|
37
46
  (?<=require\s)php(?:\-[^\s\/]+)?\s.*?\s(?=->) # composer v2
38
- }x
39
- VERSION_REGEX = /[0-9]+(?:\.[A-Za-z0-9\-_]+)*/
47
+ }x,
48
+ Regexp
49
+ )
50
+ VERSION_REGEX = T.let(/[0-9]+(?:\.[A-Za-z0-9\-_]+)*/, Regexp)
40
51
 
41
52
  # Example Timeout error from Composer 2.7.7: "curl error 28 while downloading https://example.com:81/packages.json: Failed to connect to example.com port 81 after 9853 ms: Connection timed out" # rubocop:disable Layout/LineLength
42
- SOURCE_TIMED_OUT_REGEX = %r{curl error 28 while downloading (?<url>https?://.+/packages\.json): }
53
+ SOURCE_TIMED_OUT_REGEX = T.let(%r{curl error 28 while downloading (?<url>https?://.+/packages\.json): }, Regexp)
43
54
 
55
+ sig do
56
+ params(
57
+ credentials: T::Array[Dependabot::Credential],
58
+ dependency: Dependabot::Dependency,
59
+ dependency_files: T::Array[Dependabot::DependencyFile],
60
+ requirements_to_unlock: Symbol,
61
+ latest_allowable_version: T.nilable(Gem::Version)
62
+ ).void
63
+ end
44
64
  def initialize(credentials:, dependency:, dependency_files:,
45
65
  requirements_to_unlock:, latest_allowable_version:)
46
66
  @credentials = credentials
@@ -48,24 +68,43 @@ module Dependabot
48
68
  @dependency_files = dependency_files
49
69
  @requirements_to_unlock = requirements_to_unlock
50
70
  @latest_allowable_version = latest_allowable_version
51
- @composer_platform_extensions = initial_platform
52
- @error_handler = ComposerErrorHandler.new
71
+ @composer_platform_extensions = T.let(initial_platform, T::Hash[String, T::Array[String]])
72
+ @error_handler = T.let(ComposerErrorHandler.new, ComposerErrorHandler)
53
73
  end
54
74
 
75
+ sig { returns(T.nilable(Dependabot::Version)) }
55
76
  def latest_resolvable_version
56
- @latest_resolvable_version ||= fetch_latest_resolvable_version
77
+ @latest_resolvable_version ||= T.let(
78
+ fetch_latest_resolvable_version,
79
+ T.nilable(Dependabot::Version)
80
+ )
57
81
  end
58
82
 
59
83
  private
60
84
 
85
+ # Initialize instance variables with T.let for strict typing
86
+ sig { returns(T::Array[Dependabot::Credential]) }
61
87
  attr_reader :credentials
88
+
89
+ sig { returns(Dependabot::Dependency) }
62
90
  attr_reader :dependency
91
+
92
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
63
93
  attr_reader :dependency_files
94
+
95
+ sig { returns(Symbol) }
64
96
  attr_reader :requirements_to_unlock
97
+
98
+ sig { returns(T.nilable(Gem::Version)) }
65
99
  attr_reader :latest_allowable_version
100
+
101
+ sig { returns(T::Hash[String, T::Array[String]]) }
66
102
  attr_reader :composer_platform_extensions
103
+
104
+ sig { returns(ComposerErrorHandler) }
67
105
  attr_reader :error_handler
68
106
 
107
+ sig { returns(T.nilable(Dependabot::Version)) }
69
108
  def fetch_latest_resolvable_version
70
109
  version = fetch_latest_resolvable_version_string
71
110
  return if version.nil?
@@ -80,8 +119,9 @@ module Dependabot
80
119
  retry
81
120
  end
82
121
 
122
+ sig { returns(T.nilable(String)) }
83
123
  def fetch_latest_resolvable_version_string
84
- base_directory = dependency_files.first.directory
124
+ base_directory = T.must(dependency_files.first).directory
85
125
  SharedHelpers.in_a_temporary_directory(base_directory) do
86
126
  write_temporary_dependency_files
87
127
  run_update_checker
@@ -93,6 +133,7 @@ module Dependabot
93
133
  handle_composer_errors(e)
94
134
  end
95
135
 
136
+ sig { params(unlock_requirement: T::Boolean).void }
96
137
  def write_temporary_dependency_files(unlock_requirement: true)
97
138
  write_dependency_file(unlock_requirement: unlock_requirement)
98
139
  write_path_dependency_files
@@ -101,6 +142,7 @@ module Dependabot
101
142
  write_auth_file
102
143
  end
103
144
 
145
+ sig { void }
104
146
  def write_zipped_path_dependency_files
105
147
  zipped_path_dependency_files.each do |file|
106
148
  FileUtils.mkdir_p(Pathname.new(file.name).dirname)
@@ -108,6 +150,7 @@ module Dependabot
108
150
  end
109
151
  end
110
152
 
153
+ sig { params(unlock_requirement: T::Boolean).void }
111
154
  def write_dependency_file(unlock_requirement:)
112
155
  File.write(
113
156
  PackageManager::MANIFEST_FILENAME,
@@ -117,6 +160,7 @@ module Dependabot
117
160
  )
118
161
  end
119
162
 
163
+ sig { void }
120
164
  def write_path_dependency_files
121
165
  path_dependency_files.each do |file|
122
166
  FileUtils.mkdir_p(Pathname.new(file.name).dirname)
@@ -124,14 +168,17 @@ module Dependabot
124
168
  end
125
169
  end
126
170
 
171
+ sig { void }
127
172
  def write_lockfile
128
- File.write(PackageManager::LOCKFILE_FILENAME, lockfile.content) if lockfile
173
+ File.write(PackageManager::LOCKFILE_FILENAME, T.must(lockfile).content) if lockfile
129
174
  end
130
175
 
176
+ sig { void }
131
177
  def write_auth_file
132
- File.write(PackageManager::AUTH_FILENAME, auth_json.content) if auth_json
178
+ File.write(PackageManager::AUTH_FILENAME, T.must(auth_json).content) if auth_json
133
179
  end
134
180
 
181
+ sig { params(error: SharedHelpers::HelperSubprocessFailed).returns(T::Boolean) }
135
182
  def transitory_failure?(error)
136
183
  return true if error.message.include?("404 Not Found")
137
184
  return true if error.message.include?("timed out")
@@ -140,6 +187,7 @@ module Dependabot
140
187
  error.message.include?("Content-Length mismatch")
141
188
  end
142
189
 
190
+ sig { returns(String) }
143
191
  def run_update_checker
144
192
  SharedHelpers.with_git_configured(credentials: credentials) do
145
193
  SharedHelpers.run_helper_subprocess(
@@ -156,14 +204,16 @@ module Dependabot
156
204
  end
157
205
  end
158
206
 
207
+ sig { params(unlock_requirement: T::Boolean).returns(String) }
159
208
  def prepared_composer_json_content(unlock_requirement: true)
160
- content = composer_file.content
209
+ content = T.must(T.must(composer_file).content)
161
210
  content = unlock_dep_being_updated(content) if unlock_requirement
162
211
  content = lock_git_dependencies(content) if lockfile
163
212
  content = add_temporary_platform_extensions(content)
164
213
  content
165
214
  end
166
215
 
216
+ sig { params(content: String).returns(String) }
167
217
  def unlock_dep_being_updated(content)
168
218
  content.gsub(
169
219
  /"#{Regexp.escape(dependency.name)}"\s*:\s*".*"/,
@@ -171,6 +221,7 @@ module Dependabot
171
221
  )
172
222
  end
173
223
 
224
+ sig { params(content: String).returns(String) }
174
225
  def add_temporary_platform_extensions(content)
175
226
  json = JSON.parse(content)
176
227
 
@@ -186,6 +237,7 @@ module Dependabot
186
237
  JSON.dump(json)
187
238
  end
188
239
 
240
+ sig { params(content: String).returns(String) }
189
241
  def lock_git_dependencies(content)
190
242
  json = JSON.parse(content)
191
243
 
@@ -197,7 +249,7 @@ module Dependabot
197
249
  next if req.include?("#")
198
250
 
199
251
  commit_sha = parsed_lockfile
200
- .fetch(keys[:lockfile], [])
252
+ .fetch(T.must(keys[:lockfile]), [])
201
253
  .find { |d| d["name"] == name }
202
254
  &.dig("source", "reference")
203
255
  updated_req_parts = req.split
@@ -211,6 +263,7 @@ module Dependabot
211
263
 
212
264
  # rubocop:disable Metrics/PerceivedComplexity
213
265
  # rubocop:disable Metrics/AbcSize
266
+ sig { returns(String) }
214
267
  def updated_version_requirement_string
215
268
  lower_bound =
216
269
  if requirements_to_unlock == :none
@@ -253,6 +306,7 @@ module Dependabot
253
306
  # rubocop:disable Metrics/AbcSize
254
307
  # rubocop:disable Metrics/CyclomaticComplexity
255
308
  # rubocop:disable Metrics/MethodLength
309
+ sig { params(error: SharedHelpers::HelperSubprocessFailed).returns(T.nilable(NilClass)) }
256
310
  def handle_composer_errors(error)
257
311
  # Special case for Laravel Nova, which will fall back to attempting
258
312
  # to close a private repo if given invalid (or no) credentials
@@ -271,7 +325,11 @@ module Dependabot
271
325
  missing_extensions =
272
326
  error.message.scan(MISSING_EXPLICIT_PLATFORM_REQ_REGEX)
273
327
  .map do |extension_string|
274
- name, requirement = extension_string.strip.split(" ", 2)
328
+ name, requirement = if extension_string.is_a?(Array)
329
+ [extension_string.first.to_s.strip, extension_string.last.to_s]
330
+ else
331
+ extension_string.to_s.strip.split(" ", 2)
332
+ end
275
333
  { name: name, requirement: requirement }
276
334
  end
277
335
  raise MissingExtensions, missing_extensions
@@ -282,7 +340,7 @@ module Dependabot
282
340
  missing_extensions =
283
341
  error.message.scan(MISSING_IMPLICIT_PLATFORM_REQ_REGEX)
284
342
  .map do |extension_string|
285
- name, requirement = extension_string.strip.split(" ", 2)
343
+ name, requirement = T.cast(extension_string, String).strip.split(" ", 2)
286
344
  { name: name, requirement: requirement }
287
345
  end
288
346
 
@@ -291,7 +349,7 @@ module Dependabot
291
349
  version_for_reqs(existing_reqs + [hash[:requirement]])
292
350
  end
293
351
 
294
- raise MissingExtensions, [missing_extension]
352
+ raise MissingExtensions, [missing_extension].compact
295
353
  elsif error.message.include?("cannot require itself") ||
296
354
  error.message.include?('packages.json" file could not be down')
297
355
  raise Dependabot::DependencyFileNotResolvable, error.message
@@ -312,14 +370,14 @@ module Dependabot
312
370
  # now, we therefore just ignore the dependency and log the error.
313
371
 
314
372
  Dependabot.logger.error(error.message)
315
- error.backtrace.each { |line| Dependabot.logger.error(line) }
373
+ error.backtrace&.each { |line| Dependabot.logger.error(line) }
316
374
  nil
317
375
  elsif error.message.include?("URL required authentication") ||
318
376
  error.message.include?("403 Forbidden")
319
- source = error.message.match(%r{https?://(?<source>[^/]+)/}).named_captures.fetch("source")
377
+ source = error.message.match(%r{https?://(?<source>[^/]+)/})&.named_captures&.fetch("source")
320
378
  raise Dependabot::PrivateSourceAuthenticationFailure, source
321
379
  elsif error.message.match?(SOURCE_TIMED_OUT_REGEX)
322
- url = error.message.match(SOURCE_TIMED_OUT_REGEX).named_captures.fetch("url")
380
+ url = T.must(error.message.match(SOURCE_TIMED_OUT_REGEX)&.named_captures&.fetch("url"))
323
381
  raise if [
324
382
  "packagist.org",
325
383
  "www.packagist.org"
@@ -357,6 +415,7 @@ module Dependabot
357
415
  # rubocop:enable Metrics/CyclomaticComplexity
358
416
  # rubocop:enable Metrics/MethodLength
359
417
 
418
+ sig { params(error: SharedHelpers::HelperSubprocessFailed).returns(T::Boolean) }
360
419
  def unresolvable_error?(error)
361
420
  error.message.start_with?("Could not parse version") ||
362
421
  error.message.include?("does not allow connections to http://") ||
@@ -364,15 +423,17 @@ module Dependabot
364
423
  error.message.start_with?("Invalid version string")
365
424
  end
366
425
 
426
+ sig { returns(T::Boolean) }
367
427
  def library?
368
428
  parsed_composer_file["type"] == "library"
369
429
  end
370
430
 
431
+ sig { params(message: String).returns(T::Boolean) }
371
432
  def implicit_platform_reqs_satisfiable?(message)
372
433
  missing_extensions =
373
434
  message.scan(MISSING_IMPLICIT_PLATFORM_REQ_REGEX)
374
435
  .map do |extension_string|
375
- name, requirement = extension_string.strip.split(" ", 2)
436
+ name, requirement = T.cast(extension_string, String).strip.split(" ", 2)
376
437
  { name: name, requirement: requirement }
377
438
  end
378
439
 
@@ -382,8 +443,9 @@ module Dependabot
382
443
  end
383
444
  end
384
445
 
446
+ sig { returns(T::Boolean) }
385
447
  def check_original_requirements_resolvable
386
- base_directory = dependency_files.first.directory
448
+ base_directory = T.must(dependency_files.first).directory
387
449
  SharedHelpers.in_a_temporary_directory(base_directory) do
388
450
  write_temporary_dependency_files(unlock_requirement: false)
389
451
 
@@ -414,6 +476,7 @@ module Dependabot
414
476
  raise Dependabot::DependencyFileNotResolvable, e.message
415
477
  end
416
478
 
479
+ sig { params(requirements: T::Array[String]).returns(T.nilable(String)) }
417
480
  def version_for_reqs(requirements)
418
481
  req_arrays =
419
482
  requirements
@@ -438,25 +501,32 @@ module Dependabot
438
501
  version.to_s
439
502
  end
440
503
 
504
+ sig { params(additional_extensions: T::Array[T::Hash[Symbol, String]]).void }
441
505
  def update_required_extensions(additional_extensions)
442
506
  additional_extensions.each do |ext|
443
507
  composer_platform_extensions[ext.fetch(:name)] ||= []
444
- composer_platform_extensions[ext.fetch(:name)] +=
445
- [ext.fetch(:requirement)]
446
508
  composer_platform_extensions[ext.fetch(:name)] =
447
- composer_platform_extensions[ext.fetch(:name)].uniq
509
+ T.must(composer_platform_extensions[ext.fetch(:name)]) + [ext.fetch(:requirement)]
510
+ composer_platform_extensions[ext.fetch(:name)] =
511
+ T.must(composer_platform_extensions[ext.fetch(:name)]).uniq
448
512
  end
449
513
  end
450
514
 
515
+ sig { returns(String) }
451
516
  def php_helper_path
452
517
  NativeHelpers.composer_helper_path(composer_version: composer_version)
453
518
  end
454
519
 
520
+ sig { returns(String) }
455
521
  def composer_version
456
522
  parsed_lockfile_or_nil = lockfile ? parsed_lockfile : nil
457
- @composer_version ||= Helpers.composer_version(parsed_composer_file, parsed_lockfile_or_nil)
523
+ @composer_version ||= T.let(
524
+ Helpers.composer_version(parsed_composer_file, parsed_lockfile_or_nil),
525
+ T.nilable(String)
526
+ )
458
527
  end
459
528
 
529
+ sig { returns(T::Hash[String, T::Array[String]]) }
460
530
  def initial_platform
461
531
  platform_php = Helpers.capture_platform_php(parsed_composer_file)
462
532
 
@@ -477,38 +547,63 @@ module Dependabot
477
547
  platform
478
548
  end
479
549
 
550
+ sig { returns(T::Hash[String, T.untyped]) }
480
551
  def parsed_composer_file
481
- @parsed_composer_file ||= JSON.parse(composer_file.content)
552
+ @parsed_composer_file ||= T.let(
553
+ JSON.parse(T.must(T.must(composer_file).content)),
554
+ T.nilable(T::Hash[String, T.untyped])
555
+ )
482
556
  end
483
557
 
558
+ sig { returns(T::Hash[String, T.untyped]) }
484
559
  def parsed_lockfile
485
- @parsed_lockfile ||= JSON.parse(lockfile.content)
560
+ @parsed_lockfile ||= T.let(
561
+ JSON.parse(T.must(lockfile&.content)),
562
+ T.nilable(T::Hash[String, T.untyped])
563
+ )
486
564
  end
487
565
 
566
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
488
567
  def composer_file
489
- @composer_file ||=
490
- dependency_files.find { |f| f.name == PackageManager::MANIFEST_FILENAME }
568
+ @composer_file ||= T.let(
569
+ dependency_files.find { |f| f.name == PackageManager::MANIFEST_FILENAME },
570
+ T.nilable(Dependabot::DependencyFile)
571
+ )
491
572
  end
492
573
 
574
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
493
575
  def path_dependency_files
494
- @path_dependency_files ||=
495
- dependency_files.select { |f| f.name.end_with?("/#{PackageManager::MANIFEST_FILENAME}") }
576
+ @path_dependency_files ||= T.let(
577
+ dependency_files.select { |f| f.name.end_with?("/#{PackageManager::MANIFEST_FILENAME}") },
578
+ T.nilable(T::Array[Dependabot::DependencyFile])
579
+ )
496
580
  end
497
581
 
582
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
498
583
  def zipped_path_dependency_files
499
- @zipped_path_dependency_files ||=
500
- dependency_files.select { |f| f.name.end_with?(".zip", ".gitkeep") }
584
+ @zipped_path_dependency_files ||= T.let(
585
+ dependency_files.select { |f| f.name.end_with?(".zip", ".gitkeep") },
586
+ T.nilable(T::Array[Dependabot::DependencyFile])
587
+ )
501
588
  end
502
589
 
590
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
503
591
  def lockfile
504
- @lockfile ||=
505
- dependency_files.find { |f| f.name == PackageManager::LOCKFILE_FILENAME }
592
+ @lockfile ||= T.let(
593
+ dependency_files.find { |f| f.name == PackageManager::LOCKFILE_FILENAME },
594
+ T.nilable(Dependabot::DependencyFile)
595
+ )
506
596
  end
507
597
 
598
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
508
599
  def auth_json
509
- @auth_json ||= dependency_files.find { |f| f.name == PackageManager::AUTH_FILENAME }
600
+ @auth_json ||= T.let(
601
+ dependency_files.find { |f| f.name == PackageManager::AUTH_FILENAME },
602
+ T.nilable(Dependabot::DependencyFile)
603
+ )
510
604
  end
511
605
 
606
+ sig { params(req_string: String).returns(T::Boolean) }
512
607
  def requirement_valid?(req_string)
513
608
  Composer::Requirement.requirements_array(req_string)
514
609
  true
@@ -516,12 +611,14 @@ module Dependabot
516
611
  false
517
612
  end
518
613
 
614
+ sig { returns(T::Array[Dependabot::Credential]) }
519
615
  def git_credentials
520
616
  credentials
521
617
  .select { |cred| cred["type"] == "git_source" }
522
618
  .select { |cred| cred["password"] }
523
619
  end
524
620
 
621
+ sig { returns(T::Array[Dependabot::Credential]) }
525
622
  def registry_credentials
526
623
  credentials
527
624
  .select { |cred| cred["type"] == PackageManager::REPOSITORY_KEY }
@@ -534,23 +631,24 @@ module Dependabot
534
631
  extend T::Sig
535
632
 
536
633
  # Private source errors
537
- CURL_ERROR = /curl error 52 while downloading (?<url>.*): Empty reply from server/
634
+ CURL_ERROR = T.let(/curl error 52 while downloading (?<url>.*): Empty reply from server/, Regexp)
538
635
 
539
- PRIVATE_SOURCE_AUTH_FAIL = [
636
+ PRIVATE_SOURCE_AUTH_FAIL = T.let([
540
637
  /Could not authenticate against (?<url>.*)/,
541
638
  /The '(?<url>.*)' URL could not be accessed \(HTTP 403\)/,
542
639
  /The "(?<url>.*)" file could not be downloaded/
543
- ].freeze
640
+ ].freeze, T::Array[Regexp])
544
641
 
545
- REQUIREMENT_ERROR = /^(?<req>.*) is invalid, it should not contain uppercase characters/
642
+ REQUIREMENT_ERROR = T.let(/^(?<req>.*) is invalid, it should not contain uppercase characters/, Regexp)
546
643
 
547
- NO_URL = "No URL specified"
644
+ NO_URL = T.let("No URL specified", String)
548
645
 
646
+ sig { params(url: String).returns(String) }
549
647
  def sanitize_uri(url)
550
648
  url = "http://#{url}" unless url.start_with?("http")
551
649
  uri = URI.parse(url)
552
650
  host = T.must(uri.host).downcase
553
- host.start_with?("www.") ? host[4..-1] : host
651
+ host.start_with?("www.") ? T.must(host[4..-1]) : host
554
652
  end
555
653
 
556
654
  # Handles errors with specific to composer error codes
@@ -561,7 +659,8 @@ module Dependabot
561
659
  next unless error.message.match?(regex)
562
660
 
563
661
  url = T.must(error.message.match(regex)).named_captures["url"]
564
- raise Dependabot::PrivateSourceAuthenticationFailure, sanitize_uri(url).empty? ? NO_URL : sanitize_uri(url)
662
+ sanitized_url = sanitize_uri(T.must(url))
663
+ raise Dependabot::PrivateSourceAuthenticationFailure, sanitized_url.empty? ? NO_URL : sanitized_url
565
664
  end
566
665
 
567
666
  # invalid requirement mentioned in manifest file
@@ -573,7 +672,7 @@ module Dependabot
573
672
  return unless error.message.match?(CURL_ERROR)
574
673
 
575
674
  url = T.must(error.message.match(CURL_ERROR)).named_captures["url"]
576
- raise PrivateSourceBadResponse, url
675
+ raise PrivateSourceBadResponse, T.must(url)
577
676
  end
578
677
  end
579
678
  end
@@ -28,7 +28,7 @@ module Dependabot
28
28
  latest_version_from_registry || latest_resolvable_version
29
29
  end
30
30
 
31
- sig { override.returns(T.nilable(Dependabot::Composer::Version)) }
31
+ sig { override.returns(T.nilable(Dependabot::Version)) }
32
32
  def latest_resolvable_version
33
33
  return nil if path_dependency? || git_dependency?
34
34
 
@@ -40,26 +40,26 @@ module Dependabot
40
40
  latest_allowable_version: latest_version_from_registry,
41
41
  requirements_to_unlock: :own
42
42
  ).latest_resolvable_version,
43
- T.nilable(Dependabot::Composer::Version)
43
+ T.nilable(Dependabot::Version)
44
44
  )
45
45
  end
46
46
 
47
- sig { override.returns(T.nilable(Dependabot::Composer::Version)) }
47
+ sig { override.returns(T.nilable(Dependabot::Version)) }
48
48
  def lowest_security_fix_version
49
49
  latest_version_finder.lowest_security_fix_version
50
50
  end
51
51
 
52
- sig { override.returns(T.nilable(Dependabot::Composer::Version)) }
52
+ sig { override.returns(T.nilable(Dependabot::Version)) }
53
53
  def lowest_resolvable_security_fix_version
54
54
  raise "Dependency not vulnerable!" unless vulnerable?
55
55
 
56
56
  @lowest_resolvable_security_fix_version ||= T.let(
57
57
  fetch_lowest_resolvable_security_fix_version,
58
- T.nilable(Dependabot::Composer::Version)
58
+ T.nilable(Dependabot::Version)
59
59
  )
60
60
  end
61
61
 
62
- sig { override.returns(T.nilable(Dependabot::Composer::Version)) }
62
+ sig { override.returns(T.nilable(Dependabot::Version)) }
63
63
  def latest_resolvable_version_with_no_unlock
64
64
  return nil if path_dependency? || git_dependency?
65
65
 
@@ -71,7 +71,7 @@ module Dependabot
71
71
  latest_allowable_version: latest_version_from_registry,
72
72
  requirements_to_unlock: :none
73
73
  ).latest_resolvable_version,
74
- T.nilable(Dependabot::Composer::Version)
74
+ T.nilable(Dependabot::Version)
75
75
  )
76
76
  end
77
77
 
@@ -80,7 +80,7 @@ module Dependabot
80
80
  RequirementsUpdater.new(
81
81
  requirements: dependency.requirements,
82
82
  latest_resolvable_version: preferred_resolvable_version&.to_s,
83
- update_strategy: requirements_update_strategy
83
+ update_strategy: T.must(requirements_update_strategy)
84
84
  ).updated_requirements
85
85
  end
86
86
 
@@ -111,7 +111,7 @@ module Dependabot
111
111
  raise NotImplementedError
112
112
  end
113
113
 
114
- sig { returns(T.nilable(Dependabot::Composer::Version)) }
114
+ sig { returns(T.nilable(Dependabot::Version)) }
115
115
  def latest_version_from_registry
116
116
  latest_version_finder.latest_version
117
117
  end
@@ -131,7 +131,7 @@ module Dependabot
131
131
  )
132
132
  end
133
133
 
134
- sig { returns(T.nilable(Dependabot::Composer::Version)) }
134
+ sig { returns(T.nilable(Dependabot::Version)) }
135
135
  def fetch_lowest_resolvable_security_fix_version
136
136
  return nil if path_dependency? || git_dependency?
137
137
 
@@ -1,6 +1,8 @@
1
- # typed: true
1
+ # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
5
+
4
6
  require "dependabot/version"
5
7
  require "dependabot/utils"
6
8
 
@@ -11,11 +13,15 @@ require "dependabot/utils"
11
13
  module Dependabot
12
14
  module Composer
13
15
  class Version < Dependabot::Version
16
+ extend T::Sig
17
+
18
+ sig { override.params(version: VersionParameter).void }
14
19
  def initialize(version)
15
- @version_string = version.to_s
20
+ @version_string = T.let(version.to_s, String)
16
21
  super
17
22
  end
18
23
 
24
+ sig { returns(String) }
19
25
  def to_s
20
26
  @version_string
21
27
  end