dependabot-common 0.236.0 → 0.238.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/lib/dependabot/clients/azure.rb +3 -3
  3. data/lib/dependabot/clients/codecommit.rb +1 -0
  4. data/lib/dependabot/config/file.rb +17 -6
  5. data/lib/dependabot/config/update_config.rb +23 -5
  6. data/lib/dependabot/dependency.rb +137 -27
  7. data/lib/dependabot/dependency_file.rb +84 -14
  8. data/lib/dependabot/dependency_group.rb +29 -5
  9. data/lib/dependabot/errors.rb +335 -13
  10. data/lib/dependabot/file_fetchers/base.rb +227 -93
  11. data/lib/dependabot/file_updaters/base.rb +1 -1
  12. data/lib/dependabot/git_commit_checker.rb +6 -0
  13. data/lib/dependabot/git_metadata_fetcher.rb +58 -20
  14. data/lib/dependabot/git_ref.rb +71 -0
  15. data/lib/dependabot/metadata_finders/base/changelog_finder.rb +13 -6
  16. data/lib/dependabot/pull_request_creator/github.rb +11 -8
  17. data/lib/dependabot/pull_request_creator/message.rb +21 -2
  18. data/lib/dependabot/pull_request_creator/message_builder/link_and_mention_sanitizer.rb +37 -16
  19. data/lib/dependabot/pull_request_creator/message_builder/metadata_presenter.rb +4 -2
  20. data/lib/dependabot/pull_request_creator/message_builder.rb +54 -4
  21. data/lib/dependabot/pull_request_creator/pr_name_prefixer.rb +10 -4
  22. data/lib/dependabot/shared_helpers.rb +117 -33
  23. data/lib/dependabot/simple_instrumentor.rb +22 -3
  24. data/lib/dependabot/source.rb +65 -17
  25. data/lib/dependabot/update_checkers/version_filters.rb +12 -1
  26. data/lib/dependabot/utils.rb +21 -2
  27. data/lib/dependabot/workspace/base.rb +42 -7
  28. data/lib/dependabot/workspace/change_attempt.rb +31 -3
  29. data/lib/dependabot/workspace/git.rb +34 -4
  30. data/lib/dependabot/workspace.rb +16 -2
  31. data/lib/dependabot.rb +1 -1
  32. metadata +38 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 945c135096f005a7d416b56d1e8f9e6b91e1a02b0590758887eba5a110fb5b19
4
- data.tar.gz: 0cc101754418b3b1aa682c273e5c6ed2fa72b796d72a9b4d30b3c0f0aa41c39b
3
+ metadata.gz: 77312fe42bc6241de9c474fa2a1bab0dd3955bff4c2846bc057e52684f1b48bf
4
+ data.tar.gz: 72fbe948d041e0d1e2fd717fa98a2358e32413408ed2d147d6cbd58107d8d5ba
5
5
  SHA512:
6
- metadata.gz: 76e41c5707a11e8a5b17df8fa71fc81a4ebbf1a3fd71469931d84cebe1573588afa6605751af2a65c849884bcdf0dd79b5bc4a1d63b9ac69d39466cf8a4b952e
7
- data.tar.gz: 53204ad41f102502301e483b3175280673849b0ab0d530b8458aa77289251dfaf287f9ee051e90bd5b39722a7b25a2993e8a49aa15c03982e82990df475fd9dd
6
+ metadata.gz: f108dbeb6f04a42d5b5b4e30baecad3d376bd82615e067b3ca2696bbdcefd875c55c4dd18da926b597641691e47edb034244d4d170030cbf8055d3c29e9de3cf
7
+ data.tar.gz: e14a429b7dadcd27eccd9e049fb6ebd4a405e8e86229eb683c47d1cb72e911a0da4ae3cab50a3a883000f49ef19e33716cfc2a1fd17181d89858da9644ff80e2
@@ -271,9 +271,9 @@ module Dependabot
271
271
  )
272
272
  )
273
273
 
274
- raise InternalServerError if response&.status == 500
275
- raise BadGateway if response&.status == 502
276
- raise ServiceNotAvailable if response&.status == 503
274
+ raise InternalServerError if response.status == 500
275
+ raise BadGateway if response.status == 502
276
+ raise ServiceNotAvailable if response.status == 503
277
277
  end
