dependabot-bun 0.305.0 → 0.306.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: ce7041993b9d64b4a4189d5ca9a4a03a77dff0a4976ba90320edc0ae5a38b9e3
4
- data.tar.gz: 78474ef6d6bc726d9275a7817c3ff3d7666d4c5692319567060f045aee579440
3
+ metadata.gz: 5318c5bef5f7b65a8b0dfcd0ac25f3a2224c6535d73fce986ac77acdb2485c66
4
+ data.tar.gz: d1209df0024619b48d7e8cb34b4d2dcdf37bdd67593ce0910ed20519eaba6ea5
5
5
  SHA512:
6
- metadata.gz: 952dc4d6c311dab15d48d7992ea857e2f18c0f2df16fb73804f8b2c3d8c3eb6334abf86d10ab455da85d6745d3c8ca7082433d9f8302374bb5d29d7b0f04e758
7
- data.tar.gz: 786c6d9069871bf87518bfc1bdb464ad50fb7818f4ded374e6568c40cf7f31eeef01d692b8a41f07e57d2ca0783824d155cc44238a691a8aad49dd7649ec9cce
6
+ metadata.gz: 547fcd49277721954a07f796e265fc4d69759d2338ff5e3e513f93c66ea32cf4eb574fc330230ccf20e6c355591aeca11e19a138734cfdc2a1bdf638ec445787
7
+ data.tar.gz: 104aa91ef4222b1cf17e200ee9656c538afca3b14a84b338e8e63ad1796c101118514dec420d278b19355dccc4514f7117577fb60362deb22a7750d54f6378d9
@@ -98,8 +98,6 @@ module Dependabot
98
98
 
99
99
  sig { returns(T.nilable(T.any(Integer, String))) }
100
100
  def bun_version
