dependabot-terraform 0.275.0 → 0.277.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cbb275a531475285a18eaa11ebd12714cdc8779a5875bdc9d63815005e48a76a
4
- data.tar.gz: 69b974fdd88b965452bc475e5a88d4231fc00aa4c7be2c26df99eeffbd9832c3
3
+ metadata.gz: ebe92edc7ae776761d9ddb633672c9ff260d86b40dd845c08307d7f30a4315c1
4
+ data.tar.gz: 1fb3fb264832e08f580e40157f3fac8e3de388bc700991cd2184b2ef3de0c025
5
5
  SHA512:
6
- metadata.gz: 0ef3cdef01fb6a4b8f3aa02d9d8acf437dccbcc7001a3afb47de05b32bb41923d8f0308fa53f3108c4e8ffd8003f73d00cc345f6b6c6027bf7e0e0e095e5c76a
7
- data.tar.gz: bf6c50b10f52d0a5775eda42eb6b7d867fbbaa819a24f94616cec06f3e199ac531634874d03cb2e3d12dbeb9bec6139e4fedce96fb20e5d3946adbcd5d85f383
6
+ metadata.gz: d0a06b41820076bf571c81d4bda05b0fac400e6853ab1264042cf425585c01c984eb1c4467fd0fbc9bf232afea18026cda47349fd9ede280693aa9cbd9e27da7
7
+ data.tar.gz: c885814bd5b0ddd9bd858b9d1e0eec2491ec45711e76a8f41c8955ff316e9b0a39b76db33b8b15a68d5ee1756e8d31a31844b04bd7c6e764efa9a9efa12499f9
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "cgi"
@@ -30,6 +30,7 @@ module Dependabot
30
30
  # https://www.terraform.io/docs/language/providers/requirements.html#source-addresses
31
31
  PROVIDER_SOURCE_ADDRESS = %r{\A((?<hostname>.+)/)?(?<namespace>.+)/(?<name>.+)\z}
32
32
 
33
+ sig { override.returns(T::Array[Dependabot::Dependency]) }
33
34
  def parse
34
35
  dependency_set = DependencySet.new
35
36
 
@@ -42,6 +43,7 @@ module Dependabot
42
43
 
43
44
  private
44
45
 
46
+ sig { params(dependency_set: Dependabot::FileParsers::Base::DependencySet).void }
45
47
  def parse_terraform_files(dependency_set)
46
48
  terraform_files.each do |file|
47
49
  modules = parsed_file(file).fetch("module", {})
@@ -50,9 +52,9 @@ module Dependabot
50
52
 
51
53
  source = source_from(details)
52
54
  # Cannot update local path modules, skip
53
- next if source[:type] == "path"
55
+ next if source && source[:type] == "path"
54
56
 
55
- dependency_set << build_terraform_dependency(file, name, source, details)
57
+ dependency_set << build_terraform_dependency(file, name, T.must(source), details)
56
58
  end
57
59
 
58
60
  parsed_file(file).fetch("terraform", []).each do |terraform|
@@ -66,6 +68,7 @@ module Dependabot
66
68
  end
67
69
  end
68
70
 
71
+ sig { params(dependency_set: Dependabot::FileParsers::Base::DependencySet).void }
69
72
  def parse_terragrunt_files(dependency_set)
70
73
  terragrunt_files.each do |file|
71
74
  modules = parsed_file(file).fetch("terraform", [])
@@ -81,6 +84,15 @@ module Dependabot
81
84
  end
82
85
  end
83
86
 
87
+ sig do
88
+ params(
89
+ file: Dependabot::DependencyFile,
90
+ name: String,
91
+ source: T::Hash[Symbol, T.untyped],
92
+ details: T.untyped
93
+ )
94
+ .returns(Dependabot::Dependency)
95
+ end
84
96
  def build_terraform_dependency(file, name, source, details)
85
97
  # dep_name should be unique for a source, using the info derived from
86
98
  # the source or the source name provides this uniqueness
@@ -109,17 +121,25 @@ module Dependabot
109
121
  )
