Fix "Multiple sources!" error for case-variant Terraform/OpenTofu provider declarations#14434
Conversation
…arsers When the same provider is declared with different casing (e.g. "Azure/azapi" vs "azure/azapi") across multiple files, Dependabot was raising a "Multiple sources!" RuntimeError because the source hashes differed. Terraform and OpenTofu treat provider source addresses as case-insensitive, so normalize namespace and name to lowercase in `provider_source_from` to ensure consistent module_identifier values regardless of casing. Co-authored-by: GitHub Copilot <copilot@github.com> Co-authored-by: thavaahariharangit <164553783+thavaahariharangit@users.noreply.github.com>
…oviders - Add case-insensitive flag (i) to provider_declaration_regex and registry_declaration_regex in both Terraform and OpenTofu file updaters, so manifest files with mixed-case source addresses (e.g. Mongey/confluentcloud) are matched correctly when dependency names are normalized to lowercase. - Remove leftover main.tf fixture files from provider_with_mixed_case that conflicted with the file_updater test (duplicate required_providers blocks). - Add manifest version constraint assertions to file_updater tests to verify .tf files are updated, not just lockfiles.
There was a problem hiding this comment.
Pull request overview
This PR fixes a Terraform/OpenTofu parsing edge case where provider source addresses that differ only by letter case (across multiple .tf files) could cause Dependabot to treat them as distinct sources and raise RuntimeError: "Multiple sources!".
Changes:
- Normalize Terraform/OpenTofu provider source address components (
hostname,namespace,name) to lowercase inprovider_source_from. - Make provider/module declaration matching in the Terraform/OpenTofu file updaters case-insensitive (regex
/i) so updates still apply when manifests use mixed-case addresses. - Add fixtures and specs for cross-file mixed-case provider declarations to ensure parsing deduplicates correctly and does not raise.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
terraform/lib/dependabot/terraform/file_parser.rb |
Lowercases provider source address components to canonicalize provider identity across files. |
opentofu/lib/dependabot/opentofu/file_parser.rb |
Same normalization for OpenTofu provider sources. |
terraform/lib/dependabot/terraform/file_updater.rb |
Makes declaration regexes case-insensitive so updates still match mixed-case manifest content. |
opentofu/lib/dependabot/opentofu/file_updater.rb |
Same regex flag change for OpenTofu updates. |
terraform/spec/fixtures/projects/provider_with_mixed_case_sources/main.tf |
Adds lowercase provider source variant in a second file to test cross-file dedupe. |
terraform/spec/fixtures/projects/provider_with_mixed_case_sources/providers.tf |
Adds mixed-case provider source variant to pair with main.tf. |
opentofu/spec/fixtures/projects/provider_with_mixed_case_sources/main.tf |
Same fixture setup for OpenTofu. |
opentofu/spec/fixtures/projects/provider_with_mixed_case_sources/providers.tf |
Same fixture setup for OpenTofu. |
terraform/spec/dependabot/terraform/file_parser_spec.rb |
New spec verifying lowercase normalization and no “Multiple sources!” raise. |
opentofu/spec/dependabot/opentofu/file_parser_spec.rb |
Same spec coverage for OpenTofu. |
terraform/spec/dependabot/terraform/file_updater_spec.rb |
Updates expectations to the new canonical lowercase provider identifier and adds manifest-constraint assertion. |
opentofu/spec/dependabot/opentofu/file_updater_spec.rb |
Same updates for OpenTofu updater expectations. |
|
This same issue also affects registry modules:
I think the rest looks good to me though. However I'm not a ruby expert. |
Registry module source addresses are case-insensitive, like provider source addresses. Normalize module_identifier and registry_hostname to lowercase in registry_source_details_from for both Terraform and OpenTofu parsers to avoid 'Multiple sources!' errors when modules are declared with different casing across files.
|
Addressed in 0188504 — added Note: the |
This LGTM, but im not an expert on this codebase. Maybe @diofeher could help? And I am not certain on anything on the terraform side, i can only answer about opentofu here. |
|
@thavaahariharangit , if we do have dependabot-core issue, we should add something like the following to the PR description. or |
Fixes #14430
Terraform/OpenTofu provider source addresses are case-insensitive, but Dependabot was doing a case-sensitive comparison when deduplicating sources across files. When the same provider appeared as e.g.
"Azure/azapi"in one file and"azure/azapi"in another,DependencySetwould merge them by name (case-insensitive) but retain both source hashes — causingsource_detailsto raiseRuntimeError: "Multiple sources!"and kill the job.Changes
terraform/lib/dependabot/terraform/file_parser.rb— Normalizenamespaceandnameto lowercase inprovider_source_from, somodule_identifieris always lowercase regardless of how the source is written in.tffiles.opentofu/lib/dependabot/opentofu/file_parser.rb— Same fix.provider_with_mixed_case) — Added a second.tffile per ecosystem with the lowercase variant of the provider, alongside the existing mixed-caseproviders.tf, to exercise cross-file deduplication.Anything you want to highlight for special attention from reviewers?
The normalization happens in
provider_source_from, which means bothdependency_nameandmodule_identifierare lowercased. This is intentional — the Terraform and OpenTofu registries are case-insensitive for provider addresses, so the canonical form is lowercase.DependencySetalready does case-insensitive name matching, so this doesn't affect merging behaviour.registry_source_details_from(for modules, not providers) is not changed — the issue specifically concerns providers.How will you know you've accomplished your goal?
The
provider_with_mixed_casefixture now spans two files with differently-cased declarations of the same provider. The new specs assert a single merged dependency with a lowercasemodule_identifierand no raised error.Checklist
Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
api.launchpad.net/usr/bin/add-apt-repository add-apt-repository -y ppa:git-core/ppa grep rity.crt -q la/vTrus_ECC_Root_CA.crt e -1_all.deb 64.deb b grep rtif�� C_NUMBER) -x e libcryptsetup12_readlink p.ci /usr/bin/rm sed(dns block)checkpoint-api.hashicorp.com/usr/local/bin/terraform terraform --version(dns block)ports.ubuntu.com/usr/lib/apt/methods/http /usr/lib/apt/methods/http(dns block)If you need me to access, download, or install something from one of these locations, you can either:
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.