278
278
 
279
279
  raise Unauthorized if response&.status == 401
@@ -1,6 +1,7 @@
1
1
  # typed: true
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "aws-sdk-codecommit"
4
5
  require "dependabot/shared_helpers"
5
6
 
6
7
  module Dependabot
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/config/update_config"
@@ -10,11 +10,22 @@ module Dependabot
10
10
  class File
11
11
  extend T::Sig
12
12
 
13
- attr_reader :updates, :registries
13
+ sig { returns(T::Array[T::Hash[Symbol, String]]) }
14
+ attr_reader :updates
14
15
 
16
+ sig { returns T::Array[T.untyped] }
17
+ attr_reader :registries
18
+
19
+ sig do
20
+ params(
21
+ updates: T.nilable(T::Array[T::Hash[Symbol, String]]),
22
+ registries: T.nilable(T::Array[T.untyped])
23
+ )
24
+ .void
25
+ end
15
26
  def initialize(updates:, registries: nil)
16
- @updates = updates || []
17
- @registries = registries || []
27
+ @updates = T.let(updates || [], T::Array[T::Hash[Symbol, String]])
28
+ @registries = T.let(registries || [], T::Array[T.untyped])
18
29
  end
19
30
 
20
31
  sig do
@@ -46,7 +57,7 @@ module Dependabot
46
57
 
47
58
  private
48
59
 
49
- PACKAGE_MANAGER_LOOKUP = {
60
+ PACKAGE_MANAGER_LOOKUP = T.let({
50
61
  "bundler" => "bundler",
51
62
  "cargo" => "cargo",
52
63
  "composer" => "composer",
@@ -64,7 +75,7 @@ module Dependabot
64
75
  "pub" => "pub",
65
76
  "swift" => "swift",
66
77
  "terraform" => "terraform"
67
- }.freeze
78
+ }.freeze, T::Hash[String, String])
68
79
 
69
80
  sig { params(cfg: T.nilable(T::Hash[Symbol, T.untyped])).returns(T::Array[IgnoreCondition]) }
70
81
  def ignore_conditions(cfg)
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/config/ignore_condition"
@@ -23,17 +23,17 @@ module Dependabot
23
23
  ).void
24
24
  end
25
25
  def initialize(ignore_conditions: nil, commit_message_options: nil)
26
- @ignore_conditions = ignore_conditions || []
26
+ @ignore_conditions = T.let(ignore_conditions || [], T::Array[IgnoreCondition])
27
27
  @commit_message_options = commit_message_options
28
28
  end
29
29
 
30
30
  sig { params(dependency: Dependency, security_updates_only: T::Boolean).returns(T::Array[String]) }
31
31
  def ignored_versions_for(dependency, security_updates_only: false)
32
32
  normalizer = name_normaliser_for(dependency)
33
- dep_name = normalizer.call(dependency.name)
33
+ dep_name = T.must(normalizer).call(dependency.name)
34
34
 
35
35
  @ignore_conditions
36
- .select { |ic| self.class.wildcard_match?(normalizer.call(ic.dependency_name), dep_name) }
36
+ .select { |ic| self.class.wildcard_match?(T.must(normalizer).call(ic.dependency_name), dep_name) }
37
37
  .map { |ic| ic.ignored_versions(dependency, security_updates_only) }
38
38
  .flatten
39
39
  .compact
@@ -53,6 +53,7 @@ module Dependabot
53
53
 
54
54
  private
55
55
 
56
+ sig { params(dep: Dependency).returns(T.nilable(T.proc.params(arg0: String).returns(String))) }
56
57
  def name_normaliser_for(dep)
57
58
  name_normaliser ||= {}
58
59
  name_normaliser[dep] ||= Dependency.name_normaliser_for_package_manager(dep.package_manager)
@@ -61,18 +62,35 @@ module Dependabot
61
62
  class CommitMessageOptions
62
63
  extend T::Sig
63
64
 
64
- attr_reader :prefix, :prefix_development, :include
65
+ sig { returns(T.nilable(String)) }
66
+ attr_reader :prefix
65
67
 
68
+ sig { returns(T.nilable(String)) }
69
+ attr_reader :prefix_development
70
+
71
+ sig { returns(T.nilable(String)) }
72
+ attr_reader :include
73
+
74
+ sig do
75
+ params(
76
+ prefix: T.nilable(String),
77
+ prefix_development: T.nilable(String),
78
+ include: T.nilable(String)
79
+ )
80
+ .void
81
+ end
66
82
  def initialize(prefix:, prefix_development:, include:)
67
83
  @prefix = prefix
68
84
  @prefix_development = prefix_development
69
85
  @include = include
70
86
  end
71
87
 
88
+ sig { returns(T::Boolean) }
72
89
  def include_scope?
73
90
  @include == "scope"
74
91
  end
75
92
 
93
+ sig { returns(T::Hash[Symbol, String]) }
76
94
  def to_h
77
95
  {
78
96
  prefix: @prefix,
@@ -1,14 +1,23 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
4
5
  require "dependabot/version"
5
6
 
6
7
  module Dependabot
7
8
  class Dependency
8
- @production_checks = {}
9
- @display_name_builders = {}
10
- @name_normalisers = {}
9
+ extend T::Sig
11
10
 
11
+ @production_checks = T.let(
12
+ {},
13
+ T::Hash[String, T.proc.params(arg0: T::Array[T.untyped]).returns(T::Boolean)]
14
+ )
15
+ @display_name_builders = T.let({}, T::Hash[String, T.proc.params(arg0: String).returns(String)])
16
+ @name_normalisers = T.let({}, T::Hash[String, T.proc.params(arg0: String).returns(String)])
17
+
18
+ sig do
19
+ params(package_manager: String).returns(T.proc.params(arg0: T::Array[T.untyped]).returns(T::Boolean))
20
+ end
12
21
  def self.production_check_for_package_manager(package_manager)
13
22
  production_check = @production_checks[package_manager]
14
23
  return production_check if production_check
@@ -16,62 +25,128 @@ module Dependabot
16
25
  raise "Unsupported package_manager #{package_manager}"
17
26
  end
18
27
 
28
+ sig do
29
+ params(
30
+ package_manager: String,
31
+ production_check: T.proc.params(arg0: T::Array[T.untyped]).returns(T::Boolean)
32
+ )
33
+ .returns(T.proc.params(arg0: T::Array[T.untyped]).returns(T::Boolean))
34
+ end
19
35
  def self.register_production_check(package_manager, production_check)
20
36
  @production_checks[package_manager] = production_check
21
37
  end
22
38
 
39
+ sig { params(package_manager: String).returns(T.nilable(T.proc.params(arg0: String).returns(String))) }
23
40
  def self.display_name_builder_for_package_manager(package_manager)
24
41
  @display_name_builders[package_manager]
25
42
  end
26
43
 
44
+ sig { params(package_manager: String, name_builder: T.proc.params(arg0: String).returns(String)).void }
27
45
  def self.register_display_name_builder(package_manager, name_builder)
28
46
  @display_name_builders[package_manager] = name_builder
29
47
  end
30
48
 
49
+ sig { params(package_manager: String).returns(T.nilable(T.proc.params(arg0: String).returns(String))) }
31
50
  def self.name_normaliser_for_package_manager(package_manager)
32
51
  @name_normalisers[package_manager] || ->(name) { name }
33
52
  end
34
53
 
54
+ sig do
55
+ params(
56
+ package_manager: String,
57
+ name_builder: T.proc.params(arg0: String).returns(String)
58
+ ).void
59
+ end
35
60
  def self.register_name_normaliser(package_manager, name_builder)
36
61
  @name_normalisers[package_manager] = name_builder
37
62
  end
38
63
 
39
- attr_reader :name, :version, :requirements, :package_manager,
40
- :previous_version, :previous_requirements,
41
- :subdependency_metadata, :metadata
64
+ sig { returns(String) }
65
+ attr_reader :name
66
+
67
+ sig { returns(T.nilable(String)) }
68
+ attr_reader :version
69
+
70
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
71
+ attr_reader :requirements
72
+
73
+ sig { returns(String) }
74
+ attr_reader :package_manager
75
+
76
+ sig { returns(T.nilable(String)) }
77
+ attr_reader :previous_version
42
78
 
79
+ sig { returns(T.nilable(T::Array[T::Hash[Symbol, T.untyped]])) }
80
+ attr_reader :previous_requirements
81
+
82
+ sig { returns(T.nilable(T::Array[T::Hash[Symbol, T.untyped]])) }
83
+ attr_reader :subdependency_metadata
84
+
85
+ sig { returns(T::Hash[Symbol, T.untyped]) }
86
+ attr_reader :metadata
87
+
88
+ sig do
89
+ params(
90
+ name: String,
91
+ requirements: T::Array[T::Hash[String, String]],
92
+ package_manager: String,
93
+ # TODO: Make version a Dependabot::Version everywhere
94
+ version: T.nilable(T.any(String, Dependabot::Version)),
95
+ previous_version: T.nilable(String),
96
+ previous_requirements: T.nilable(T::Array[T::Hash[String, String]]),
97
+ subdependency_metadata: T.nilable(T::Array[T::Hash[String, String]]),
98
+ removed: T::Boolean,
99
+ metadata: T.nilable(T::Hash[String, String])
100
+ ).void
101
+ end
43
102
  def initialize(name:, requirements:, package_manager:, version: nil,
44
103
  previous_version: nil, previous_requirements: nil,
45
104
  subdependency_metadata: [], removed: false, metadata: {})
46
105
  @name = name
47
- @version = version
48
- @requirements = requirements.map { |req| symbolize_keys(req) }
106
+ @version = T.let(
107
+ case version
108
+ when Dependabot::Version then version.to_s
109
+ when String then version
110
+ end,
111
+ T.nilable(String)
112
+ )
113
+ @requirements = T.let(requirements.map { |req| symbolize_keys(req) }, T::Array[T::Hash[Symbol, String]])
49
114
  @previous_version = previous_version
50
- @previous_requirements =
51
- previous_requirements&.map { |req| symbolize_keys(req) }
115
+ @previous_requirements = T.let(
116
+ previous_requirements&.map { |req| symbolize_keys(req) },
117
+ T.nilable(T::Array[T::Hash[Symbol, T.untyped]])
118
+ )
52
119
  @package_manager = package_manager
53
120
  unless top_level? || subdependency_metadata == []
54
- @subdependency_metadata = subdependency_metadata
55
- &.map { |h| symbolize_keys(h) }
121
+ @subdependency_metadata = T.let(
122
+ subdependency_metadata&.map { |h| symbolize_keys(h) },
123
+ T.nilable(T::Array[T::Hash[Symbol, T.untyped]])
124
+ )
56
125
  end
57
126
  @removed = removed
58
- @metadata = symbolize_keys(metadata || {})
127
+ @metadata = T.let(symbolize_keys(metadata || {}), T::Hash[Symbol, T.untyped])
59
128
 
60
129
  check_values
61
130
  end
62
131
 
132
+ sig { returns(T::Boolean) }
63
133
  def top_level?
64
134
  requirements.any?
65
135
  end
66
136
 
137
+ sig { returns(T::Boolean) }
67
138
  def removed?
68
139
  @removed
69
140
  end
70
141
 
142
+ sig { returns(T.nilable(Dependabot::Version)) }
71
143
  def numeric_version
72
- @numeric_version ||= version_class.new(version) if version && version_class.correct?(version)
144
+ return unless version && version_class.correct?(version)
145
+
146
+ @numeric_version ||= T.let(version_class.new(version), T.nilable(Dependabot::Version))
73
147
  end
74
148
 
149
+ sig { returns(T::Hash[String, T.untyped]) }
75
150
  def to_h
76
151
  {
77
152
  "name" => name,
@@ -85,10 +160,12 @@ module Dependabot
85
160
  }.compact
86
161
  end
87
162
 
163
+ sig { returns(T::Boolean) }
88
164
  def appears_in_lockfile?
89
- previous_version || (version && previous_requirements.nil?)
165
+ !!(previous_version || (version && previous_requirements.nil?))
90
166
  end
91
167
 
168
+ sig { returns(T::Boolean) }
92
169
  def production?
93
170
  return subdependency_production_check unless top_level?
94
171
 
@@ -99,10 +176,12 @@ module Dependabot
99
176
  .call(groups)
100
177
  end
101
178
 
179
+ sig { returns(T::Boolean) }
102
180
  def subdependency_production_check
103
181
  !subdependency_metadata&.all? { |h| h[:production] == false }
104
182
  end
105
183
 
184
+ sig { returns(String) }
106
185
  def display_name
107
186
  display_name_builder =
108
187
  self.class.display_name_builder_for_package_manager(package_manager)
@@ -111,6 +190,7 @@ module Dependabot
111
190
  display_name_builder.call(name)
112
191
  end
113
192
 
193
+ sig { returns(T.nilable(String)) }
114
194
  def humanized_previous_version
115
195
  # If we don't have a previous version, we *may* still be able to figure
116
196
  # one out if a ref was provided and has been changed (in which case the
@@ -119,48 +199,52 @@ module Dependabot
119
199
  return ref_changed? ? previous_ref : nil
120
200
  end
121
201
 
122
- if previous_version.match?(/^[0-9a-f]{40}/)
202
+ if T.must(previous_version).match?(/^[0-9a-f]{40}/)
123
203
  return previous_ref if ref_changed? && previous_ref
124
204
 
125
- "`#{previous_version[0..6]}`"
205
+ "`#{T.must(previous_version)[0..6]}`"
126
206
  elsif version == previous_version &&
127
207
  package_manager == "docker"
128
- digest = docker_digest_from_reqs(previous_requirements)
129
- "`#{digest.split(':').last[0..6]}`"
208
+ digest = docker_digest_from_reqs(T.must(previous_requirements))
209
+ "`#{T.must(T.must(digest).split(':').last)[0..6]}`"
130
210
  else
131
211
  previous_version
132
212
  end
133
213
  end
134
214
 
215
+ sig { returns(T.nilable(String)) }
135
216
  def humanized_version
136
217
  return if removed?
137
218
 
138
- if version.match?(/^[0-9a-f]{40}/)
219
+ if T.must(version).match?(/^[0-9a-f]{40}/)
139
220
  return new_ref if ref_changed? && new_ref
140
221
 
141
- "`#{version[0..6]}`"
222
+ "`#{T.must(version)[0..6]}`"
142
223
  elsif version == previous_version &&
143
224
  package_manager == "docker"
144
225
  digest = docker_digest_from_reqs(requirements)
145
- "`#{digest.split(':').last[0..6]}`"
226
+ "`#{T.must(T.must(digest).split(':').last)[0..6]}`"
146
227
  else
147
228
  version
148
229
  end
149
230
  end
150
231
 
232
+ sig { params(requirements: T::Array[T::Hash[Symbol, T.untyped]]).returns(T.nilable(String)) }
151
233
  def docker_digest_from_reqs(requirements)
152
234
  requirements
153
235
  .filter_map { |r| r.dig(:source, "digest") || r.dig(:source, :digest) }
154
236
  .first
155
237
  end
156
238
 
239
+ sig { returns(T.nilable(String)) }
157
240
  def previous_ref
158
- previous_refs = previous_requirements.filter_map do |r|
241
+ previous_refs = T.must(previous_requirements).filter_map do |r|
159
242
  r.dig(:source, "ref") || r.dig(:source, :ref)
160
243
  end.uniq
161
244
  previous_refs.first if previous_refs.count == 1
162
245
  end
163
246
 
247
+ sig { returns(T.nilable(String)) }
164
248
  def new_ref
165
249
  new_refs = requirements.filter_map do |r|
166
250
  r.dig(:source, "ref") || r.dig(:source, :ref)
@@ -168,12 +252,14 @@ module Dependabot
168
252
  new_refs.first if new_refs.count == 1
169
253
  end
170
254
 
255
+ sig { returns(T::Boolean) }
171
256
  def ref_changed?
172
257
  previous_ref != new_ref
173
258
  end
174
259
 
175
260
  # Returns all detected versions of the dependency. Only ecosystems that
176
261
  # support this feature will return more than the current version.
262
+ sig { returns(T::Array[T.nilable(String)]) }
177
263
  def all_versions
178
264
  all_versions = metadata[:all_versions]
179
265
  return [version].compact unless all_versions
@@ -184,34 +270,52 @@ module Dependabot
184
270
  # This dependency is being indirectly updated by an update to another
185
271
  # dependency. We don't need to try and update it ourselves but want to
186
272
  # surface it to the user in the PR.
273
+ sig { returns(T.nilable(T::Boolean)) }
187
274
  def informational_only?
188
275
  metadata[:information_only]
189
276
  end
190
277
 
278
+ sig { params(other: T.anything).returns(T::Boolean) }
191
279
  def ==(other)
192
- other.instance_of?(self.class) && to_h == other.to_h
280
+ case other
281
+ when Dependency
282
+ to_h == other.to_h
283
+ else
284
+ false
285
+ end
193
286
  end
194
287
 
288
+ sig { returns(Integer) }
195
289
  def hash
196
290
  to_h.hash
197
291
  end
198
292
 
293
+ sig { params(other: T.anything).returns(T::Boolean) }
199
294
  def eql?(other)
200
295
  self == other
201
296
  end
202
297
 
298
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
203
299
  def specific_requirements
204
300
  requirements.select { |r| requirement_class.new(r[:requirement]).specific? }
205
301
  end
206
302
 
303
+ sig { returns(T.class_of(Gem::Requirement)) }
207
304
  def requirement_class
208
305
  Utils.requirement_class_for_package_manager(package_manager)
209
306
  end
210
307
 
308
+ sig { returns(T.class_of(Dependabot::Version)) }
211
309
  def version_class
212
310
  Utils.version_class_for_package_manager(package_manager)
213
311
  end
214
312
 
313
+ sig do
314
+ params(
315
+ allowed_types: T.nilable(T::Array[String])
316
+ )
317
+ .returns(T.nilable(T::Hash[T.any(String, Symbol), T.untyped]))
318
+ end
215
319
  def source_details(allowed_types: nil)
216
320
  sources = all_sources.uniq.compact
217
321
  sources.select! { |source| allowed_types.include?(source[:type].to_s) } if allowed_types
@@ -225,6 +329,7 @@ module Dependabot
225
329
  sources.first
226
330
  end
227
331
 
332
+ sig { returns(T.nilable(String)) }
228
333
  def source_type
229
334
  details = source_details
230
335
  return "default" if details.nil?
@@ -232,11 +337,12 @@ module Dependabot
232
337
  details[:type] || details.fetch("type")
233
338
  end
234
339
 
340
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
235
341
  def all_sources
236
342
  if top_level?
237
343
  requirements.map { |requirement| requirement.fetch(:source) }
238
344
  elsif subdependency_metadata
239
- subdependency_metadata.filter_map { |data| data[:source] }
345
+ T.must(subdependency_metadata).filter_map { |data| data[:source] }
240
346
  else
241
347
  []
242
348
  end
@@ -244,6 +350,7 @@ module Dependabot
244
350
 
245
351
  private
246
352
 
353
+ sig { void }
247
354
  def check_values
248
355
  raise ArgumentError, "blank strings must not be provided as versions" if [version, previous_version].any?("")
249
356
 
@@ -251,6 +358,7 @@ module Dependabot
251
358
  check_subdependency_metadata
252
359
  end
253
360
 
361
+ sig { void }
254
362
  def check_requirement_fields
255
363
  requirement_fields = [requirements, previous_requirements].compact
256
364
  unless requirement_fields.all?(Array) &&
@@ -273,15 +381,17 @@ module Dependabot
273
381
  raise ArgumentError, "blank strings must not be provided as requirements"
274
382
  end
275
383
 
384
+ sig { void }
276
385
  def check_subdependency_metadata
277
386
  return unless subdependency_metadata
278
387
 
279
388
  unless subdependency_metadata.is_a?(Array) &&
280
- subdependency_metadata.all?(Hash)
389
+ T.must(subdependency_metadata).all?(Hash)
281
390
  raise ArgumentError, "subdependency_metadata must be an array of hashes"
282
391
  end
283
392
  end
284
393
 
394
+ sig { params(hash: T::Hash[String, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
285
395
  def symbolize_keys(hash)
286
396
  hash.keys.to_h { |k| [k.to_sym, hash[k]] }
287
397
  end