101
- return @bun_version = nil unless allow_beta_ecosystems?
102
-
103
101
  @bun_version ||= T.let(
104
102
  package_manager_helper.setup(BunPackageManager::NAME),
105
103
  T.nilable(T.any(Integer, String))
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "sorbet-runtime"
@@ -27,9 +27,9 @@ module Dependabot
27
27
 
28
28
  require_relative "latest_version_finder"
29
29
 
30
- TIGHTLY_COUPLED_MONOREPOS = {
30
+ TIGHTLY_COUPLED_MONOREPOS = T.let({
31
31
  "vue" => %w(vue vue-template-compiler)
32
- }.freeze
32
+ }.freeze, T::Hash[String, T::Array[String]])
33
33
 
34
34
  # Error message returned by `npm install` (for NPM 6):
35
35
  # react-dom@15.2.0 requires a peer of react@^15.2.0 \
@@ -54,19 +54,55 @@ module Dependabot
54
54
  npm\s(?:WARN|ERR!)\speer\s(?<required_dep>\S+@\S+(\s\S+)?)\sfrom\s(?<requiring_dep>\S+@\S+)
55
55
  /x
56
56
 
57
- def initialize(dependency:, credentials:, dependency_files:,
58
- latest_allowable_version:, latest_version_finder:, repo_contents_path:, dependency_group: nil)
57
+ sig do
58
+ params(
59
+ dependency: Dependabot::Dependency,
60
+ dependency_files: T::Array[Dependabot::DependencyFile],
61
+ credentials: T::Array[Dependabot::Credential],
62
+ latest_allowable_version: T.nilable(T.any(String, Gem::Version)),
63
+ latest_version_finder: T.any(LatestVersionFinder, PackageLatestVersionFinder),
64
+ repo_contents_path: T.nilable(String),
65
+ dependency_group: T.nilable(Dependabot::DependencyGroup),
66
+ raise_on_ignored: T::Boolean,
67
+ update_cooldown: T.nilable(Dependabot::Package::ReleaseCooldownOptions)
68
+ ).void
69
+ end
70
+ def initialize( # rubocop:disable Metrics/AbcSize
71
+ dependency:, dependency_files:, credentials:,
72
+ latest_allowable_version:, latest_version_finder:,
73
+ repo_contents_path:, dependency_group: nil,
74
+ raise_on_ignored: false, update_cooldown: nil
75
+ )
59
76
  @dependency = dependency
60
- @credentials = credentials
61
77
  @dependency_files = dependency_files
78
+ @credentials = credentials
62
79
  @latest_allowable_version = latest_allowable_version
63
80
  @dependency_group = dependency_group
64
81
 
65
- @latest_version_finder = {}
82
+ @latest_version_finder = T.let(
83
+ {},
84
+ T::Hash[Dependabot::Dependency, T.any(LatestVersionFinder, PackageLatestVersionFinder)
85
+ ]
86
+ )
66
87
  @latest_version_finder[dependency] = latest_version_finder
67
88
  @repo_contents_path = repo_contents_path
68
- end
69
-
89
+ @raise_on_ignored = raise_on_ignored
90
+ @update_cooldown = update_cooldown
91
+
92
+ @types_package = T.let(nil, T.nilable(Dependabot::Dependency))
93
+ @original_package = T.let(nil, T.nilable(Dependabot::Dependency))
94
+ @latest_types_package_version = T.let(nil, T.nilable(Dependabot::Version))
95
+ @dependency_files_builder = T.let(nil, T.nilable(DependencyFilesBuilder))
96
+ @resolve_latest_previous_version = T.let({}, T::Hash[Dependabot::Dependency, T.nilable(String)])
97
+ @paths_requiring_update_check = T.let(nil, T.nilable(T::Array[String]))
98
+ @top_level_dependencies = T.let(nil, T.nilable(T::Array[Dependabot::Dependency]))
99
+ @old_peer_dependency_errors = T.let(
100
+ nil, T.nilable(T::Array[T.any(T::Hash[String, T.nilable(String)], String)])
101
+ )
102
+ @peer_dependency_errors = T.let(nil, T.nilable(T::Array[T.any(T::Hash[String, T.nilable(String)], String)]))
103
+ end
104
+
105
+ sig { returns(T.nilable(T.any(String, Gem::Version))) }
70
106
  def latest_resolvable_version
71
107
  return latest_allowable_version if git_dependency?(dependency)
72
108
  return if part_of_tightly_locked_monorepo?
@@ -78,17 +114,24 @@ module Dependabot
78
114
  satisfying_versions.first
79
115
  end
80
116
 
117
+ sig { returns(T::Boolean) }
81
118
  def latest_version_resolvable_with_full_unlock?
82
119
  return false if dependency_updates_from_full_unlock.nil?
83
120
 
84
121
  true
85
122
  end
86
123
 
124
+ sig do
125
+ params(
126
+ updated_version: T.nilable(T.any(String, Gem::Version))
127
+ ).returns(T.nilable(T.any(String, Gem::Version)))
128
+ end
87
129
  def latest_resolvable_previous_version(updated_version)
88
130
  resolve_latest_previous_version(dependency, updated_version)
89
131
  end
90
132
 
91
133
  # rubocop:disable Metrics/PerceivedComplexity
134
+ sig { returns(T.nilable(T::Array[T::Hash[String, T.nilable(String)]])) }
92
135
  def dependency_updates_from_full_unlock
93
136
  return if git_dependency?(dependency)
94
137
  return updated_monorepo_dependencies if part_of_tightly_locked_monorepo?
@@ -131,28 +174,61 @@ module Dependabot
131
174
 
132
175
  sig { returns(Dependabot::Dependency) }
133
176
  attr_reader :dependency
134
- attr_reader :credentials
177
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
135
178
  attr_reader :dependency_files
179
+ sig { returns(T::Array[Dependabot::Credential]) }
180
+ attr_reader :credentials
181
+ sig { returns(T.nilable(T.any(String, Gem::Version))) }
136
182
  attr_reader :latest_allowable_version
183
+ sig { returns(T.nilable(String)) }
137
184
  attr_reader :repo_contents_path
185
+ sig { returns(T.nilable(Dependabot::DependencyGroup)) }
138
186
  attr_reader :dependency_group
187
+ sig { returns(T.nilable(Dependabot::Package::ReleaseCooldownOptions)) }
188
+ attr_reader :update_cooldown
189
+ sig { returns(T::Boolean) }
190
+ attr_reader :raise_on_ignored
139
191
 
192
+ sig { params(dep: Dependabot::Dependency) .returns(T.any(LatestVersionFinder, PackageLatestVersionFinder)) }
140
193
  def latest_version_finder(dep)
141
194
  @latest_version_finder[dep] ||=
142
- LatestVersionFinder.new(
143
- dependency: dep,
144
- credentials: credentials,
145
- dependency_files: dependency_files,
146
- ignored_versions: [],
147
- security_advisories: []
148
- )
195
+ if enable_cooldown?
196
+ PackageLatestVersionFinder.new(
197
+ dependency: dep,
198
+ dependency_files: dependency_files,
199
+ credentials: credentials,
200
+ cooldown_options: update_cooldown,
201
+ ignored_versions: [],
202
+ security_advisories: [],
203
+ raise_on_ignored: raise_on_ignored
204
+ )
205
+ else
206
+ LatestVersionFinder.new(
207
+ dependency: dep,
208
+ credentials: credentials,
209
+ dependency_files: dependency_files,
210
+ ignored_versions: [],
211
+ security_advisories: [],
212
+ raise_on_ignored: raise_on_ignored
213
+ )
214
+ end
215
+ end
216
+
217
+ sig { returns(T::Boolean) }
218
+ def enable_cooldown?
219
+ Dependabot::Experiments.enabled?(:enable_cooldown_for_npm_and_yarn)
149
220
  end
150
221
 
151
222
  # rubocop:disable Metrics/PerceivedComplexity
223
+ sig do
224
+ params(
225
+ dep: Dependabot::Dependency,
226
+ updated_version: T.nilable(T.any(String, Gem::Version))
227
+ ).returns(T.nilable(String))
228
+ end
152
229
  def resolve_latest_previous_version(dep, updated_version)
153
230
  return dep.version if dep.version
154
231
 
155
- @resolve_latest_previous_version ||= {}
156
232
  @resolve_latest_previous_version[dep] ||= begin
157
233
  relevant_versions = latest_version_finder(dependency)
158
234
  .possible_previous_versions_with_details
@@ -183,6 +259,7 @@ module Dependabot
183
259
  end
184
260
  # rubocop:enable Metrics/PerceivedComplexity
185
261
 
262
+ sig { returns(T::Boolean) }
186
263
  def part_of_tightly_locked_monorepo?
187
264
  monorepo_dep_names =
188
265
  TIGHTLY_COUPLED_MONOREPOS.values
@@ -196,6 +273,7 @@ module Dependabot
196
273
  deps_to_update.count > 1
197
274
  end
198
275
 
276
+ sig { returns(T::Array[T::Hash[String, T.nilable(String)]]) }
199
277
  def updated_monorepo_dependencies
200
278
  monorepo_dep_names =
201
279
  TIGHTLY_COUPLED_MONOREPOS.values
@@ -203,7 +281,7 @@ module Dependabot
203
281
 
204
282
  deps_to_update =
205
283
  top_level_dependencies
206
- .select { |d| monorepo_dep_names.include?(d.name) }
284
+ .select { |d| monorepo_dep_names&.include?(d.name) }
207
285
 
208
286
  updates = []
209
287
  deps_to_update.each do |dep|
@@ -229,48 +307,71 @@ module Dependabot
229
307
  updates
230
308
  end
231
309
 
310
+ sig { returns(T.nilable(Dependabot::Dependency)) }
232
311
  def types_package
233
- @types_package ||= begin
312
+ return @types_package if @types_package
313
+
314
+ @types_package = begin
234
315
  types_package_name = PackageName.new(dependency.name).types_package_name
235
316
  top_level_dependencies.find { |d| types_package_name.to_s == d.name } if types_package_name
236
317
  end
318
+ @types_package
237
319
  end
238
320
 
321
+ sig { returns(T.nilable(Dependabot::Dependency)) }
239
322
  def original_package
240
- @original_package ||= begin
323
+ return @original_package if @original_package
324
+
325
+ @original_package = begin
241
326
  original_package_name = PackageName.new(dependency.name).library_name
242
327
  top_level_dependencies.find { |d| original_package_name.to_s == d.name } if original_package_name
243
328
  end
329
+ @original_package
244
330
  end
245
331
 
332
+ sig { returns(T.nilable(Dependabot::Version)) }
246
333
  def latest_types_package_version
247
- @latest_types_package_version ||= latest_version_finder(types_package).latest_version_from_registry
334
+ types_pkg = types_package
335
+ return unless types_pkg
336
+
337
+ return @latest_types_package_version if @latest_types_package_version
338
+
339
+ @latest_types_package_version = latest_version_finder(types_pkg).latest_version_from_registry
340
+ @latest_types_package_version
248
341
  end
249
342
 
343
+ sig { returns(T::Boolean) }
250
344
  def types_update_available?
251
- return false if types_package.nil?
345
+ types_pkg = types_package
346
+ return false unless types_pkg
252
347
 
253
- return false if latest_types_package_version.nil?
348
+ latest_types_version = latest_types_package_version
349
+ return false unless latest_types_version
254
350
 
255
- return false unless latest_allowable_version.backwards_compatible_with?(latest_types_package_version)
351
+ latest_allowable_ver = latest_allowable_version
352
+ return false unless latest_allowable_ver.is_a?(Version) && latest_allowable_ver.backwards_compatible_with?(
353
+ T.unsafe(latest_types_version)
354
+ )
256
355
 
257
- return false unless version_class.correct?(types_package.version)
356
+ return false unless version_class.correct?(types_pkg.version)
258
357
 
259
- current_types_package_version = version_class.new(types_package.version)
358
+ current_types_package_version = version_class.new(types_pkg.version)
260
359
 
261
- return false unless current_types_package_version < latest_types_package_version
360
+ return false unless current_types_package_version < latest_types_version
262
361
 
263
362
  true
264
363
  end
265
364
 
365
+ sig { returns(T::Boolean) }
266
366
  def original_package_update_available?
267
- return false if original_package.nil?
367
+ original_pack = original_package
368
+ return false unless original_pack
268
369
 
269
- return false unless version_class.correct?(original_package.version)
370
+ return false unless version_class.correct?(original_pack.version)
270
371
 
271
- original_package_version = version_class.new(original_package.version)
372
+ original_package_version = version_class.new(original_pack.version)
272
373
 
273
- latest_version = latest_version_finder(original_package).latest_version_from_registry
374
+ latest_version = latest_version_finder(original_pack).latest_version_from_registry
274
375
 
275
376
  # If the latest version is within the scope of the current requirements,
276
377
  # latest_version will be nil. In such cases, there is no update available.
@@ -279,41 +380,45 @@ module Dependabot
279
380
  original_package_version < latest_version
280
381
  end
281
382
 
383
+ sig { returns(T::Array[T::Hash[String, T.nilable(String)]]) }
282
384
  def updated_types_dependencies
283
385
  [{
284
386
  dependency: types_package,
285
387
  version: latest_types_package_version,
286
388
  previous_version: resolve_latest_previous_version(
287
- types_package, latest_types_package_version
389
+ T.must(types_package), T.cast(latest_types_package_version, Gem::Version)
288
390
  )
289
391
  }]
290
392
  end
291
393
 
394
+ sig { returns(T::Array[T.any(T::Hash[String, T.nilable(String)], String)]) }
292
395
  def peer_dependency_errors
293
- return @peer_dependency_errors if @peer_dependency_errors_checked
294
-
295
- @peer_dependency_errors_checked = true
396
+ return @peer_dependency_errors if @peer_dependency_errors
296
397
 
297
- @peer_dependency_errors =
298
- fetch_peer_dependency_errors(version: latest_allowable_version)
398
+ @peer_dependency_errors = fetch_peer_dependency_errors(version: latest_allowable_version)
399
+ @peer_dependency_errors
299
400
  end
300
401
 
402
+ sig { returns(T::Array[T.any(T::Hash[String, T.nilable(String)], String)]) }
301
403
  def old_peer_dependency_errors
302
- return @old_peer_dependency_errors if @old_peer_dependency_errors_checked
303
-
304
- @old_peer_dependency_errors_checked = true
404
+ return @old_peer_dependency_errors if @old_peer_dependency_errors
305
405
 
306
406
  version = version_for_dependency(dependency)
307
407
 
308
- @old_peer_dependency_errors =
309
- fetch_peer_dependency_errors(version: version)
408
+ @old_peer_dependency_errors = fetch_peer_dependency_errors(version: version)
409
+ @old_peer_dependency_errors
310
410
  end
311
411
 
412
+ sig do
413
+ params(
414
+ version: T.nilable(T.any(String, Gem::Version))
415
+ ).returns(T::Array[T.any(T::Hash[String, T.nilable(String)], String)])
416
+ end
312
417
  def fetch_peer_dependency_errors(version:)
313
418
  # TODO: Add all of the error handling that the FileUpdater does
314
419
  # here (since problematic repos will be resolved here before they're
315
420
  # seen by the FileUpdater)
316
- base_dir = dependency_files.first.directory
421
+ base_dir = T.must(dependency_files.first).directory
317
422
  SharedHelpers.in_a_temporary_repo_directory(base_dir, repo_contents_path) do
318
423
  dependency_files_builder.write_temporary_dependency_files
319
424
 
@@ -345,16 +450,22 @@ module Dependabot
345
450
  errors
346
451
  end
347
452
 
453
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
348
454
  def unmet_peer_dependencies
349
455
  peer_dependency_errors
350
456
  .map { |captures| error_details_from_captures(captures) }
351
457
  end
352
458
 
459
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
353
460
  def old_unmet_peer_dependencies
354
461
  old_peer_dependency_errors
355
462
  .map { |captures| error_details_from_captures(captures) }
356
463
  end
357
464
 
465
+ sig do
466
+ params(captures: T.any(T::Hash[String, T.nilable(String)], String))
467
+ .returns(T::Hash[Symbol, T.nilable(String)])
468
+ end
358
469
  def error_details_from_captures(captures)
359
470
  return {} unless captures.is_a?(Hash)
360
471
 
@@ -364,12 +475,13 @@ module Dependabot
364
475
 
365
476
  {
366
477
  requirement_name: required_dep_captures.sub(/@[^@]+$/, ""),
367
- requirement_version: required_dep_captures.split("@").last.delete('"'),
478
+ requirement_version: required_dep_captures.split("@").last&.delete('"'),
368
479
  requiring_dep_name: requiring_dep_captures.sub(/@[^@]+$/, "")
369
480
  }
370
481
  end
371
482
 
372
- def relevant_unmet_peer_dependencies
483
+ sig { returns(T::Array[T::Hash[Symbol, T.nilable(String)]]) }
484
+ def relevant_unmet_peer_dependencies # rubocop:disable Metrics/PerceivedComplexity
373
485
  relevant_unmet_peer_dependencies =
374
486
  unmet_peer_dependencies.select do |dep|
375
487
  dep[:requirement_name] == dependency.name ||
@@ -380,7 +492,7 @@ module Dependabot
380
492
  # Ignore unmet peer dependencies that are in the dependency group because
381
493
  # the update is also updating those dependencies.
382
494
  relevant_unmet_peer_dependencies.reject! do |dep|
383
- dependency_group.dependencies.any? do |group_dep|
495
+ dependency_group&.dependencies&.any? do |group_dep|
384
496
  dep[:requirement_name] == group_dep.name ||
385
497
  dep[:requiring_dep_name] == group_dep.name
386
498
  end
@@ -399,11 +511,13 @@ module Dependabot
399
511
  end
400
512
 
401
513
  # rubocop:disable Metrics/PerceivedComplexity
514
+ sig { returns(T::Array[T.any(String, Gem::Version)]) }
402
515
  def satisfying_versions
403
516
  latest_version_finder(dependency)
404
517
  .possible_versions_with_details
405
- .select do |version, details|
406
- next false unless satisfies_peer_reqs_on_dep?(version)
518
+ .select do |versions_with_details|
519
+ version, details = versions_with_details
520
+ next false unless satisfies_peer_reqs_on_dep?(T.unsafe(version))
407
521
  next true unless details["peerDependencies"]
408
522
  next true if version == version_for_dependency(dependency)
409
523
 
@@ -419,18 +533,18 @@ module Dependabot
419
533
  rescue Gem::Requirement::BadRequirementError
420
534
  false
421
535
  end
422
- end
423
- .map(&:first)
536
+ end.map(&:first)
424
537
  end
425
538
 
426
539
  # rubocop:enable Metrics/PerceivedComplexity
427
540
 
541
+ sig { params(version: T.nilable(T.any(String, Gem::Version))).returns(T::Boolean) }
428
542
  def satisfies_peer_reqs_on_dep?(version)
429
543
  newly_broken_peer_reqs_on_dep.all? do |peer_req|
430
544
  req = peer_req.fetch(:requirement_version)
431
545
 
432
546
  # Git requirements can't be satisfied by a version
433
- next false if req.include?("/")
547
+ next false if req&.include?("/")
434
548
 
435
549
  reqs = requirement_class.requirements_array(req)
436
550
  reqs.any? { |r| r.satisfied_by?(version) }
@@ -439,11 +553,16 @@ module Dependabot
439
553
  end
440
554
  end
441
555
 
442
- def latest_version_of_dep_with_satisfied_peer_reqs(dep)
443
- latest_version_finder(dep)
556
+ sig { params(dep: Dependabot::Dependency).returns(T.nilable(T.any(String, Gem::Version))) }
557
+ def latest_version_of_dep_with_satisfied_peer_reqs(dep) # rubocop:disable Metrics/PerceivedComplexity
558
+ dependency_version = version_for_dependency(dep)
559
+ version_with_detail =
560
+ latest_version_finder(dep)
444
561
  .possible_versions_with_details
445
- .find do |version, details|
446
- next false unless version > version_for_dependency(dep)
562
+ .find do |version_details|
563
+ version, details = version_details
564
+
565
+ next false unless !dependency_version || version > dependency_version
447
566
  next true unless details["peerDependencies"]
448
567
 
449
568
  details["peerDependencies"].all? do |peer_dep_name, req|
@@ -458,9 +577,10 @@ module Dependabot
458
577
  false
459
578
  end
460
579
  end
461
- &.first
580
+ version_with_detail.is_a?(Array) ? version_with_detail.first : version_with_detail
462
581
  end
463
582
 
583
+ sig { params(dep: Dependabot::Dependency).returns(T::Boolean) }
464
584
  def git_dependency?(dep)
465
585
  # ignored_version/raise_on_ignored are irrelevant.
466
586
  GitCommitChecker
@@ -468,22 +588,36 @@ module Dependabot
468
588
  .git_dependency?
469
589
  end
470
590
 
591
+ sig { returns(T::Array[T::Hash[Symbol, T.nilable(String)]]) }
471
592
  def newly_broken_peer_reqs_on_dep
472
593
  relevant_unmet_peer_dependencies
473
594
  .select { |dep| dep[:requirement_name] == dependency.name }
474
595
  end
475
596
 
597
+ sig { returns(T::Array[T::Hash[Symbol, T.nilable(String)]]) }
476
598
  def newly_broken_peer_reqs_from_dep
477
599
  relevant_unmet_peer_dependencies
478
600
  .select { |dep| dep[:requiring_dep_name] == dependency.name }
479
601
  end
480
602
 
603
+ sig do
604
+ params(
605
+ lockfiles: T::Array[Dependabot::DependencyFile],
606
+ path: String
607
+ ).returns(T::Array[Dependabot::DependencyFile])
608
+ end
481
609
  def lockfiles_for_path(lockfiles:, path:)
482
610
  lockfiles.select do |lockfile|
483
611
  File.dirname(lockfile.name) == File.dirname(path)
484
612
  end
485
613
  end
486
614
 
615
+ sig do
616
+ params(
617
+ path: String,
618
+ version: T.nilable(T.any(String, Gem::Version))
619
+ ).returns(T.nilable(T.any(T::Hash[String, T.untyped], String, T::Array[T::Hash[String, T.untyped]])))
620
+ end
487
621
  def run_checker(path:, version:)
488
622
  bun_lockfiles = lockfiles_for_path(lockfiles: dependency_files_builder.bun_locks, path: path)
489
623
  return run_bun_checker(path: path, version: version) if bun_lockfiles.any?
@@ -494,6 +628,12 @@ module Dependabot
494
628
  handle_peer_dependency_errors(e.message)
495
629
  end
496
630
 
631
+ sig do
632
+ params(
633
+ path: String,
634
+ version: T.nilable(T.any(String, Gem::Version))
635
+ ).returns(T.untyped)
636
+ end
497
637
  def run_bun_checker(path:, version:)
498
638
  SharedHelpers.with_git_configured(credentials: credentials) do
499
639
  Dir.chdir(path) do
@@ -505,6 +645,11 @@ module Dependabot
505
645
  end
506
646
  end
507
647
 
648
+ sig do
649
+ params(
650
+ version: T.nilable(T.any(String, Gem::Version))
651
+ ).returns(String)
652
+ end
508
653
  def version_install_arg(version:)
509
654
  git_source = dependency.requirements.find { |req| req[:source] && req[:source][:type] == "git" }
510
655
 
@@ -515,6 +660,12 @@ module Dependabot
515
660
  end
516
661
  end
517
662
 
663
+ sig do
664
+ params(
665
+ requirements: T::Array[T::Hash[Symbol, T.untyped]],
666
+ path: String
667
+ ).returns(T::Array[T::Hash[Symbol, T.untyped]])
668
+ end
518
669
  def requirements_for_path(requirements, path)
519
670
  return requirements if path.to_s == "."
520
671
 
@@ -528,31 +679,44 @@ module Dependabot
528
679
  # Top level dependencies are required in the peer dep checker
529
680
  # to fetch the manifests for all top level deps which may contain
530
681
  # "peerDependency" requirements
682
+ sig { returns(T::Array[Dependabot::Dependency]) }
531
683
  def top_level_dependencies
532
- @top_level_dependencies ||= Bun::FileParser.new(
684
+ return @top_level_dependencies if @top_level_dependencies
685
+
686
+ @top_level_dependencies = Bun::FileParser.new(
533
687
  dependency_files: dependency_files,
534
688
  source: nil,
535
689
  credentials: credentials
536
690
  ).parse.select(&:top_level?)
691
+ @top_level_dependencies
537
692
  end
538
693
 
694
+ sig { returns(T::Array[String]) }
539
695
  def paths_requiring_update_check
540
- @paths_requiring_update_check ||=
696
+ return @paths_requiring_update_check if @paths_requiring_update_check
697
+
698
+ @paths_requiring_update_check =
541
699
  DependencyFilesFilterer.new(
542
700
  dependency_files: dependency_files,
543
701
  updated_dependencies: [dependency]
544
702
  ).paths_requiring_update_check
703
+ @paths_requiring_update_check
545
704
  end
546
705
 
706
+ sig { returns(DependencyFilesBuilder) }
547
707
  def dependency_files_builder
548
- @dependency_files_builder ||=
708
+ return @dependency_files_builder if @dependency_files_builder
709
+
710
+ @dependency_files_builder =
549
711
  DependencyFilesBuilder.new(
550
712
  dependency: dependency,
551
713
  dependency_files: dependency_files,
552
714
  credentials: credentials
553
715
  )
716
+ @dependency_files_builder
554
717
  end
555
718
 
719
+ sig { params(dep: Dependabot::Dependency).returns(T.nilable(T.any(String, Gem::Version))) }
556
720
  def version_for_dependency(dep)
557
721
  return version_class.new(dep.version) if dep.version && version_class.correct?(dep.version)
558
722
 
@@ -565,14 +729,17 @@ module Dependabot
565
729
  .max
566
730
  end
567
731
 
732
+ sig { returns(T.class_of(Dependabot::Version)) }
568
733
  def version_class
569
734
  dependency.version_class
570
735
  end
571
736
 
737
+ sig { returns(T.class_of(Dependabot::Requirement)) }
572
738
  def requirement_class
573
739
  dependency.requirement_class
574
740
  end
575
741
 
742
+ sig { returns(String) }
576
743
  def version_regex
577
744
  Dependabot::Bun::Version::VERSION_PATTERN
578
745
  end
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "set"
@@ -11,7 +11,8 @@ require "dependabot/update_checkers/base"
11
11
 
12
12
  module Dependabot
13
13
  module Bun
14
- class UpdateChecker < Dependabot::UpdateCheckers::Base
14
+ class UpdateChecker < Dependabot::UpdateCheckers::Base # rubocop:disable Metrics/ClassLength
15
+ extend T::Sig
15
16
  require_relative "update_checker/requirements_updater"
16
17
  require_relative "update_checker/library_detector"
17
18
  require_relative "update_checker/latest_version_finder"
@@ -20,6 +21,48 @@ module Dependabot
20
21
  require_relative "update_checker/conflicting_dependency_resolver"
21
22
  require_relative "update_checker/vulnerability_auditor"
22
23
 
24
+ sig do
25
+ params(
26
+ dependency: Dependabot::Dependency,
27
+ dependency_files: T::Array[Dependabot::DependencyFile],
28
+ credentials: T::Array[Dependabot::Credential],
29
+ repo_contents_path: T.nilable(String),
30
+ ignored_versions: T::Array[String],
31
+ raise_on_ignored: T::Boolean,
32
+ security_advisories: T::Array[Dependabot::SecurityAdvisory],
33
+ requirements_update_strategy: T.nilable(Dependabot::RequirementsUpdateStrategy),
34
+ dependency_group: T.nilable(Dependabot::DependencyGroup),
35
+ update_cooldown: T.nilable(Dependabot::Package::ReleaseCooldownOptions),
36
+ options: T::Hash[Symbol, T.untyped]
37
+ )
38
+ .void
39
+ end
40
+ def initialize(dependency:, dependency_files:, credentials:, # rubocop:disable Metrics/AbcSize
41
+ repo_contents_path: nil, ignored_versions: [],
42
+ raise_on_ignored: false, security_advisories: [],
43
+ requirements_update_strategy: nil, dependency_group: nil,
44
+ update_cooldown: nil, options: {})
45
+ @latest_version = T.let(nil, T.nilable(T.any(String, Gem::Version)))
46
+ @latest_resolvable_version = T.let(nil, T.nilable(T.any(String, Gem::Version)))
47
+ @updated_requirements = T.let(nil, T.nilable(T::Array[T::Hash[Symbol, T.untyped]]))
48
+ @vulnerability_audit = T.let(nil, T.nilable(T::Hash[String, T.untyped]))
49
+ @vulnerable_versions = T.let(nil, T.nilable(T::Array[T.any(String, Gem::Version)]))
50
+
51
+ @latest_version_for_git_dependency = T.let(nil, T.nilable(T.any(String, Gem::Version)))
52
+ @latest_released_version = T.let(nil, T.nilable(Gem::Version))
53
+ @latest_version_details = T.let(nil, T.nilable(T::Hash[Symbol, T.untyped]))
54
+ @latest_version_finder = T.let(
55
+ nil, T.nilable(T.any(LatestVersionFinder, PackageLatestVersionFinder))
56
+ )
57
+ @version_resolver = T.let(nil, T.nilable(VersionResolver))
58
+ @subdependency_version_resolver = T.let(nil, T.nilable(SubdependencyVersionResolver))
59
+ @library = T.let(nil, T.nilable(T::Boolean))
60
+ @package_json = T.let(nil, T.nilable(Dependabot::DependencyFile))
61
+ @git_commit_checker = T.let(nil, T.nilable(Dependabot::GitCommitChecker))
62
+ super
63
+ end
64
+
65
+ sig { returns(T::Boolean) }
23
66
  def up_to_date?
24
67
  return false if security_update? &&
25
68
  dependency.version &&
@@ -30,10 +73,12 @@ module Dependabot
30
73
  super
31
74
  end
32
75
 
76
+ sig { returns(T::Boolean) }
33
77
  def vulnerable?
34
78
  super || vulnerable_versions.any?
35
79
  end
36
80
 
81
+ sig { override.returns(T.nilable(T.any(String, Gem::Version))) }
37
82
  def latest_version
38
83
  @latest_version ||=
39
84
  if git_dependency?
@@ -43,6 +88,7 @@ module Dependabot
43
88
  end
44
89
  end
45
90
 
91
+ sig { override.returns(T.nilable(T.any(String, Dependabot::Version))) }
46
92
  def latest_resolvable_version
47
93
  return unless latest_version
48
94
 
@@ -56,13 +102,15 @@ module Dependabot
56
102
  end
57
103
  end
58
104
 
105
+ sig { override.returns(T.nilable(Dependabot::Version)) }
59
106
  def lowest_security_fix_version
60
107
  # This will require a full unlock to update multiple top level ancestors.
61
108
  return if vulnerability_audit["fix_available"] && vulnerability_audit["top_level_ancestors"].count > 1
62
109
 
63
- latest_version_finder.lowest_security_fix_version
110
+ T.unsafe(latest_version_finder.lowest_security_fix_version)
64
111
  end
65
112
 
113
+ sig { override.returns(T.nilable(Dependabot::Version)) }
66
114
  def lowest_resolvable_security_fix_version
67
115
  raise "Dependency not vulnerable!" unless vulnerable?
68
116
 
@@ -83,6 +131,7 @@ module Dependabot
83
131
  lowest_security_fix_version
84
132
  end
85
133
 
134
+ sig { override.returns(T.nilable(T.any(String, Dependabot::Version))) }
86
135
  def latest_resolvable_version_with_no_unlock
87
136
  return latest_resolvable_version unless dependency.top_level?
88
137
 
@@ -91,10 +140,15 @@ module Dependabot
91
140
  latest_version_finder.latest_version_with_no_unlock
92
141
  end
93
142
 
143
+ sig do
144
+ params(updated_version: T.any(String, Gem::Version))
145
+ .returns(T.nilable(T.any(String, T.untyped)))
146
+ end
94
147
  def latest_resolvable_previous_version(updated_version)
95
- version_resolver.latest_resolvable_previous_version(updated_version)
148
+ T.unsafe(version_resolver.latest_resolvable_previous_version(updated_version))
96
149
  end
97
150
 
151
+ sig { override.returns(T::Array[T::Hash[Symbol, T.untyped]]) }
98
152
  def updated_requirements
99
153
  resolvable_version =
100
154
  if preferred_resolvable_version.is_a?(version_class)
@@ -117,10 +171,12 @@ module Dependabot
117
171
  ).updated_requirements
118
172
  end
119
173
 
174
+ sig { returns(T::Boolean) }
120
175
  def requirements_unlocked_or_can_be?
121
- !requirements_update_strategy.lockfile_only?
176
+ !requirements_update_strategy&.lockfile_only?
122
177
  end
123
178
 
179
+ sig { returns(T.nilable(Dependabot::RequirementsUpdateStrategy)) }
124
180
  def requirements_update_strategy
125
181
  # If passed in as an option (in the base class) honour that option
126
182
  return @requirements_update_strategy if @requirements_update_strategy
@@ -129,6 +185,7 @@ module Dependabot
129
185
  library? ? RequirementsUpdateStrategy::WidenRanges : RequirementsUpdateStrategy::BumpVersions
130
186
  end
131
187
 
188
+ sig { override.returns(T::Array[T::Hash[String, String]]) }
132
189
  def conflicting_dependencies
133
190
  conflicts = ConflictingDependencyResolver.new(
134
191
  dependency_files: dependency_files,
@@ -148,10 +205,12 @@ module Dependabot
148
205
 
149
206
  private
150
207
 
208
+ sig { returns(T::Boolean) }
151
209
  def vulnerability_audit_performed?
152
- defined?(@vulnerability_audit)
210
+ !!defined?(@vulnerability_audit)
153
211
  end
154
212
 
213
+ sig { returns(T::Hash[String, T.untyped]) }
155
214
  def vulnerability_audit
156
215
  @vulnerability_audit ||=
157
216
  VulnerabilityAuditor.new(
@@ -163,6 +222,7 @@ module Dependabot
163
222
  )
164
223
  end
165
224
 
225
+ sig { returns(T::Array[T.any(String, Gem::Version)]) }
166
226
  def vulnerable_versions
167
227
  @vulnerable_versions ||=
168
228
  begin
@@ -175,6 +235,7 @@ module Dependabot
175
235
  end
176
236
  end
177
237
 
238
+ sig { override.returns(T::Boolean) }
178
239
  def latest_version_resolvable_with_full_unlock?
179
240
  return false unless latest_version
180
241
 
@@ -185,14 +246,16 @@ module Dependabot
185
246
  vulnerability_audit["fix_available"]
186
247
  end
187
248
 
249
+ sig { override.returns(T::Array[Dependabot::Dependency]) }
188
250
  def updated_dependencies_after_full_unlock
189
251
  return conflicting_updated_dependencies if security_advisories.any? && vulnerability_audit["fix_available"]
190
252
 
191
- version_resolver.dependency_updates_from_full_unlock
192
- .map { |update_details| build_updated_dependency(update_details) }
253
+ T.must(version_resolver.dependency_updates_from_full_unlock)
254
+ .map { |update_details| build_updated_dependency(update_details.transform_keys(&:to_sym)) }
193
255
  end
194
256
 
195
257
  # rubocop:disable Metrics/AbcSize
258
+ sig { returns(T::Array[Dependabot::Dependency]) }
196
259
  def conflicting_updated_dependencies
197
260
  top_level_dependencies = top_level_dependency_lookup
198
261
 
@@ -233,6 +296,7 @@ module Dependabot
233
296
  updated_deps.reject { |dep| dep.name == dependency.name }
234
297
  end
235
298
 
299
+ sig { returns(T::Hash[String, Dependabot::Dependency]) }
236
300
  def top_level_dependency_lookup
237
301
  top_level_dependencies = FileParser.new(
238
302
  dependency_files: dependency_files,
@@ -243,6 +307,11 @@ module Dependabot
243
307
  top_level_dependencies.to_h { |dep| [dep.name, dep] }
244
308
  end
245
309
 
310
+ sig do
311
+ params(
312
+ update_details: T::Hash[Symbol, T.untyped]
313
+ ).returns(Dependabot::Dependency)
314
+ end
246
315
  def build_updated_dependency(update_details)
247
316
  original_dep = update_details.fetch(:dependency)
248
317
  removed = update_details.fetch(:removed, false)
@@ -267,9 +336,15 @@ module Dependabot
267
336
  )
268
337
  end
269
338
 
339
+ sig { returns(T.nilable(T.any(String, Gem::Version, T.untyped))) }
270
340
  def latest_resolvable_transitive_security_fix_version_with_no_unlock
341
+ versions = T.let([], T::Array[Gem::Version])
342
+
343
+ latest = latest_released_version
344
+ versions.push(latest) if latest
345
+
271
346
  fix_possible = Dependabot::UpdateCheckers::VersionFilters.filter_vulnerable_versions(
272
- [latest_resolvable_version].compact,
347
+ versions,
273
348
  security_advisories
274
349
  ).any?
275
350
  return nil unless fix_possible
@@ -277,6 +352,7 @@ module Dependabot
277
352
  latest_resolvable_version
278
353
  end
279
354
 
355
+ sig { returns(T.nilable(T.any(String, Dependabot::Version))) }
280
356
  def latest_resolvable_version_with_no_unlock_for_git_dependency
281
357
  reqs = dependency.requirements.filter_map do |r|
282
358
  next if r.fetch(:requirement).nil?
@@ -300,21 +376,24 @@ module Dependabot
300
376
  git_commit_checker.head_commit_for_current_branch
301
377
  end
302
378
 
379
+ sig { returns(T.nilable(T.any(String, Gem::Version))) }
303
380
  def latest_version_for_git_dependency
304
381
  @latest_version_for_git_dependency ||=
305
382
  if version_class.correct?(dependency.version)
306
- latest_git_version_details[:version] &&
307
- version_class.new(latest_git_version_details[:version])
383
+ T.unsafe(latest_git_version_details[:version] &&
384
+ version_class.new(latest_git_version_details[:version]))
308
385
  else
309
386
  latest_git_version_details[:sha]
310
387
  end
311
388
  end
312
389
 
390
+ sig { returns(T.nilable(Gem::Version)) }
313
391
  def latest_released_version
314
392
  @latest_released_version ||=
315
393
  latest_version_finder.latest_version_from_registry
316
394
  end
317
395
 
396
+ sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
318
397
  def latest_version_details
319
398
  @latest_version_details ||=
320
399
  if git_dependency?
@@ -324,18 +403,37 @@ module Dependabot
324
403
  end
325
404
  end
326
405
 
406
+ sig { returns(T.any(LatestVersionFinder, PackageLatestVersionFinder)) }
327
407
  def latest_version_finder
328
408
  @latest_version_finder ||=
329
- LatestVersionFinder.new(
330
- dependency: dependency,
331
- credentials: credentials,
332
- dependency_files: dependency_files,
333
- ignored_versions: ignored_versions,
334
- raise_on_ignored: raise_on_ignored,
335
- security_advisories: security_advisories
336
- )
409
+ if enable_cooldown?
410
+ PackageLatestVersionFinder.new(
411
+ dependency: dependency,
412
+ credentials: credentials,
413
+ dependency_files: dependency_files,
414
+ ignored_versions: ignored_versions,
415
+ raise_on_ignored: raise_on_ignored,
416
+ security_advisories: security_advisories,
417
+ cooldown_options: @update_cooldown
418
+ )
419
+ else
420
+ LatestVersionFinder.new(
421
+ dependency: dependency,
422
+ credentials: credentials,
423
+ dependency_files: dependency_files,
424
+ ignored_versions: ignored_versions,
425
+ raise_on_ignored: raise_on_ignored,
426
+ security_advisories: security_advisories
427
+ )
428
+ end
337
429
  end
338
430
 
431
+ sig { returns(T::Boolean) }
432
+ def enable_cooldown?
433
+ Dependabot::Experiments.enabled?(:enable_cooldown_for_bun)
434
+ end
435
+
436
+ sig { returns(VersionResolver) }
339
437
  def version_resolver
340
438
  @version_resolver ||=
341
439
  VersionResolver.new(
@@ -345,10 +443,13 @@ module Dependabot
345
443
  latest_allowable_version: latest_version,
346
444
  latest_version_finder: latest_version_finder,
347
445
  repo_contents_path: repo_contents_path,
348
- dependency_group: dependency_group
446
+ dependency_group: dependency_group,
447
+ raise_on_ignored: raise_on_ignored,
448
+ update_cooldown: @update_cooldown
349
449
  )
350
450
  end
351
451
 
452
+ sig { returns(SubdependencyVersionResolver) }
352
453
  def subdependency_version_resolver
353
454
  @subdependency_version_resolver ||=
354
455
  SubdependencyVersionResolver.new(
@@ -361,10 +462,12 @@ module Dependabot
361
462
  )
362
463
  end
363
464
 
465
+ sig { returns(T::Boolean) }
364
466
  def git_dependency?
365
467
  git_commit_checker.git_dependency?
366
468
  end
367
469
 
470
+ sig { returns(T::Hash[Symbol, T.untyped]) }
368
471
  def latest_git_version_details
369
472
  semver_req =
370
473
  dependency.requirements
@@ -390,6 +493,7 @@ module Dependabot
390
493
  { sha: dependency.version }
391
494
  end
392
495
 
496
+ sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
393
497
  def updated_source
394
498
  # Never need to update source, unless a git_dependency
395
499
  return dependency_source_details unless git_dependency?
@@ -398,13 +502,14 @@ module Dependabot
398
502
  if git_commit_checker.pinned_ref_looks_like_version? &&
399
503
  !git_commit_checker.local_tag_for_latest_version.nil?
400
504
  new_tag = git_commit_checker.local_tag_for_latest_version
401
- return dependency_source_details.merge(ref: new_tag.fetch(:tag))
505
+ return dependency_source_details&.merge(ref: new_tag&.fetch(:tag))
402
506
  end
403
507
 
404
508
  # Otherwise return the original source
405
509
  dependency_source_details
406
510
  end
407
511
 
512
+ sig { returns(T::Boolean) }
408
513
  def library?
409
514
  return true unless dependency.version
410
515
  return true if dependency_files.any? { |f| f.name == "lerna.json" }
@@ -417,14 +522,20 @@ module Dependabot
417
522
  ).library?
418
523
  end
419
524
 
525
+ sig { returns(T::Boolean) }
420
526
  def security_update?
421
527
  security_advisories.any?
422
528
  end
423
529
 
530
+ sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
424
531
  def dependency_source_details
425
532
  original_source(dependency)
426
533
  end
427
534
 
535
+ sig do
536
+ params(updated_dependency: Dependabot::Dependency)
537
+ .returns(T.nilable(T::Hash[Symbol, T.untyped]))
538
+ end
428
539
  def original_source(updated_dependency)
429
540
  sources =
430
541
  updated_dependency
@@ -433,14 +544,17 @@ module Dependabot
433
544
  .sort_by do |source|
434
545
  Package::RegistryFinder.central_registry?(source[:url]) ? 1 : 0
435
546
  end
547
+
436
548
  sources.first
437
549
  end
438
550
 
551
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
439
552
  def package_json
440
553
  @package_json ||=
441
554
  dependency_files.find { |f| f.name == "package.json" }
442
555
  end
443
556
 
557
+ sig { returns(Dependabot::GitCommitChecker) }
444
558
  def git_commit_checker
445
559
  @git_commit_checker ||=
446
560
  GitCommitChecker.new(
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-bun
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.305.0
4
+ version: 0.306.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-04-06 00:00:00.000000000 Z
11
+ date: 2025-04-10 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.305.0
19
+ version: 0.306.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.305.0
26
+ version: 0.306.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: debug
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -348,7 +348,7 @@ licenses:
348
348
  - MIT
349
349
  metadata:
350
350
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
351
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.305.0
351
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.306.0
352
352
  post_install_message:
353
353
  rdoc_options: []
354
354
  require_paths: