Repository navigation
feat(cli): resolve providers from the registry the project targets - #445
Conversation
5912d8f to
a3c68a6
Compare
|
In Consequently, adding a bare provider to an OpenTofu-only destination can normalize and resolve it against Could the registry selection read |
a3c68a6 to
7304164
Compare
Addresses the two code-level readings of open-constructs#208 using the mechanism added for open-constructs#393: the registry comes from the project's declared targetVersions, so OpenTofu only when it is the sole declared product. 1. The "could not find a version" error pointed everyone at registry.terraform.io/browse/providers. An OpenTofu project now gets search.opentofu.org/providers - registry.opentofu.org/browse/providers is a 404, the listing lives on the search host. 2. `cdktn provider add` resolved available versions from registry.terraform.io regardless of target. Both registries expose the same /v1/providers/<ns>/<name>/versions shape and their version lists differ - 42 versions vs 41 for hashicorp/random at time of writing - so an OpenTofu project could be told to pin a version its own registry does not carry. Deliberately out of scope: DEFAULT_HOSTNAME, which normalizes a bare "hashicorp/aws" into a fully qualified source. That is provider *identity*, not resolution, and it is consumed by more than this path - cdktf-config-manager and prebuilt-providers both hardcode stripping the "registry.terraform.io/" prefix, so making normalization registry-aware would break prebuilt matching and cdktf.json round-tripping for OpenTofu projects. It needs its own change with those consumers updated together. The registry parameter defaults to Terraform, so every caller that does not yet thread targetVersions keeps its current behaviour. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Folds DEFAULT_HOSTNAME into the registry work, per review. OpenTofu users have been told to fully qualify their providers because normalization hardcoded registry.terraform.io. Two changes so that advice becomes optional rather than required, without breaking anyone following it: - A bare or namespace-only source now expands against the registry the project targets, so `cdktn provider add aws` in an OpenTofu project yields registry.opentofu.org/hashicorp/aws. - A source that already names a host is still left alone, so an explicit registry.opentofu.org/... always wins over the project's target - and over the default, for a project that declares no targetVersions. `isFromTerraformRegistry` becomes `isFromPublicRegistry`. That predicate gated automatic version resolution on the host being Terraform's, so an explicitly qualified OpenTofu provider - exactly what tofu users were told to write - silently skipped resolution and got no version. It now asks whether the host is a registry we can query at all, so private and self-hosted registries are still correctly excluded. Resolution and the browse URL in the error text both follow the constraint's own hostname rather than a registry passed down the call chain, which is what makes explicit qualification win and let the DependencyManager parameter go away again. simplifiedName drops whichever public host it carries, not just Terraform's. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Review finding on open-constructs#445. `providerAdd` picked the registry from `readConfigSync()`, which with no argument reads `process.cwd()/cdktf.json`, while passing `projectDirectory` to DependencyManager. Those are not the same directory: init() scaffolds into `destination` and calls providerAdd with `projectDirectory: destination` without changing cwd (cli-core/src/lib/init.ts:93). So adding a bare provider to a freshly scaffolded OpenTofu-only project would normalize and resolve it against registry.terraform.io, chosen from whatever project the CLI happened to be run from. Regression test covers the boundary directly: cwd is a Terraform-targeting project, the destination targets OpenTofu only, and the selection must follow the destination. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
7304164 to
b17afc6
Compare
### Related issue Re-lands #439, reverted in #446. **Stacked on #443** — merge that first; this branch contains its commit. If this is approved before #446, #446 can be dropped. Otherwise this is the follow-up to it. ### Why #439 failed Its diff touched only `.github/workflows/pr-unit.yml`. The job it adds runs `nx affected -t test --exclude='*,!tag:unit-test:terraform'`, so on a workflow-only change `nx affected` resolved to **no terraform-tagged projects** and the OpenTofu job ran zero tests. The green check proved nothing, and it then failed on every PR that touched a tagged project. **This branch touches `provider-generator` and `provider-schema`, so the tofu job runs for real on its own PR.** That is the point — a change to `pr-unit.yml` alone can never demonstrate this. ### What actually had to be fixed Four fixtures, in two classes. The first was expected; the second was not, and is the more interesting one. #### Providers OpenTofu will not install - `versions-file.test.ts` pinned `kreuzwerker/docker` **2.16.0**, `provider.test.ts` pinned **3.0.2**. Both rejected as unsigned. Moved to 3.9.0 — signing starts at 3.7.0, **not** at the 3.x major (#440). - `provider.test.ts` used `andsafe-AG/bitbucket`, which is on the Terraform registry but **404s on OpenTofu's**. That test needs two same-named providers from different namespaces, so it moves to `zahiar/bitbucket`, which is on both. #### Fully qualified names leaking the fetching CLI into expectations The schema JSON is keyed by FQPN, so the host records *which binary fetched it*, not anything about the code under test. Three places baked Terraform's in: | file | was | now | | --- | --- | --- | | `provider-schema.test.ts` | snapshots raw schema incl. FQPN keys | keys stubbed in the existing sanitizer | | `versions-file.test.ts` | asserted `registry.terraform.io/${fqn}` | compares the provider part | | `provider.test.ts` | directory snapshot incl. `versions.json` | FQPN keys normalized | For `provider-schema.test.ts` this extends a pattern already there: its `sanitizeJson` stubs `format_version`, `cli_name` and `cli_version` for exactly this reason — `cli_name` is already stubbed because it stamps the fetching binary, and the FQPN host is the same signal through a different field. **Keys only.** A registry URL appearing inside provider *documentation text* is identical under either CLI and stays as authored. Normalizing happens in the tests, not the product: the FQPN host is meaningful at runtime — #443 and #445 depend on it — so stripping it in the product would destroy information. ### Verified against both CLIs Not assumed, and not inferred from a green matrix job: | package | terraform | OpenTofu 1.12.6 | | --- | --- | --- | | `@cdktn/provider-generator` | 23 suites / 117 tests / 101 snapshots | same, all pass | | `@cdktn/provider-schema` | 6 suites / 58 tests / 10 snapshots | same, all pass | The generated documentation links that also differed by CLI are fixed by #443, which this is stacked on — without it, `provider.test.ts` still diverges. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Review feedback on open-constructs#445: the previous test called readConfigSync directly and asserted helper semantics, so it passed against the pathless call it was meant to guard. It documented behaviour without protecting the fix. It now calls providerAdd() with a Terraform project as cwd, an OpenTofu-only projectDirectory and a bare provider source, and asserts the constraint that reaches the DependencyManager carries registry.opentofu.org. A second case covers the mirror - an OpenTofu cwd must not leak into a Terraform destination. Confirmed it is a real guard: reverting provider-add.ts to the pathless readConfigSync() fails both cases. Spying on DependencyManager.prototype.addLocalProvider rather than mocking the module keeps the real ProviderConstraint doing the normalizing, so the assertion is on emitted behaviour. It also avoids the circular import between dependency-manager and registry-api, which makes requireActual on that module throw a TDZ error on DEFAULT_HOSTNAME. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
so0k
left a comment
There was a problem hiding this comment.
reviewed discord bot findings and final diff - LGTM
…istry `CdktfConfigManager` stripped the literal `registry.terraform.io/` prefix and compared existing entries via `ProviderConstraint.fromConfigEntry()` with no registry, which defaults to Terraform. Both only hold for a Terraform project, so open-constructs#445 left this file behind when it made provider resolution registry-aware. In an OpenTofu project `cdktn provider upgrade random@=3.2.0` produced: ["hashicorp/random@=3.1.3", "registry.opentofu.org/hashicorp/random@=3.2.0"] The prefix did not match so the source stayed qualified, and the comparison normalised the existing entry under the wrong registry, so it was not recognised as the same provider and was left in place next to the new one. The project was left with two conflicting constraints for one provider. The manager now derives its registry from the `targetVersions` of the very file it manages, which is the same source of truth open-constructs#445 used, and needs no plumbing from callers. The host is dropped only when it matches that registry, so a source explicitly qualified with another registry stays qualified - OpenTofu users have been told to fully qualify providers and that must keep working. Terraform behaviour is unchanged: of the five new test cases, the four covering OpenTofu fail against the previous implementation and the Terraform one passes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
### Description Depot runners set `NX_SELF_HOSTED_REMOTE_CACHE_SERVER`, so Nx tasks on `depot-*` runners read and write the Depot remote cache. The five `*-documentation` examples run there, and their `build` target (`cdktn get`) started getting `[remote cache]` hits: ``` nx run @examples/go-documentation:build [remote cache] ... nx run @examples/go-documentation:synth ERROR: synthesis failed, run "cdktn get" to generate providers in generated ``` Two things are wrong with caching example builds at all: - The example projects have no Nx dependency edge to `cdktn`, so their task hash covers only the example's own files, not the dist bundle the job installs. A cache hit replays bindings generated against whatever build was under test when the entry was stored. - The generated bindings directory (`generated/`, `.gen/`, `imports/`) is not a declared output, so nothing is restored and `synth` fails. Declaring outputs would fix the second point but keep the first, so this passes `--skip-nx-cache` to the single `nx run-many` call in `tools/build-example.mjs`. It covers every example and every target the runner invokes. The core packages keep their cache; #474 made their outputs complete. Seen on the Release runs for #467, #445 and #475 (a rotating set of documentation examples depending on which keys were warm). Draft until #476 lands; will rebase then. ### Checklist - [x] I have updated the PR title to match [CDKTN's style guide](https://github.com/open-constructs/cdk-terrain/blob/main/CONTRIBUTING.md#pull-requests-1) - [x] I have performed a self-review of my code - [ ] I have made corresponding changes to the documentation if applicable - [x] My changes generate no new warnings 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01RvtnNBvNuTHU4dG3NFuBeb Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
#478) ### Description The `pip` variant of `python/provider-add-command` and `python/provider-upgrade-command` installs `cdktn` in `beforeAll` without awaiting the call, while the `pipenv` block above does await its equivalent. `TestDriver.exec` returns a promise, so the first test can run `cdktn debug` before pip has finished: ``` External Error: Could not determine cdktf/cdktn version. Please make sure you are in a directory containing a cdktn project and have all dependencies installed. at TestDriver.exec (test-helper.ts:171:17) at Object.<anonymous> (python/provider-add-command/test.ts:89:21) ✕ detects correct cdktn version (1364 ms) Tests: 1 failed, 3 passed, 4 total ``` Later tests in the block pass once pip completes, which is why exactly one test fails. The slower Terraform 1.5.7 matrix entry loses the race consistently; seen on the Release runs for #445 and #475. #188 added `--no-compile` to the same line but left it un-awaited, and upstream terraform-cdk has the same call. Adds the missing `await` in both files. Draft until #476 lands; will rebase then. ### Checklist - [x] I have updated the PR title to match [CDKTN's style guide](https://github.com/open-constructs/cdk-terrain/blob/main/CONTRIBUTING.md#pull-requests-1) - [x] I have performed a self-review of my code - [ ] I have made corresponding changes to the documentation if applicable - [x] My changes generate no new warnings 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01RvtnNBvNuTHU4dG3NFuBeb Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…ness Three assumptions in the integration layer only hold under Terraform, so the fixtures could not run against OpenTofu. versions.json is keyed by fully qualified provider name, whose host is whichever registry the fetching CLI used. Five assertions indexed those keys with a literal `registry.terraform.io/...`, which reads `undefined` under OpenTofu. Adds `providerVersion()` to the test helper, matching on the provider part the way the provider-generator unit test already does, and uses it at every site. Two of the five are in `onWindows` branches that no job runs today, since `windows_integration` is `if: false`; they are corrected so re-enabling that job does not reintroduce the problem. The helper still returns `undefined` for an absent provider, so the assertions stay real guards. `TestDriver.validate()` shelled out to a bare `terraform`. The CI image points that symlink at DEFAULT_TERRAFORM_VERSION, so the helper validated with 1.16.1 even on the 1.5.7 matrix rows, and would have run Terraform on an OpenTofu row. It now honours TERRAFORM_BINARY_NAME, which the workflow already exports. Pins the two provider-command targets to OpenTofu as well. They drive provider resolution through the CLI's own registry, so they are what would catch a regression in the registry selection added by open-constructs#445. Their Terraform entries restate the `tested` default so the pin does not silently drop 1.5.7; the matrix grows by two jobs. Also normalises path separators in the matrix builder. `jest --listTests` emits Windows separators, so no target matched the `test/` prefix and every configured pin tripped the "not a discovered test target" guard, making the builder impossible to run outside CI. Verified every provider, module and exact version the fixtures pin is present on registry.opentofu.org, checking a known-absent provider and a nonsense path first to confirm that endpoint 404s rather than soft-404ing like search.opentofu.org. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…istry `CdktfConfigManager` stripped the literal `registry.terraform.io/` prefix and compared existing entries via `ProviderConstraint.fromConfigEntry()` with no registry, which defaults to Terraform. Both only hold for a Terraform project, so open-constructs#445 left this file behind when it made provider resolution registry-aware. In an OpenTofu project `cdktn provider upgrade random@=3.2.0` produced: ["hashicorp/random@=3.1.3", "registry.opentofu.org/hashicorp/random@=3.2.0"] The prefix did not match so the source stayed qualified, and the comparison normalised the existing entry under the wrong registry, so it was not recognised as the same provider and was left in place next to the new one. The project was left with two conflicting constraints for one provider. The manager now derives its registry from the `targetVersions` of the very file it manages, which is the same source of truth open-constructs#445 used, and needs no plumbing from callers. The host is dropped only when it matches that registry, so a source explicitly qualified with another registry stays qualified - OpenTofu users have been told to fully qualify providers and that must keep working. Terraform behaviour is unchanged: of the five new test cases, the four covering OpenTofu fail against the previous implementation and the Terraform one passes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ness Three assumptions in the integration layer only hold under Terraform, so the fixtures could not run against OpenTofu. versions.json is keyed by fully qualified provider name, whose host is whichever registry the fetching CLI used. Five assertions indexed those keys with a literal `registry.terraform.io/...`, which reads `undefined` under OpenTofu. Adds `providerVersion()` to the test helper, matching on the provider part the way the provider-generator unit test already does, and uses it at every site. Two of the five are in `onWindows` branches that no job runs today, since `windows_integration` is `if: false`; they are corrected so re-enabling that job does not reintroduce the problem. The helper still returns `undefined` for an absent provider, so the assertions stay real guards. `TestDriver.validate()` shelled out to a bare `terraform`. The CI image points that symlink at DEFAULT_TERRAFORM_VERSION, so the helper validated with 1.16.1 even on the 1.5.7 matrix rows, and would have run Terraform on an OpenTofu row. It now honours TERRAFORM_BINARY_NAME, which the workflow already exports. Pins the two provider-command targets to OpenTofu as well. They drive provider resolution through the CLI's own registry, so they are what would catch a regression in the registry selection added by open-constructs#445. Their Terraform entries restate the `tested` default so the pin does not silently drop 1.5.7; the matrix grows by two jobs. Also normalises path separators in the matrix builder. `jest --listTests` emits Windows separators, so no target matched the `test/` prefix and every configured pin tripped the "not a discovered test target" guard, making the builder impossible to run outside CI. Verified every provider, module and exact version the fixtures pin is present on registry.opentofu.org, checking a known-absent provider and a nonsense path first to confirm that endpoint 404s rather than soft-404ing like search.opentofu.org. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…istry `CdktfConfigManager` stripped the literal `registry.terraform.io/` prefix and compared existing entries via `ProviderConstraint.fromConfigEntry()` with no registry, which defaults to Terraform. Both only hold for a Terraform project, so open-constructs#445 left this file behind when it made provider resolution registry-aware. In an OpenTofu project `cdktn provider upgrade random@=3.2.0` produced: ["hashicorp/random@=3.1.3", "registry.opentofu.org/hashicorp/random@=3.2.0"] The prefix did not match so the source stayed qualified, and the comparison normalised the existing entry under the wrong registry, so it was not recognised as the same provider and was left in place next to the new one. The project was left with two conflicting constraints for one provider. The manager now derives its registry from the `targetVersions` of the very file it manages, which is the same source of truth open-constructs#445 used, and needs no plumbing from callers. The host is dropped only when it matches that registry, so a source explicitly qualified with another registry stays qualified - OpenTofu users have been told to fully qualify providers and that must keep working. Terraform behaviour is unchanged: of the five new test cases, the four covering OpenTofu fail against the previous implementation and the Terraform one passes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
🤖 Release PR — merge to cut a new release. Kept open and rebased as commits land on `main`. --- <details><summary>0.25.0</summary> ## [0.25.0](v0.24.0...v0.25.0) (2026-10-27) ### ⚠ BREAKING CHANGES * **lib:** `IAssetPackaging` gains `acceptsDirectorySource` as a required member. Custom implementations of the interface must add it. * **lib:** ValidateBinaryVersion and ValidateTerraformVersion are removed (they were only reachable through deep imports, not the cdktn package root). Synth no longer executes the terraform/tofu binary for feature validation; set validateInstalledBinary: true in cdktf.json to verify the installed binary before commands that run it. * **lib:** resource moves (moved blocks) are now validated at synth against the project's declared targetVersions (default terraform >=1.5.7, opentofu >=1.6.0) instead of the locally installed binary. Projects that declare terraform targets below 1.5.0 now fail synth; projects whose installed binary is older than their declared targets should set validateInstalledBinary: true in cdktf.json. * **lib:** import blocks (importFrom / ImportableResource) are now validated at synth against the project's declared targetVersions (default terraform >=1.5.7, opentofu >=1.6.0) instead of the locally installed binary. Projects that declare terraform targets below 1.5.0 now fail synth; projects whose installed binary is older than their declared targets should set validateInstalledBinary: true in cdktf.json. * **lib:** terraform_data resources are now validated at synth against the project's declared targetVersions (default terraform >=1.5.7, opentofu >=1.6.0) instead of the locally installed binary. Projects that declare terraform targets below 1.4.0 now fail synth; projects whose installed binary is older than their declared targets should set * **lib:** cloud backends (the cloud block) are now validated at synth against the project's declared targetVersions (default terraform >=1.5.7, opentofu >=1.6.0) instead of the locally installed binary. Projects that declare terraform targets below 1.1.0 now fail synth; projects whose installed binary is older than their declared targets should set validateInstalledBinary: true in cdktf.json. * **lib:** IAssetPackaging gains a required member omitsDirectoryEntries; external implementations must add it. Custom TerraformAsset assetHash values are now validated against `/^[A-Za-z0-9_.-]+$/` and throw if they contain other characters (e.g. "feature/my-branch"). * **lib:** add asset pipeline foundation types and hash utilities ([#371](#371)) ### Features * **cli:** add a typescript-pnpm init template and deprecate Yarn ([#422](#422)) ([81da164](81da164)) * **cli:** move the TypeScript template to tsx and TypeScript 6 ([#396](#396)) ([b50349d](b50349d)) * **cli:** point AI coding agents at the CDKTN docs MCP server ([#518](#518)) ([f257cd9](f257cd9)) * **cli:** rename `--cdktf-version` to `--cdktn-version` in `init` ([#228](#228)) ([dd3818e](dd3818e)) * **cli:** replace HashiCorp checkpoint telemetry with Sentry usage metrics and consent ([#411](#411)) ([e17046a](e17046a)) * **cli:** report aggregated stack, provider and command usage metrics ([#413](#413)) ([ed9b1e5](ed9b1e5)) * **cli:** report the installed binary, target versions, platform and package manager in usage metrics ([#412](#412)) ([bfe26a8](bfe26a8)) * **cli:** resolve providers from the registry the project targets ([#445](#445)) ([78898ae](78898ae)) * **deps:** adopt jsii 6.0 and TypeScript 6 ([#395](#395)) ([26fa8fa](26fa8fa)) * **gha:** Revert "run the affected unit tests against OpenTofu ([#439](#439))" ([#446](#446)) ([ae015ef](ae015ef)) * **gha:** run the affected unit tests against OpenTofu ([#439](#439)) ([823682d](823682d)) * **gha:** run the affected unit tests against OpenTofu ([#447](#447)) ([c0c4c1c](c0c4c1c)) * **lib:** add asset bundling extension interface ([#442](#442)) ([7839625](7839625)) * **lib:** add asset pipeline foundation types and hash utilities ([#371](#371)) ([a008d12](a008d12)) * **lib:** add asset staging core with no bundling ([#433](#433)) ([44d8bd1](44d8bd1)) * **lib:** add support for single-file bundler outputs ([#464](#464)) ([3592db0](3592db0)) * **lib:** pass ignore strategy through terraform asset ([#472](#472)) ([705e5b9](705e5b9)) * **tests:** add per-test runtime pinning to the integration matrix ([#405](#405)) ([17c2278](17c2278)) ### Bug Fixes * **cli:** catch failures of the background environment collection ([#531](#531)) ([c5feed8](c5feed8)) * **cli:** correct the constructs range comment in the TypeScript template hook ([#408](#408)) ([9fc0e43](9fc0e43)) * **cli:** don't crash after a successful deploy when an output is missing ([#375](#375)) ([0bbd64a](0bbd64a)) * **cli:** fail cleanly when the --outputs-file write fails ([#376](#376)) ([8f9d03a](8f9d03a)) * **cli:** make `cdktn get` remove stale files for resources removed from a provider ([#421](#421)) ([d6e28dc](d6e28dc)) * **cli:** match prebuilt providers regardless of the project's registry ([#493](#493)) ([ea82124](ea82124)) * **cli:** probe with `version` instead of `-v` ([#471](#471)) ([b87ee22](b87ee22)) * **cli:** require patched Node 22.23.4 and bump undici for security fixes ([#516](#516)) ([76436f5](76436f5)) * **cli:** resolve bundled handlers next to the entrypoint ([#414](#414)) ([49600c1](49600c1)) * **cli:** resolve upgraded providers from the CLI's own registry ([#489](#489)) ([10672ee](10672ee)) * **cli:** stop the top-level error handler racing yargs ([#410](#410)) ([5d0c2ef](5d0c2ef)) * **deps:** move jsii-rosetta to 6.0.16 for stream-json 3 ([#463](#463)) ([f1ec16f](f1ec16f)) * **gha:** authenticate to public.ecr.aws in the docker image build ([#519](#519)) ([c65bf2f](c65bf2f)) * **gha:** don't fail the pnpm upgrade jobs on ignored dep builds ([#399](#399)) ([5b66342](5b66342)) * **gha:** move the jsii package cache out of the container HOME ([#514](#514)) ([df5b490](df5b490)) * **gha:** pass -R to gh pr edit in release_github relabel step ([#372](#372)) ([358edc7](358edc7)) * **gha:** push only the prerelease tag from prepare-next ([#476](#476)) ([848f2a6](848f2a6)) * **lib:** avoid terraform init plugin-cache race in test matchers ([#467](#467)) ([26847f9](26847f9)) * **lib:** retry the staging install without --prefer-offline outside CI ([#407](#407)) ([7bb26e7](7bb26e7)) * **provider-generator:** pass the default provider configuration a module requires on get ([#466](#466)) ([a5225ab](a5225ab)) * **provider-generator:** pick the docs registry from targetVersions ([#443](#443)) ([00f2884](00f2884)) * **provider-generator:** pick the module docs registry from targetVersions ([#484](#484)) ([8200330](8200330)) * **provider-generator:** regenerate bindings when the target registry changes ([#490](#490)) ([813e022](813e022)) * **provider-generator:** satisfy module provider configuration aliases on get ([#383](#383)) ([54a8217](54a8217)) * **provider-generator:** stop a provider_functions resource clobbering the functions submodule ([#403](#403)) ([cf19de9](cf19de9)) * **tests:** await the pip install in the python provider command tests ([#478](#478)) ([1c83a36](1c83a36)) * **tests:** bound and retry the dist publish to the local registry ([#425](#425)) ([cc9f9e2](cc9f9e2)) * **tests:** build the edge provider bindings in their own cached Nx target ([#482](#482)) ([f480cc9](f480cc9)) * **tests:** drop unused ts-jest transform from shared jest preset ([#382](#382)) ([03f6e16](03f6e16)) * **tests:** mark the terraform-cloud target Terraform-only in the matrix ([#430](#430)) ([b0deefa](b0deefa)) * **tests:** run example builds with the Nx cache skipped ([#477](#477)) ([3e25e13](3e25e13)) * **tools:** declare the cdktn-cli bundle as a cached Nx output with its real inputs ([#485](#485)) ([10dd118](10dd118)) * **tools:** make the workspace build, package, lint and test on Windows ([#364](#364)) ([8dcddbe](8dcddbe)) ### Code Refactoring * **lib:** Remove the ValidateBinaryVersion synth-time binary probe ([#457](#457)) ([e60142e](e60142e)) * **lib:** Use declared targetVersions for synth-time validation of import blocks ([#454](#454)) ([c0097f4](c0097f4)) * **lib:** Use declared targetVersions for synth-time validation of resource moves ([#453](#453)) ([43edc1e](43edc1e)) * **lib:** Use declared targetVersions for synth-time validation of terraform_data ([#455](#455)) ([a1c125b](a1c125b)) * **lib:** Use declared targetVersions for synth-time validation of the cloud backend ([#456](#456)) ([4a83507](4a83507)) ### Miscellaneous Chores * add OpenTofu and current Terraform to the jsii-terraform image ([#394](#394)) ([2f29d5a](2f29d5a)) * declare complete Nx build outputs so cache hits restore them ([#474](#474)) ([794cf77](794cf77)) * **deps:** move the remaining packages to TypeScript 6 ([#406](#406)) ([c55d360](c55d360)) * **deps:** move the root TypeScript to 6 ([#417](#417)) ([3cae1e2](3cae1e2)) * **deps:** Update xstate to v5.32.4 ([#333](#333)) ([5ebf74f](5ebf74f)) * **deps:** upgrade @sentry/node to 10.x ([#409](#409)) ([2714fff](2714fff)) * **deps:** use caret ranges for unbundled runtime dependencies ([#503](#503)) ([e722357](e722357)) * **docs:** add the test-audit skill for authoring and auditing tests ([#475](#475)) ([909c612](909c612)) * **examples:** move the TypeScript examples to tsx and TypeScript 6 ([#419](#419)) ([857e182](857e182)) * Flexible python version ([#420](#420)) ([955f62a](955f62a)) * **gha:** adopt the new jsii-terraform image and test Terraform 1.5.7 + 1.16.1 ([#398](#398)) ([3ad760b](3ad760b)) * **gha:** gate dependency upgrades on release age ([#418](#418)) ([b611a87](b611a87)) * **gha:** retire Docker Hub publishing of jsii-terraform ([#388](#388)) ([e53cddf](e53cddf)) * **gha:** select the CLI by binary name instead of concatenating a version ([#438](#438)) ([914da56](914da56)) * **gha:** skip the remote Nx cache in the release workflow ([#487](#487)) ([bce91da](bce91da)) * **lib:** stop publishing build state in the cdktn package ([#397](#397)) ([51e4a95](51e4a95)) * npm-check-updates && pnpm update ([#326](#326)) ([7095f6b](7095f6b)) * **readme:** point to the cdktn-io/action GitHub Action ([#504](#504)) ([e387852](e387852)), closes [#58](#58) * **tests:** add timeout handling to spawned commands ([#432](#432)) ([ddb4a8a](ddb4a8a)) * **tests:** run the function-binding scripts with tsx ([#431](#431)) ([fec67bf](fec67bf)) ### Tests * **lib:** ensure TerraformAsset stage within stack own directory ([#434](#434)) ([9a80366](9a80366)) * **lib:** move matcher Docker fixture to a provider version OpenTofu accepts ([#429](#429)) ([7b0da12](7b0da12)) * **tests:** move the python providers fixture to Docker provider 3.9.0 ([#440](#440)) ([a678473](a678473)) * **tests:** move the remaining kreuzwerker/docker pins off unsigned versions ([#459](#459)) ([d855cc1](d855cc1)) * **tests:** move the testing-matchers fixtures to Docker provider 3.x ([#436](#436)) ([8e2c60e](8e2c60e)) * **tests:** re-enable the Python edge integration test ([#404](#404)) ([0a80626](0a80626)) </details> --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: open-constructs-cdktn[bot] <291052431+open-constructs-cdktn[bot]@users.noreply.github.com>
|
I'm going to lock this pull request because it has been closed for 30 days. This helps our maintainers find and focus on the active issues. If you've found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further. |
Related issue
Addresses the code-level readings of #208. Stacked on #443 — merge that first; this branch contains its commit and reuses the registry mechanism it adds.
Description
#208's title reads like a
dependency-managerchange while its body is about sample code on registries, so it admits three readings. This takes the two that are code-level, using the sametargetVersions-derived registry as #443 — OpenTofu only when it is the sole declared product, Terraform otherwise.The through-line: OpenTofu users have been told to fully qualify their providers, because everything here hardcoded
registry.terraform.io. These changes make that advice optional rather than required, without breaking anyone already following it.1. Bare sources expand against the project's registry
normalizeProviderSourcehardcoded the Terraform host, socdktn provider add awsalways producedregistry.terraform.io/hashicorp/aws. It now expands against the registry the project targets, so an OpenTofu project getsregistry.opentofu.org/hashicorp/aws.A source that already names a host is still left untouched, so an explicit
registry.opentofu.org/...always wins — over the project's target, and over the default for a project that declares notargetVersions.2. Explicitly qualified OpenTofu providers silently skipped version resolution
This is a live bug on
main, and it hits exactly the users who followed the fully-qualify advice. Version resolution was gated on:where
isFromTerraformRegistry()ishostname === "registry.terraform.io". A provider written asregistry.opentofu.org/hashicorp/awswith no version failed that check, so no version was resolved and none was written.It becomes
isFromPublicRegistry()— whether the host is a registry cdktn can query at all. Private and self-hosted registries are still correctly excluded, since they expose no versions API.3. Resolution and the browse URL follow the constraint
Both now derive from the constraint's own hostname rather than a registry threaded down the call chain. That is what makes explicit qualification win, and it let the
DependencyManagerparameter from the first commit go away again.Both registries expose the same
/v1/providers/{ns}/{name}/versionsshape, and their version lists differ — 42 versus 41 forhashicorp/randomat time of writing — so an OpenTofu project could previously be told to pin a version its own registry does not carry.The error text's browse URL follows too:
search.opentofu.org/providersfor OpenTofu, sinceregistry.opentofu.org/browse/providersis a 404.simplifiedNamedrops whichever public host it carries, not just Terraform's.What is still out of scope
The third reading of #208 — publishing CDK Terrain samples to the OpenTofu registry — is untouched, so the issue stays open for it.
cdktf-config-managerstill strips only the Terraform prefix when writingcdktf.json, which means an OpenTofu project's providers are written fully qualified. That round-trips correctly and matches what those users already write by hand, so it is left alone deliberately rather than risking a strip that normalization would not re-add.Testing
registry-api.test.tscovers all four paths with theMockAgentpattern the neighbouring tests use: default resolves against Terraform; a bare source under an OpenTofu target expands and resolves against OpenTofu; an explicitly qualified OpenTofu source resolves even with no declared target; a private registry is not queryable.nx test @cdktn/cli-core(so the dependency chain is built): all suites pass.Running jest directly in the package without building siblings reports failures on
Cannot find module '@cdktn/hcl2cdk'/'@cdktn/hcl-tools'— pre-existing and unrelated.🤖 Generated with Claude Code