dependabot-opentofu 0.385.0 → 0.387.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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2bc33535e90295dc9a6701b45db149a1d6b91c5771a1c6905a76be6568324c7f
|
|
4
|
+
data.tar.gz: e9dbb471d8b1f931cc073167deef98a03edc4be1f12aebb71cbcec511fff895c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 22cef6dcf34daa9849d66cd54fbf87c6fc1c046f58396ce0ec308515776ca5478c9c7b8066f69c10fcee428bebe17cff9d61a41fc9f16c090fa9bc564717619f
|
|
7
|
+
data.tar.gz: a2290ea710a8bf2fbbb0ed18ff55c7b4c9fc56adaea9a6e7f89485b8b16c7f598e1be4684ca8625b9a34faa58b3c2c58f6ba2199c1203f7b8ab9ec6a547066b0
|
|
@@ -52,14 +52,14 @@ module Dependabot
|
|
|
52
52
|
|
|
53
53
|
sig do
|
|
54
54
|
params(
|
|
55
|
-
modules: T::Hash[String, T::Array[T::Hash[String,
|
|
55
|
+
modules: T::Hash[String, T::Array[T::Hash[String, Object]]],
|
|
56
56
|
base_modules: T::Hash[String,
|
|
57
57
|
T::Array[T::Hash[String,
|
|
58
|
-
|
|
58
|
+
Object]]]
|
|
59
59
|
)
|
|
60
60
|
.returns(T::Hash[String,
|
|
61
61
|
T::Array[T::Hash[String,
|
|
62
|
-
|
|
62
|
+
Object]]])
|
|
63
63
|
end
|
|
64
64
|
def merge_modules(modules, base_modules)
|
|
65
65
|
merged_modules = base_modules.dup
|
|
@@ -7,11 +7,12 @@ require "dependabot/file_updaters"
|
|
|
7
7
|
require "dependabot/file_updaters/base"
|
|
8
8
|
require "dependabot/errors"
|
|
9
9
|
require "dependabot/opentofu/file_selector"
|
|
10
|
+
require "dependabot/opentofu/registry_client"
|
|
10
11
|
require "dependabot/shared_helpers"
|
|
11
12
|
|
|
12
13
|
module Dependabot
|
|
13
14
|
module Opentofu
|
|
14
|
-
class FileUpdater < Dependabot::FileUpdaters::Base
|
|
15
|
+
class FileUpdater < Dependabot::FileUpdaters::Base # rubocop:disable Metrics/ClassLength
|
|
15
16
|
extend T::Sig
|
|
16
17
|
|
|
17
18
|
include FileSelector
|
|
@@ -234,17 +235,52 @@ module Dependabot
|
|
|
234
235
|
end
|
|
235
236
|
|
|
236
237
|
sig { returns(T.nilable(T::Array[Symbol])) }
|
|
237
|
-
def lookup_hash_architecture
|
|
238
|
+
def lookup_hash_architecture
|
|
238
239
|
new_req = T.must(dependency.requirements.first)
|
|
239
240
|
|
|
240
241
|
# NOTE: Only providers are included in the lockfile, modules are not
|
|
241
242
|
return unless new_req[:source][:type] == "provider"
|
|
242
243
|
|
|
244
|
+
result = lookup_hash_architecture_from_registry(new_req)
|
|
245
|
+
return result if result
|
|
246
|
+
|
|
247
|
+
lookup_hash_architecture_from_cli(new_req)
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
sig { params(new_req: T::Hash[Symbol, T.untyped]).returns(T.nilable(T::Array[Symbol])) }
|
|
251
|
+
def lookup_hash_architecture_from_registry(new_req) # rubocop:disable Metrics/PerceivedComplexity
|
|
252
|
+
content, _provider_source, declaration_regex = lockfile_details(new_req)
|
|
253
|
+
existing_h1 = extract_provider_h1_hashes(content, declaration_regex)
|
|
254
|
+
return nil if existing_h1.empty?
|
|
255
|
+
|
|
256
|
+
identifier = new_req[:source][:module_identifier]
|
|
257
|
+
old_version = dependency.previous_version
|
|
258
|
+
return nil unless old_version
|
|
259
|
+
|
|
260
|
+
hostname = new_req[:source][:registry_hostname] || RegistryClient::PUBLIC_HOSTNAME
|
|
261
|
+
client = RegistryClient.new(hostname: hostname, credentials: credentials)
|
|
262
|
+
packages = client.all_provider_package_hashes(identifier: identifier, version: old_version)
|
|
263
|
+
return nil unless packages
|
|
264
|
+
|
|
265
|
+
h1_to_platform = {}
|
|
266
|
+
packages.each do |platform, hashes|
|
|
267
|
+
hashes.each do |h|
|
|
268
|
+
h1_to_platform[h] = platform if h.start_with?("h1:")
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
architectures = existing_h1.filter_map { |h| h1_to_platform[h]&.to_sym }
|
|
273
|
+
architectures.empty? ? nil : architectures.uniq
|
|
274
|
+
rescue Dependabot::DependabotError
|
|
275
|
+
nil
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
sig { params(new_req: T::Hash[Symbol, T.untyped]).returns(T::Array[Symbol]) }
|
|
279
|
+
def lookup_hash_architecture_from_cli(new_req) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
243
280
|
architectures = []
|
|
244
281
|
content, provider_source, declaration_regex = lockfile_details(new_req)
|
|
245
282
|
hashes = extract_provider_h1_hashes(content, declaration_regex)
|
|
246
283
|
|
|
247
|
-
# These are ordered in assumed popularity
|
|
248
284
|
possible_architectures = %w(
|
|
249
285
|
linux_amd64
|
|
250
286
|
darwin_amd64
|
|
@@ -256,15 +292,10 @@ module Dependabot
|
|
|
256
292
|
base_dir = T.must(dependency_files.first).directory
|
|
257
293
|
lockfile_hash_removed = remove_provider_h1_hashes(content, declaration_regex)
|
|
258
294
|
|
|
259
|
-
# This runs in the same directory as the actual lockfile update so
|
|
260
|
-
# the platform must be determined before the updated manifest files
|
|
261
|
-
# are written to disk
|
|
262
295
|
SharedHelpers.in_a_temporary_repo_directory(base_dir, repo_contents_path) do
|
|
263
296
|
possible_architectures.each do |arch|
|
|
264
|
-
# Exit early if we have detected all of the architectures present
|
|
265
297
|
break if architectures.count == hashes.count
|
|
266
298
|
|
|
267
|
-
# OpenTofu will update the lockfile in place so we use a fresh lockfile for each lookup
|
|
268
299
|
File.write(".terraform.lock.hcl", lockfile_hash_removed)
|
|
269
300
|
|
|
270
301
|
SharedHelpers.run_shell_command(
|
|
@@ -276,7 +307,6 @@ module Dependabot
|
|
|
276
307
|
updated_hashes = extract_provider_h1_hashes(updated_lockfile, declaration_regex)
|
|
277
308
|
next if updated_hashes.nil?
|
|
278
309
|
|
|
279
|
-
# Check if the architecture is present in the original lockfile
|
|
280
310
|
hashes.each do |hash|
|
|
281
311
|
updated_hashes.select { |h| h.match?(/^h1:/) }.each do |updated_hash|
|
|
282
312
|
architectures.append(arch.to_sym) if hash == updated_hash
|
|
@@ -292,7 +322,6 @@ module Dependabot
|
|
|
292
322
|
end
|
|
293
323
|
raise if @retrying_lock || !e.message.include?("tofu init")
|
|
294
324
|
|
|
295
|
-
# NOTE: Modules need to be installed before OpenTofu can update the lockfile
|
|
296
325
|
@retrying_lock = true
|
|
297
326
|
run_opentofu_init
|
|
298
327
|
retry
|
|
@@ -304,32 +333,117 @@ module Dependabot
|
|
|
304
333
|
sig { returns(T::Array[Symbol]) }
|
|
305
334
|
def architecture_type
|
|
306
335
|
@architecture_type ||= T.let(
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
T.must(lookup_hash_architecture)
|
|
336
|
+
begin
|
|
337
|
+
detected = lookup_hash_architecture
|
|
338
|
+
detected.nil? || detected.empty? ? [:linux_amd64] : detected
|
|
311
339
|
end,
|
|
312
340
|
T.nilable(T::Array[Symbol])
|
|
313
341
|
)
|
|
314
342
|
end
|
|
315
343
|
|
|
316
344
|
sig { params(updated_manifest_files: T::Array[Dependabot::DependencyFile]).returns(T.nilable(String)) }
|
|
317
|
-
def update_lockfile_declaration(updated_manifest_files)
|
|
345
|
+
def update_lockfile_declaration(updated_manifest_files)
|
|
318
346
|
return if lockfile.nil?
|
|
319
347
|
|
|
320
348
|
new_req = T.must(dependency.requirements.first)
|
|
321
|
-
# NOTE: Only providers are included in the lockfile, modules are not
|
|
322
349
|
return unless new_req[:source][:type] == "provider"
|
|
323
350
|
|
|
351
|
+
result = update_lockfile_from_registry(new_req)
|
|
352
|
+
return result if result
|
|
353
|
+
|
|
354
|
+
update_lockfile_from_cli(new_req, updated_manifest_files)
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
sig { params(new_req: T::Hash[Symbol, T.untyped]).returns(T.nilable(String)) }
|
|
358
|
+
def update_lockfile_from_registry(new_req) # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
|
|
359
|
+
content, provider_source, declaration_regex = lockfile_details(new_req)
|
|
360
|
+
platforms = architecture_type
|
|
361
|
+
return nil if platforms.empty?
|
|
362
|
+
|
|
363
|
+
identifier = new_req[:source][:module_identifier]
|
|
364
|
+
new_version = dependency.version
|
|
365
|
+
return nil unless new_version
|
|
366
|
+
|
|
367
|
+
hostname = new_req[:source][:registry_hostname] || RegistryClient::PUBLIC_HOSTNAME
|
|
368
|
+
client = RegistryClient.new(hostname: hostname, credentials: credentials)
|
|
369
|
+
packages = client.all_provider_package_hashes(identifier: identifier, version: new_version)
|
|
370
|
+
return nil unless packages
|
|
371
|
+
|
|
372
|
+
platform_strings = platforms.map(&:to_s)
|
|
373
|
+
return nil unless platform_strings.all? { |p| packages.key?(p) }
|
|
374
|
+
|
|
375
|
+
h1_hashes = platform_strings.flat_map { |p| packages.fetch(p).select { |h| h.start_with?("h1:") } }.uniq.sort
|
|
376
|
+
zh_hashes = packages.values.flat_map { |hs| hs.select { |h| h.start_with?("zh:") } }.uniq.sort
|
|
377
|
+
all_hashes = h1_hashes + zh_hashes
|
|
378
|
+
return nil if all_hashes.empty?
|
|
379
|
+
|
|
380
|
+
new_declaration = build_lockfile_declaration(
|
|
381
|
+
provider_source: provider_source,
|
|
382
|
+
version: new_version,
|
|
383
|
+
constraints: extract_constraints(content, declaration_regex),
|
|
384
|
+
hashes: all_hashes
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
replace_lockfile_provider_block(content, declaration_regex, new_declaration)
|
|
388
|
+
rescue Dependabot::DependabotError
|
|
389
|
+
nil
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
sig do
|
|
393
|
+
params(
|
|
394
|
+
provider_source: String,
|
|
395
|
+
version: String,
|
|
396
|
+
constraints: T.nilable(String),
|
|
397
|
+
hashes: T::Array[String]
|
|
398
|
+
).returns(String)
|
|
399
|
+
end
|
|
400
|
+
def build_lockfile_declaration(provider_source:, version:, constraints:, hashes:)
|
|
401
|
+
lines = []
|
|
402
|
+
lines << "provider \"#{provider_source}\" {"
|
|
403
|
+
if constraints
|
|
404
|
+
lines << " version = \"#{version}\""
|
|
405
|
+
lines << " constraints = \"#{constraints}\""
|
|
406
|
+
else
|
|
407
|
+
lines << " version = \"#{version}\""
|
|
408
|
+
end
|
|
409
|
+
lines << " hashes = ["
|
|
410
|
+
hashes.each { |h| lines << " \"#{h}\"," }
|
|
411
|
+
lines << " ]"
|
|
412
|
+
lines << "}"
|
|
413
|
+
lines.join("\n")
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
sig { params(content: String, declaration_regex: Regexp, new_declaration: String).returns(String) }
|
|
417
|
+
def replace_lockfile_provider_block(content, declaration_regex, new_declaration)
|
|
418
|
+
provider_block_regex = /provider\s*["'][^"']+["']\s*\{[^}]*\}/m
|
|
419
|
+
content.sub(declaration_regex) do |match|
|
|
420
|
+
match.sub(provider_block_regex, new_declaration)
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
sig { params(content: String, declaration_regex: Regexp).returns(T.nilable(String)) }
|
|
425
|
+
def extract_constraints(content, declaration_regex)
|
|
426
|
+
match = content.match(declaration_regex)
|
|
427
|
+
return nil unless match
|
|
428
|
+
|
|
429
|
+
constraint_match = match.to_s.match(/^\s*constraints\s*=\s*"([^"]*)"/)
|
|
430
|
+
constraint_match ? constraint_match[1] : nil
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
sig do
|
|
434
|
+
params(
|
|
435
|
+
new_req: T::Hash[Symbol, T.untyped],
|
|
436
|
+
updated_manifest_files: T::Array[Dependabot::DependencyFile]
|
|
437
|
+
).returns(T.nilable(String))
|
|
438
|
+
end
|
|
439
|
+
def update_lockfile_from_cli(new_req, updated_manifest_files) # rubocop:disable Metrics/AbcSize
|
|
324
440
|
content, provider_source, declaration_regex = lockfile_details(new_req)
|
|
325
441
|
lockfile_dependency_removed = content.sub(declaration_regex, "")
|
|
326
442
|
|
|
327
443
|
base_dir = T.must(dependency_files.first).directory
|
|
328
444
|
SharedHelpers.in_a_temporary_repo_directory(base_dir, repo_contents_path) do
|
|
329
|
-
# Determine the provider using the original manifest files
|
|
330
445
|
platforms = architecture_type.map { |arch| "-platform=#{arch}" }.join(" ")
|
|
331
446
|
|
|
332
|
-
# Update the provider requirements in case the previous requirement doesn't allow the new version
|
|
333
447
|
updated_manifest_files.each { |f| File.write(f.name, f.content) }
|
|
334
448
|
|
|
335
449
|
File.write(".terraform.lock.hcl", lockfile_dependency_removed)
|
|
@@ -342,8 +456,6 @@ module Dependabot
|
|
|
342
456
|
updated_lockfile = File.read(".terraform.lock.hcl")
|
|
343
457
|
updated_dependency = T.cast(updated_lockfile.scan(declaration_regex).first, String)
|
|
344
458
|
|
|
345
|
-
# OpenTofu will occasionally update h1 hashes without updating the version of the dependency
|
|
346
|
-
# Here we make sure the dependency's version actually changes in the lockfile
|
|
347
459
|
unless T.cast(updated_dependency.scan(declaration_regex).first, String).scan(/^\s*version\s*=.*/) ==
|
|
348
460
|
T.cast(content.scan(declaration_regex).first, String).scan(/^\s*version\s*=.*/)
|
|
349
461
|
content.sub!(declaration_regex, updated_dependency)
|
|
@@ -358,7 +470,6 @@ module Dependabot
|
|
|
358
470
|
end
|
|
359
471
|
raise if @retrying_lock || !e.message.include?("tofu init")
|
|
360
472
|
|
|
361
|
-
# NOTE: Modules need to be installed before OpenTofu can update the lockfile
|
|
362
473
|
@retrying_lock = T.let(true, T.nilable(T::Boolean))
|
|
363
474
|
run_opentofu_init
|
|
364
475
|
retry
|
|
@@ -130,6 +130,39 @@ module Dependabot
|
|
|
130
130
|
raise Dependabot::PrivateSourceBadResponse, host
|
|
131
131
|
end
|
|
132
132
|
|
|
133
|
+
# Fetch the package hashes for every platform of a given provider version.
|
|
134
|
+
# Returns a Hash mapping "<os>_<arch>" strings to arrays of hash strings
|
|
135
|
+
# (e.g. {"linux_amd64" => ["h1:...", "zh:..."], "darwin_arm64" => [...]}).
|
|
136
|
+
# Returns nil when the registry does not include the `packages` field
|
|
137
|
+
# (e.g. the Terraform registry).
|
|
138
|
+
sig do
|
|
139
|
+
params(identifier: String, version: String)
|
|
140
|
+
.returns(T.nilable(T::Hash[String, T::Array[String]]))
|
|
141
|
+
end
|
|
142
|
+
def all_provider_package_hashes(identifier:, version:)
|
|
143
|
+
base_url = service_url_for_registry("providers.v1")
|
|
144
|
+
response = http_get!(URI.join(base_url, "#{identifier}/#{version}/download/linux/amd64"))
|
|
145
|
+
body = JSON.parse(response.body)
|
|
146
|
+
|
|
147
|
+
packages = body["packages"]
|
|
148
|
+
return nil unless packages.is_a?(Hash)
|
|
149
|
+
|
|
150
|
+
packages.each_with_object({}) do |(platform, info), result|
|
|
151
|
+
next unless info.is_a?(Hash)
|
|
152
|
+
|
|
153
|
+
hashes = Array(info["hashes"])
|
|
154
|
+
if hashes.empty?
|
|
155
|
+
Dependabot.logger.debug(
|
|
156
|
+
"No package hashes for #{identifier} v#{version} on platform #{platform}; " \
|
|
157
|
+
"registry returned hashes=#{info['hashes'].inspect}"
|
|
158
|
+
)
|
|
159
|
+
end
|
|
160
|
+
result[platform] = hashes
|
|
161
|
+
end
|
|
162
|
+
rescue Excon::Error, JSON::ParserError
|
|
163
|
+
raise error("Could not fetch provider package hashes for #{identifier} v#{version}")
|
|
164
|
+
end
|
|
165
|
+
|
|
133
166
|
# Fetch all the versions of a provider, and return a Version
|
|
134
167
|
# representation of them.
|
|
135
168
|
#
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dependabot-opentofu
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.387.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dependabot
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - '='
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0.
|
|
18
|
+
version: 0.387.0
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - '='
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 0.
|
|
25
|
+
version: 0.387.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: debug
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -262,7 +262,7 @@ licenses:
|
|
|
262
262
|
- MIT
|
|
263
263
|
metadata:
|
|
264
264
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
|
265
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
|
265
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.387.0
|
|
266
266
|
rdoc_options: []
|
|
267
267
|
require_paths:
|
|
268
268
|
- lib
|