Repository navigation
Conversation
|
Follow-up reference for future feature-specific validation PRs: I added a semi-curated generator in the Generated file: Human-controlled input: Quick usage: canitf generate-cdktn-source \
--features-input data/hcl-feature-input.json \
--generated-features data/features.json \
--out data/cdktn-feature-constraints.tsThe generated output is intended to line up with this PR's Longer context: why this exists and how to use itThe broad changelog-derived table in
Current focused feature set:
Important baseline note: I could not confirm “OpenTofu forked from Terraform 1.7.5”; that appears to be the wrong framing. The local CDK Terrain workspace pins Terraform Example generated shape: export const TERRAFORM_HCL_FEATURE_CONSTRAINTS = {
"s3-native-state-locking": {
featureName: "S3 native state locking",
constraints: {
terraform: ">=1.10.0",
opentofu: ">=1.10.0",
},
category: "backend",
cdktnUseCase: "S3BackendConfig.useLockfile",
sources: [
"https://developer.hashicorp.com/terraform/language/v1.10.x/upgrade-guides#s3-backend",
"https://opentofu.org/docs/intro/whats-new/#native-s3-state-locking",
],
},
} as const;This should make the next PRs easier: update the curated JSON input, regenerate the TS source, then wire the relevant feature key into the specific validation path. |
|
tests are failing with FAIL test/validations.test.ts (5.325 s)
● ValidateTerraformFeatureVersion › fails when the CLI product cannot be detected from the first line
expect(received).toThrowErrorMatchingInlineSnapshot(snapshot)
Snapshot name: `ValidateTerraformFeatureVersion fails when the CLI product cannot be detected from the first line 1`
- Snapshot - 1
+ Received + 1
"Validation failed with the following errors:
- [MyStack/testResource] Could not determine whether terraform is Terraform or OpenTofu from the first line of terraform version output: {"terraform_version":"1.10.10"}
+ [MyStack/testResource] Could not determine whether terraform1.5.5 is Terraform or OpenTofu from the first line of terraform1.5.5 version output: {"terraform_version":"1.10.10"}this is for Terraform 1.5.5 and Terraform 1.6.5 |
Adds the reusable foundation for validating features against the project's declared Terraform/OpenTofu targets instead of probing whichever binary happens to be installed during synth: - resolveTargetVersions(scope): reads the targetVersions context (injected by the CLI from cdktf.json), defaulting to the dual product baseline (terraform >=1.5.7, opentofu >=1.6.0) when undeclared - checkFeatureSupportedByTargets: semver range *subset* check — a feature passes only if it is supported across the entire declared range of every targeted product - ValidateFeatureTargetSupport: IValidation over the two; never executes a binary, so it behaves identically in CI/synth-only environments Synth-time validations no longer probe the installed binary: - ValidateTerraformFeatureVersion (merged unreleased in #237, zero call sites) is removed together with its execSync machinery; the pure parseTerraformCliVersion parser and the TerraformFeatureVersionConstraints type remain. Installed-binary verification is an explicit opt-in handled by the CLI (validateInstalledBinary). - The long-released ValidateBinaryVersion and the resource-move probe built on it stay unchanged as the legacy exception, both marked with TODO(target-versions) for a follow-up migration. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds the reusable foundation for validating features against the project's declared Terraform/OpenTofu targets instead of probing whichever binary happens to be installed during synth: - resolveTargetVersions(scope): reads the targetVersions context (injected by the CLI from cdktf.json), defaulting to the dual product baseline (terraform >=1.5.7, opentofu >=1.6.0) when undeclared - checkFeatureSupportedByTargets: semver range *subset* check — a feature passes only if it is supported across the entire declared range of every targeted product - ValidateFeatureTargetSupport: IValidation over the two; never executes a binary, so it behaves identically in CI/synth-only environments Synth-time validations no longer probe the installed binary: - ValidateTerraformFeatureVersion (merged unreleased in #237, zero call sites) is removed together with its execSync machinery; the pure parseTerraformCliVersion parser and the TerraformFeatureVersionConstraints type remain. Installed-binary verification is an explicit opt-in handled by the CLI (validateInstalledBinary). - The long-released ValidateBinaryVersion and the resource-move probe built on it stay unchanged as the legacy exception, both marked with TODO(target-versions) for a follow-up migration. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds the reusable foundation for validating features against the project's declared Terraform/OpenTofu targets instead of probing whichever binary happens to be installed during synth: - resolveTargetVersions(scope): reads the targetVersions context (injected by the CLI from cdktf.json), defaulting to the dual product baseline (terraform >=1.5.7, opentofu >=1.6.0) when undeclared - checkFeatureSupportedByTargets: semver range *subset* check — a feature passes only if it is supported across the entire declared range of every targeted product - ValidateFeatureTargetSupport: IValidation over the two; never executes a binary, so it behaves identically in CI/synth-only environments Synth-time validations no longer probe the installed binary: - ValidateTerraformFeatureVersion (merged unreleased in #237, zero call sites) is removed together with its execSync machinery; the pure parseTerraformCliVersion parser and the TerraformFeatureVersionConstraints type remain. Installed-binary verification is an explicit opt-in handled by the CLI (validateInstalledBinary). - The long-released ValidateBinaryVersion and the resource-move probe built on it stay unchanged as the legacy exception, both marked with TODO(target-versions) for a follow-up migration. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ion) (#269) ## Summary > Reworks unreleased #237 to not run terraform binary during synth Prerequisite for #268. Instead of probing whichever Terraform/OpenTofu binary happens to be installed during synth, projects declare the runtimes they intend to support, and validations answer: *"is this feature supported by the project's declared target range?"* — deterministically, with no binary required. Installed-binary verification becomes an explicit opt-in for commands that execute the binary anyway. ```jsonc // cdktf.json { "targetVersions": { "terraform": ">=1.5.7", "opentofu": ">=1.6.0" }, "validateInstalledBinary": true // opt-in, off by default } ``` ### Commits 1. **feat(cli): add targetVersions to cdktf.json config** — typed field in `@cdktn/commons`; `parseConfig` validates product names and npm-semver ranges (Terraform's `~>` syntax is rejected with a hint — npm semver would silently parse it as `~` with different semantics) and threads the declaration to apps through the existing `CDKTF_CONTEXT_JSON` channel. Also adds `parseTerraformCliVersion` to commons and the `validateInstalledBinary` flag. 2. **feat(lib): validate features against declared runtime targets** — `resolveTargetVersions(scope)` (context → dual-baseline default `terraform >=1.5.7` + `opentofu >=1.6.0`), `checkFeatureSupportedByTargets` (semver range **subset**: a feature passes only if supported across the *entire* declared range of every targeted product), and `ValidateFeatureTargetSupport` (an `IValidation` that never executes a binary). Synth-time binary probing is removed: `ValidateTerraformFeatureVersion` (merged unreleased in #237, zero call sites) is deleted together with its execSync machinery — the pure `parseTerraformCliVersion` parser and the `TerraformFeatureVersionConstraints` type remain. The long-released `ValidateBinaryVersion` and the resource-move probe built on it stay unchanged as the legacy exception, both marked `TODO(target-versions)`. 3. **feat(cli): opt-in installed-binary verification** — when `validateInstalledBinary: true`, `initalizeTerraform` (the diff/deploy/destroy chokepoint, where the binary is about to run anyway) verifies the installed product/version against the declared targets. Declared targets are deliberately *not* treated as proof about the local binary. 4. **feat(cli): write default targetVersions in init templates** — new projects get the dual baseline explicitly in `cdktf.json`. ### Semantics - **Subset check**: declaring `terraform: ">=1.5.7"` while using a feature that needs `>=1.8.0` fails — the project claims to support 1.5.7..1.8.0 where the feature is missing. The fix is raising the declared floor (or narrowing the range), which keeps the declaration honest. - **Missing product key in a feature's constraints** = unsupported by that product; **missing product key in declared targets** = the project doesn't target that product. - **Undeclared** = dual product baseline (strictest, most portable interpretation). - **Synth never executes a binary.** The only places a binary is run are commands that execute it anyway (opt-in `validateInstalledBinary`) and the legacy `ValidateBinaryVersion`/resource-move path kept for compatibility. ### Stacked work #268 (function availability validation) is stacked on this branch: its `ValidateFunctionVersionSupport` checks used `Fn` functions against the declared targets via `checkFeatureSupportedByTargets`, gated by the `validateFunctionVersions` feature flag. ## Test plan - [x] `@cdktn/commons`: 83/83 — parser accepts constraint-shaped targets, rejects unknown products / malformed ranges / `~>` / empty declarations / non-strings; context payload merge - [x] `cdktn`: 425/426 — resolver default + context override + malformed-context errors; subset pass/fail; independent product evaluation; product-not-targeted skip; complex ranges; `ValidateFeatureTargetSupport` end-to-end with an execSync spy proving no binary call (the 1 failure is the pre-existing Docker-daemon-dependent `matchers.test.ts`, unrelated) - [x] `@cdktn/cli-core`: 146 passed / 30 skipped (dist-dependent) — installed-binary check helper: satisfies/outside-range/undeclared-product/unparseable/default-baseline - [ ] Integration: existing init tests exercise the new template field in CI 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🤖 Release PR — merge to cut a new release. Kept open and rebased as commits land on `main`. --- <details><summary>0.23.4</summary> ## [0.23.4](v0.23.3...v0.23.4) (2026-07-02) ### Features * **cli:** validate Terraform CLI feature versions ([#237](#237)) ([32d434c](32d434c)) * declared Terraform/OpenTofu target versions (validation foundation) ([#269](#269)) ([0aa2343](0aa2343)) * **lib:** S3-backend - Add `useLockfile` field and update `dynamodbTable` deprecated JSDoc ([#234](#234)) ([32a408f](32a408f)) * **lib:** validate Fn usage against Terraform/OpenTofu versions ([#268](#268)) ([cdf8115](cdf8115)) ### Bug Fixes * **cli:** don't mistake terraform error output for a missing-variable prompt ([#267](#267)) ([0ea946f](0ea946f)) * **cli:** release terraform state lock when interrupting diff/deploy ([#284](#284)) ([de617db](de617db)) * **cli:** resolve prebuilt Java provider versions via repo1.maven.org ([#285](#285)) ([d5af07d](d5af07d)) * **gha:** Adding CHANGELOG.md to prettier ignore list ([#258](#258)) ([5160469](5160469)) * **gha:** pull jsii-terraform CI image from GHCR instead of Docker Hub ([#261](#261)) ([f19d34b](f19d34b)) * **provider-generator:** copy only publishable files into the jsii compile bundle ([#292](#292)) ([562d4c7](562d4c7)) * **provider-generator:** match shorthand provider sources against OpenTofu schema keys ([#293](#293)) ([fda0103](fda0103)) * **release:** add Changelog title for correct release-please insertion ([#255](#255)) ([004818a](004818a)) * **release:** drop devEngines.packageManager that broke npm publish ([ef508a6](ef508a6)) * **tools:** repair generate-function-bindings tool ([#273](#273)) ([821e1cf](821e1cf)) ### Miscellaneous Chores * Add Gradle to Mise config ([#271](#271)) ([1578270](1578270)) * add pnpm to mise ([#266](#266)) ([48ab91f](48ab91f)) * add uv to mise ([#260](#260)) ([163cf3d](163cf3d)) * **deps:** bump nrwl/nx-set-shas from 38457b511e60ee4e1da09255b658e480748a1af4 to afb73a62d26e41464e9254689e1fd6122ee683c1 ([#236](#236)) ([b5ac018](b5ac018)) * **deps:** bump the github-actions-backward-compatible group across 1 directory with 7 updates ([#235](#235)) ([de67d9f](de67d9f)) * **deps:** replace uuid dependency with node:crypto.randomUUID ([#291](#291)) ([6d3657a](6d3657a)) * ESLint ignore test edge-provider-bindings ([#270](#270)) ([ba407bb](ba407bb)) * Fix Verdaccio logging config ([#272](#272)) ([aded64b](aded64b)) * **gha:** parallelize provider binding generation for documentation examples ([#244](#244)) ([0a9c955](0a9c955)) * Migrate package manager from yarn to pnpm ([#170](#170)) ([d23da4e](d23da4e)) * migrate planning artifacts to cdktn-planning [skip ci] ([968c358](968c358)) * **release:** add release-please automation for versioning ([#243](#243)) ([c759eec](c759eec)) * Remove dependency-pinner tool ([#250](#250)) ([42c27d5](42c27d5)) * Remove unused dependencies ([#281](#281)) ([c7de65e](c7de65e)) * **tests:** run verdaccio in-process ([#248](#248)) ([c17677d](c17677d)) * Update JSII version constraint ([#245](#245)) ([d89558f](d89558f)) * Update scheduled workflows to only run on open-constructs/cdk-terrain ([#256](#256)) ([ba408cf](ba408cf)) </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. |
Summary
Introduce a Terraform-compatible CLI feature/version validator that can be reused by feature PRs whose support depends on both the selected CLI product and its version.
This adds:
parseTerraformCliVersion()to detect Terraform vs OpenTofu from the first line of plainversionoutput:Terraform vX.Y.Z->terraformOpenTofu vX.Y.Z->opentofuValidateTerraformFeatureVersion, a single validation class for the matrix:terraform/opentofu) -> semver constraintversion -json-style output is not used to infer the product, because OpenTofu keeps the Terraform-compatibleterraform_versionkey.Intended downstream use
This is meant to unblock/reduce duplication for the S3
useLockfilework in:useLockfilefield and updatedynamodbTabledeprecated JSDoc #234A follow-up PR can add the backend-specific validation with:
If future features land at different times, the same class can encode different product constraints, for example:
Test plan
yarn jest packages/cdktn/test/validations.test.ts --runInBandyarn lerna run --scope cdktn buildyarn nx test cdktn --runInBand