110
122
  end
111
123
 
124
+ sig do
125
+ params(
126
+ file: Dependabot::DependencyFile,
127
+ name: String,
128
+ details: T.any(String, T::Hash[String, T.untyped])
129
+ )
130
+ .returns(Dependabot::Dependency)
131
+ end
112
132
  def build_provider_dependency(file, name, details = {})
113
133
  deprecated_provider_error(file) if deprecated_provider?(details)
114
134
 
115
- source_address = details.fetch("source", nil)
135
+ source_address = T.cast(details, T::Hash[String, T.untyped]).fetch("source", nil)
116
136
  version_req = details["version"]&.strip
117
137
  hostname, namespace, name = provider_source_from(source_address, name)
118
138
  dependency_name = source_address ? "#{namespace}/#{name}" : name
119
139
 
120
140
  Dependency.new(
121
- name: dependency_name,
122
- version: determine_version_for(hostname, namespace, name, version_req),
141
+ name: T.must(dependency_name),
142
+ version: determine_version_for(T.must(hostname), T.must(namespace), T.must(name), version_req),
123
143
  package_manager: "terraform",
124
144
  requirements: [
125
145
  requirement: version_req,
@@ -134,6 +154,7 @@ module Dependabot
134
154
  )
135
155
  end
136
156
 
157
+ sig { params(file: Dependabot::DependencyFile).returns(T.noreturn) }
137
158
  def deprecated_provider_error(file)
138
159
  raise Dependabot::DependencyFileNotParseable.new(
139
160
  file.path,
@@ -143,18 +164,20 @@ module Dependabot
143
164
  )
144
165
  end
145
166
 
167
+ sig { params(details: Object).returns(T::Boolean) }
146
168
  def deprecated_provider?(details)
147
169
  # The old syntax for terraform providers v0.12- looked like
148
170
  # "tls ~> 2.1" which gets parsed as a string instead of a hash
149
171
  details.is_a?(String)
150
172
  end
151
173
 
174
+ sig { params(file: Dependabot::DependencyFile, source: T::Hash[Symbol, String]).returns(Dependabot::Dependency) }
152
175
  def build_terragrunt_dependency(file, source)
153
176
  dep_name = Source.from_url(source[:url]) ? T.must(Source.from_url(source[:url])).repo : source[:url]
154
177
  version = version_from_ref(source[:ref])
155
178
 
156
179
  Dependency.new(
157
- name: dep_name,
180
+ name: T.must(dep_name),
158
181
  version: version,
159
182
  package_manager: "terraform",
160
183
  requirements: [
@@ -167,6 +190,7 @@ module Dependabot
167
190
  end
168
191
 
169
192
  # Full docs at https://www.terraform.io/docs/modules/sources.html
193
+ sig { params(details_hash: T::Hash[String, String]).returns(T.nilable(T::Hash[Symbol, T.untyped])) }
170
194
  def source_from(details_hash)
171
195
  raw_source = details_hash.fetch("source")
172
196
  bare_source = RegistryClient.get_proxied_source(raw_source)
@@ -183,10 +207,11 @@ module Dependabot
183
207
  return nil
184
208
  end
185
209
 
186
- source_details[:proxy_url] = raw_source if raw_source != bare_source
210
+ T.must(source_details)[:proxy_url] = raw_source if raw_source != bare_source
187
211
  source_details
188
212
  end
189
213
 
214
+ sig { params(source_address: T.nilable(String), name: String).returns(T::Array[String]) }
190
215
  def provider_source_from(source_address, name)
191
216
  matches = source_address&.match(PROVIDER_SOURCE_ADDRESS)
192
217
  matches = {} if matches.nil?
@@ -198,6 +223,7 @@ module Dependabot
198
223
  ]
199
224
  end
200
225
 
226
+ sig { params(source_string: T.untyped).returns(T::Hash[Symbol, String]) }
201
227
  def registry_source_details_from(source_string)
202
228
  parts = source_string.split("//").first.split("/")
203
229
 
@@ -219,6 +245,7 @@ module Dependabot
219
245
  end
220
246
  end
221
247
 
248
+ sig { params(name: String, source: T::Hash[Symbol, T.untyped]).returns(String) }
222
249
  def git_dependency_name(name, source)
223
250
  git_source = Source.from_url(source[:url])
224
251
  if git_source && source[:ref]
@@ -233,13 +260,14 @@ module Dependabot
233
260
  end
234
261
  end
235
262
 
263
+ sig { params(source_string: String).returns(T::Hash[Symbol, T.nilable(String)]) }
236
264
  def git_source_details_from(source_string)
237
265
  git_url = source_string.strip.gsub(/^git::/, "")
238
266
  git_url = "https://" + git_url unless git_url.start_with?("git@") || git_url.include?("://")
239
267
 
240
268
  bare_uri =
241
269
  if git_url.include?("git@")
242
- git_url.split("git@").last.sub(":", "/")
270
+ T.must(git_url.split("git@").last).sub(":", "/")
243
271
  else
244
272
  git_url.sub(%r{.*?://}, "")
245
273
  end
@@ -255,14 +283,16 @@ module Dependabot
255
283
  }
256
284
  end
257
285
 
286
+ sig { params(ref: T.nilable(String)).returns(T.nilable(String)) }
258
287
  def version_from_ref(ref)
259
288
  version_regex = GitCommitChecker::VERSION_REGEX
260
289
  return unless ref&.match?(version_regex)
261
290
 
262
- ref.match(version_regex).named_captures.fetch("version")
291
+ ref.match(version_regex)&.named_captures&.fetch("version")
263
292
  end
264
293
 
265
294
  # rubocop:disable Metrics/PerceivedComplexity
295
+ sig { params(source_string: String).returns(Symbol) }
266
296
  def source_type(source_string)
267
297
  return :interpolation if source_string.include?("${")
268
298
  return :path if source_string.start_with?(".")
@@ -272,11 +302,11 @@ module Dependabot
272
302
  return :mercurial if source_string.start_with?("hg::")
273
303
  return :s3 if source_string.start_with?("s3::")
274
304
 
275
- raise "Unknown src: #{source_string}" if source_string.split("/").first.include?("::")
305
+ raise "Unknown src: #{source_string}" if source_string.split("/").first&.include?("::")
276
306
 
277
307
  return :registry unless source_string.start_with?("http")
278
308
 
279
- path_uri = URI.parse(source_string.split(%r{(?<!:)//}).first)
309
+ path_uri = URI.parse(T.must(source_string.split(%r{(?<!:)//}).first))
280
310
  query_uri = URI.parse(source_string)
281
311
  return :http_archive if path_uri.path.end_with?(*RegistryClient::ARCHIVE_EXTENSIONS)
282
312
  return :http_archive if query_uri.query&.include?("archive=")
@@ -307,8 +337,9 @@ module Dependabot
307
337
  # }
308
338
  # ],
309
339
  # }
340
+ sig { params(file: Dependabot::DependencyFile).returns(T::Hash[String, T.untyped]) }
310
341
  def parsed_file(file)
311
- @parsed_buildfile ||= {}
342
+ @parsed_buildfile ||= T.let({}, T.nilable(T::Hash[String, T.untyped]))
312
343
  @parsed_buildfile[file.name] ||= SharedHelpers.in_a_temporary_directory do
313
344
  File.write("tmp.tf", file.content)
314
345
 
@@ -335,27 +366,40 @@ module Dependabot
335
366
  raise Dependabot::DependencyFileNotParseable.new(file.path, msg)
336
367
  end
337
368
 
369
+ sig { returns(String) }
338
370
  def terraform_parser_path
339
371
  helper_bin_dir = File.join(native_helpers_root, "terraform/bin")
340
372
  Pathname.new(File.join(helper_bin_dir, "json2hcl")).cleanpath.to_path
341
373
  end
342
374
 
375
+ sig { returns(String) }
343
376
  def terraform_hcl2_parser_path
344
377
  helper_bin_dir = File.join(native_helpers_root, "terraform/bin")
345
378
  Pathname.new(File.join(helper_bin_dir, "hcl2json")).cleanpath.to_path
346
379
  end
347
380
 
381
+ sig { returns(String) }
348
382
  def native_helpers_root
349
383
  default_path = File.join(__dir__, "../../../helpers/install-dir")
350
384
  ENV.fetch("DEPENDABOT_NATIVE_HELPERS_PATH", default_path)
351
385
  end
352
386
 
387
+ sig { override.void }
353
388
  def check_required_files
354
389
  return if [*terraform_files, *terragrunt_files].any?
355
390
 
356
391
  raise "No Terraform configuration file!"
357
392
  end
358
393
 
394
+ sig do
395
+ params(
396
+ hostname: String,
397
+ namespace: String,
398
+ name: String,
399
+ constraint: T.nilable(String)
400
+ )
401
+ .returns(T.nilable(String))
402
+ end
359
403
  def determine_version_for(hostname, namespace, name, constraint)
360
404
  return constraint if constraint&.match?(/\A\d/)
361
405
 
@@ -363,14 +407,17 @@ module Dependabot
363
407
  .dig("provider", "#{hostname}/#{namespace}/#{name}", 0, "version")
364
408
  end
365
409
 
410
+ sig { returns(T::Hash[String, T.untyped]) }
366
411
  def lockfile_content
367
- @lockfile_content ||=
412
+ @lockfile_content ||= T.let(
368
413
  begin
369
414
  lockfile = dependency_files.find do |file|
370
415
  file.name == ".terraform.lock.hcl"
371
416
  end
372
417
  lockfile ? parsed_file(lockfile) : {}
373
- end
418
+ end,
419
+ T.nilable(T::Hash[String, T.untyped])
420
+ )
374
421
  end
375
422
  end
376
423
  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://www.terraform.io/docs/modules/usage.html#module-versions #
7
7
  ####################################################################
8
8
 
9
+ require "sorbet-runtime"
10
+
9
11
  require "dependabot/terraform/version"
10
12
  require "dependabot/terraform/requirement"
11
13
 
@@ -46,9 +48,18 @@ module Dependabot
46
48
  # }
47
49
  # }
48
50
  class RequirementsUpdater
51
+ extend T::Sig
52
+
49
53
  # @param requirements [Hash{Symbol => String, Array, Hash}]
50
54
  # @param latest_version [Dependabot::Terraform::Version]
51
55
  # @param tag_for_latest_version [String, NilClass]
56
+ sig do
57
+ params(
58
+ requirements: T::Array[T::Hash[Symbol, T.untyped]],
59
+ latest_version: T.nilable(Dependabot::Version::VersionParameter),
60
+ tag_for_latest_version: T.nilable(String)
61
+ ).void
62
+ end
52
63
  def initialize(requirements:, latest_version:, tag_for_latest_version:)
53
64
  @requirements = requirements
54
65
  @tag_for_latest_version = tag_for_latest_version
@@ -56,7 +67,7 @@ module Dependabot
56
67
  return unless latest_version
57
68
  return unless version_class.correct?(latest_version)
58
69
 
59
- @latest_version = version_class.new(latest_version)
70
+ @latest_version = T.let(version_class.new(latest_version), Dependabot::Terraform::Version)
60
71
  end
61
72
 
62
73
  # @return requirements [Hash{Symbol => String, Array, Hash}]
@@ -64,9 +75,8 @@ module Dependabot
64
75
  # * groups [Array] no-op for terraform
65
76
  # * file [String] the file that specified this dependency
66
77
  # * source [Hash{Symbol => String}] The updated git or registry source details
78
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
67
79
  def updated_requirements
68
- return requirements unless latest_version
69
-
70
80
  # NOTE: Order is important here. The FileUpdater needs the updated
71
81
  # requirement at index `i` to correspond to the previous requirement
72
82
  # at the same index.
@@ -81,10 +91,16 @@ module Dependabot
81
91
 
82
92
  private
83
93
 
94
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
84
95
  attr_reader :requirements
96
+
97
+ sig { returns(Dependabot::Terraform::Version) }
85
98
  attr_reader :latest_version
99
+
100
+ sig { returns(T.nilable(String)) }
86
101
  attr_reader :tag_for_latest_version
87
102
 
103
+ sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
88
104
  def update_git_requirement(req)
89
105
  return req unless req.dig(:source, :ref)
90
106
  return req unless tag_for_latest_version
@@ -92,6 +108,7 @@ module Dependabot
92
108
  req.merge(source: req[:source].merge(ref: tag_for_latest_version))
93
109
  end
94
110
 
111
+ sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
95
112
  def update_registry_requirement(req)
96
113
  return req if req.fetch(:requirement).nil?
97
114
 
@@ -111,6 +128,7 @@ module Dependabot
111
128
  end
112
129
 
113
130
  # Updates the version in a "~>" constraint to allow the given version
131
+ sig { params(req_string: String).returns(String) }
114
132
  def update_twiddle_version(req_string)
115
133
  old_version = requirement_class.new(req_string)
116
134
  .requirements.first.last
@@ -118,6 +136,7 @@ module Dependabot
118
136
  req_string.sub(old_version.to_s, updated_version)
119
137
  end
120
138
 
139
+ sig { params(req_string: String).returns(T::Array[Dependabot::Terraform::Requirement]) }
121
140
  def update_range(req_string)
122
141
  requirement_class.new(req_string).requirements.flat_map do |r|
123
142
  ruby_req = requirement_class.new(r.join(" "))
@@ -131,6 +150,13 @@ module Dependabot
131
150
  end
132
151
  end
133
152
 
153
+ sig do
154
+ params(
155
+ new_version: Dependabot::Terraform::Version,
156
+ old_version: Dependabot::Terraform::Version
157
+ )
158
+ .returns(String)
159
+ end
134
160
  def at_same_precision(new_version, old_version)
135
161
  release_precision =
136
162
  old_version.to_s.split(".").count { |i| i.match?(/^\d+$/) }
@@ -149,6 +175,13 @@ module Dependabot
149
175
 
150
176
  # Updates the version in a "<" or "<=" constraint to allow the given
151
177
  # version
178
+ sig do
179
+ params(
180
+ requirement: Dependabot::Requirement,
181
+ version_to_be_permitted: T.any(String, Dependabot::Terraform::Version)
182
+ )
183
+ .returns(Dependabot::Terraform::Requirement)
184
+ end
152
185
  def update_greatest_version(requirement, version_to_be_permitted)
153
186
  if version_to_be_permitted.is_a?(String)
154
187
  version_to_be_permitted =
@@ -164,7 +197,7 @@ module Dependabot
164
197
  if index < index_to_update
165
198
  version_to_be_permitted.segments[index]
166
199
  elsif index == index_to_update
167
- version_to_be_permitted.segments[index] + 1
200
+ version_to_be_permitted.segments[index].to_i + 1
168
201
  else
169
202
  0
170
203
  end
@@ -173,10 +206,12 @@ module Dependabot
173
206
  requirement_class.new("#{op} #{new_segments.join('.')}")
174
207
  end
175
208
 
209
+ sig { returns(T.class_of(Dependabot::Terraform::Version)) }
176
210
  def version_class
177
211
  Version
178
212
  end
179
213
 
214
+ sig { returns(T.class_of(Dependabot::Terraform::Requirement)) }
180
215
  def requirement_class
181
216
  Requirement
182
217
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-terraform
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.275.0
4
+ version: 0.277.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-12 00:00:00.000000000 Z
11
+ date: 2024-09-23 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.275.0
19
+ version: 0.277.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.275.0
26
+ version: 0.277.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: debug
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -260,7 +260,7 @@ licenses:
260
260
  - MIT
261
261
  metadata:
262
262
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
263
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.275.0
263
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.277.0
264
264
  post_install_message:
265
265
  rdoc_options: []
266
266
  require_paths: