Skip to content

feat(cli): add a typescript-pnpm init template and deprecate Yarn - #422

Merged
so0k merged 8 commits into
open-constructs:mainfrom
X-Guardian:feat/typescript-pnpm-yarn-templates
Oct 12, 2026
Merged

so0k merged 8 commits into
open-constructs:mainfrom
X-Guardian:feat/typescript-pnpm-yarn-templates

Conversation

@X-Guardian

@X-Guardian X-Guardian commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Description

cdktn init --template=typescript-pnpm scaffolds a TypeScript project managed by pnpm. Until now --template=typescript hardcoded npm everywhere: the install in the sscaff hook, the package.json scripts, the help text, and the post-convert npm run get. A pnpm user ended up with a package-lock.json beside their pnpm-lock.yaml, and cdktn provider add on a pnpm project ran npm install. The project itself moved to pnpm in #170.

Stored as a variant. typescript/ is the one TypeScript template; its help, package.json and cdktf.json take their commands from the template variables pmRun, pmAdd and pmExec, and its hook checks for, installs with, and pins the manager named by packageManager. typescript-pnpm/ carries only pnpm-workspace.yaml, which approves the build scripts of the template's dependencies (pnpm 11 fails the install otherwise). TEMPLATE_VARIANTS in cli-core/init.ts maps the variant to its base plus those four strings; it is the only name-keyed table, and --dist validation and the --from-terraform-project gate resolve through it. init() makes one sscaff call on the base; the base hook's post copies the variant directory into the project right before installing, so a failed prerequisite check (missing or too-old pnpm) writes nothing and anything already in the directory is untouched, while an install failure keeps the scaffolded files. The pnpm template requires pnpm 10.26 or newer (allowBuilds) and does not need npm on PATH.

The CLI resolves the package manager from the project, not the template name. detectNodePackageManager(dir) in @cdktn/commons reads the packageManager field first (corepack), then pnpm-lock.yaml, .yarnrc.yml, yarn.lock, else npm. provider add and provider list use it (pnpm add -E, pnpm list --json --depth 0), so does the post-convert run get in cdktn init, and so does cdktn debug, so there is one detector and remote templates get the right command too. Quiet flags are emitted per manager: pnpm has no --no-progress, Yarn Berry rejects both.

Yarn. Yarn classic (1.x) is archived upstream; Yarn Berry (2+) is not supported by this CLI. Both now print a one-time warning pointing to #492, which documents what works and fails on Berry, the workarounds, and the projen route. On Berry, provider list, provider upgrade and debug fail with a clear usage error instead of a confusing yarn list failure; provider add keeps working. The typescript-yarn template proposed in the first revision of this PR is dropped (see the thread). Vote on #492 if you need native Berry support.

Integration test. test/typescript/init-pnpm-template scaffolds the template, synthesizes it, adds a pre-built provider through pnpm and lists it through the pnpm listing path, and covers three failure modes through a shimmed pnpm: too old and missing (directory left empty), and an install failure (scaffolded files kept).

Four pre-existing bugs fixed in passing, each a one-liner met while testing this path:

  • helper/init.ts built an ExecSyncOptions (including stdio: "ignore" under --silent) and never passed it, so --silent leaked output from the post-convert run get.
  • init() never passed cdktfVersion to providerAdd, so cdktn init --cdktf-version=X --providers=aws scaffolded and then failed with cannot use version 0.0.0.
  • The --from-terraform-project warning said "the typescript template" where several now qualify.
  • jest.config.js annotated its config with ts-jest's deprecated InitialOptionsTsJest.

Relates to #79: this adds one template through the overlay system rather than a full copy, and does not change the direction discussed there.

Telemetry

Template names flow into the init telemetry automatically. Recording the detected package manager in usage metrics is a follow-up once #411 lands.

Checklist

  • I have updated the PR title to match CDKTN's style guide
  • I have run the linter on my code locally
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation if applicable (follow-up: list typescript-pnpm in the init docs)
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works if applicable
  • New and existing unit tests pass locally with my changes

🤖 Generated with Claude Code

@X-Guardian
X-Guardian requested a review from a team as a code owner September 11, 2026 12:50
@sakul-learning

sakul-learning commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Reviewed 648dc2acbbc3. Builds and the configured test targets pass; one path introduced by the new yarn template is broken.

typescript-yarn: provider listing goes through a Yarn 1-only command

templates/typescript-yarn/.hooks.sscaff.js pins packageManager: yarn@<current 4.x> into the generated package.json, and the new detection getter in packages/@cdktn/cli-core/src/lib/dependencies/package-manager.ts:281 prefers that field, so listProviderPackages() (:444) routes yarn projects to listYarnPackages() (:356), which runs yarn list --json. Yarn 2+ (Berry) removed list:

$ yarn list --json
Usage Error: Couldn't find a script named "list".

exec in @cdktn/commons rejects on a non-zero exit, so listYarnPackages throws, getCurrentlyInstalledVersion rethrows it as Failed to list packages: (dependency-manager.ts:193), and allProviders (:503) propagates. In a project scaffolded with --template=typescript-yarn, cdktn provider list, cdktn provider upgrade and cdktn debug all fail. cdktn provider add is unaffected — it never lists, and yarn add -E does work on Berry.

It only fails in the configuration the template is aiming for: without corepack the pin cannot switch versions, Yarn 1.22 performs the install, and yarn list --json works.

Berry does have an equivalent — yarn info --name-only --all --json returns "@cdktn/provider-random@npm:15.0.0", one JSON string per line — so this needs a Berry branch plus an update to yarnListSchema (:168), which currently expects {data:{trees:[…]}}.

Two smaller items

  1. templates/typescript/.hooks.sscaff.js:9 adds exports.pre = () => requirePackageManager("npm"), and sscaff runs pre on every pass, so --template=typescript-pnpm and --template=typescript-yarn still require npm on PATH even though they install with pnpm/yarn. The isOverlayBase guard only exists in post; sscaff passes the variables to pre, so the check can move there.
  2. The added tests cover detection only. The new per-manager quiet-flag branch in NodePackageManager.addPackage (:324) — npm pushes --silent --no-progress, pnpm --silent, yarn neither — and the pnpm listing path have no coverage. Both are pure argument construction and cheap to test.

@so0k

This comment was marked as resolved.

@X-Guardian

Copy link
Copy Markdown
Contributor Author

I'll leave this PR here for you to do with what you want then.

My personal view is that currently cdktn init is broken for the package manager it uses itself, pnpm which is a bit embarrassing. This is just two variants on the typescript template, following the python/python-pip pattern already in place. You are talking as if there have been lots of templates added, which is not correct.

@so0k

so0k commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

I'll leave this PR here for you to do with what you want then.

My personal view is that currently cdktn init is broken for the package manager it uses itself, pnpm which is a bit embarrassing. This is just two variants on the typescript template, following the python/python-pip pattern already in place. You are talking as if there have been lots of templates added, which is not correct.

sure, I'd remove yarn and keep the pnpm fixes. I am reluctant to touch cdktn init is all - I highlighted this in past PRs that work on the init templates

EDIT:

but I'll wait for Jon's opinion if we keep Yarn (and fix the commands) or just stick to pnpm (as pointed out we use pnpm for this project).

@jsteinich

Copy link
Copy Markdown
Contributor
  • I don't think we should add a yarn template - it doesn't seem popular enough to warrant its inclusion
  • I can see the argument for adding pnpm as we do use it with the project
  • I'd really like to see the addition of new templates being driven by actual community requests for it. @X-Guardian perhaps this does serve as your request, but it's not clear that you'd actually be using the template from your comments.
  • In the past I would use init for reproducing reported bugs; however, these days AI can set up a full reproduction projection much easier. For real projects, I just copy an existing one (yes, I know projen was designed to handle that flow). I'm not sure what other's experiences are, but it seems like we should find out before decided to invest time into init expansions / improvements.
  • If we do add a new template, we should add integration tests to ensure that it actually functions correctly.

so0k and others added 2 commits October 9, 2026 17:19
… classic

Drop the typescript-yarn overlay template. Yarn classic is unmaintained
and Yarn Berry is not supported by the CLI; both now print a warning
pointing to open-constructs#492, and provider listing refuses Yarn Berry with a clear
error instead of failing on the removed `yarn list` command.

Resolve the package manager of a scaffolded project from the project
itself (packageManager field, then lockfiles) rather than from the
template name, so remote templates get the right `run get` too. The
base typescript template no longer requires npm on the overlay pass.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The pnpm overlay now carries its own cdktf.json (pnpm exec tsx) and a
pnpm-workspace.yaml that approves the build scripts of its dependencies,
so the scaffolded project needs neither npm on PATH nor pnpm's interactive
build approval. The template requires pnpm 10 or newer.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@so0k
so0k force-pushed the feat/typescript-pnpm-yarn-templates branch from 648dc2a to 18c2a3e Compare October 9, 2026 11:00
@so0k so0k changed the title feat(cli): add typescript-pnpm and typescript-yarn init templates feat(cli): add a typescript-pnpm init template and deprecate Yarn Oct 9, 2026
@so0k
so0k requested a review from jsteinich October 9, 2026 11:01

@jsteinich jsteinich left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few things from a pass over the pnpm path; details inline.

Run the overlay template's pre hook before the base template writes
anything, so a missing or outdated pnpm leaves the directory empty. The
pnpm template needs 10.26 or newer, where allowBuilds exists. Usage
errors from provider listing now reach the user unchanged from provider
upgrade, and Yarn classic keeps its --silent --no-progress flags.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017s2LYuggMYP9LUupxcu9Q1
…e detector

The typescript template takes its package manager commands from
template variables, so typescript-pnpm carries only pnpm-workspace.yaml
and one hook checks for, installs with, and pins the selected manager.
The variant's files are written before the base, which installs; when
the base pass fails before writing anything, its files are removed so
the directory is left as a single-template failure leaves it.

detectNodePackageManager moves to @cdktn/commons so cdktn debug and the
provider commands agree on the package manager.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017s2LYuggMYP9LUupxcu9Q1
@so0k

so0k commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Follow-up, not for this PR: python and python-pip are full copies, and the variant mechanism introduced here would collapse them the same way.

What actually differs between them: the app command in cdktf.json (pipenv run python main.py versus python3 ./main.py), the run line and the provider-install paragraph in help, and in the hook the probe (pipenv versus pip3) and the install step (three pipenv install calls versus writing requirements.txt and pip3 install). main.py and .gitignore are byte-identical. main-test.py has already drifted: the pipenv copy has a commented-out stack and assert True, the pip copy constructs a real TerraformStack. That drift is the cost the variant mechanism removes.

Shape of the change: python/ becomes the base with {{ pm* }} placeholders and one hook branching on ctx.packageManager; python-pip/ carries nothing (or a requirements.txt seed), and Pipfile stays the pipenv-only file, the equivalent of pnpm-workspace.yaml. Same ordering (variant first, base installs last). The python hooks currently process.exit(1) from pre, which bypasses sscaff's error path and the rollback in init(); moving them to throw belongs in the same change.

Tracking under #79.

@sakul-learning

Copy link
Copy Markdown
Contributor

packages/@cdktn/cli-core/src/lib/init.ts:118-134 can delete pre-existing user files when the TypeScript/pnpm base preflight fails.

checkForEmptyDirectory() deliberately permits dotfiles/directories and README.md. The variant pass adds pnpm-workspace.yaml, but variantFiles = fs.readdirSync(destination) then snapshots every destination entry, including pre-existing ones. If the base pre hook rejects missing or old pnpm before writing another file, baseWroteNothing is true and the cleanup loop calls fs.removeSync() on every snapshotted entry.

A common destructive path is:

  1. git init
  2. cdktn init --template typescript-pnpm without pnpm, or with pnpm < 10.26
  3. the base preflight fails
  4. cleanup recursively removes both pnpm-workspace.yaml and the pre-existing .git directory

The same applies to .env, .gitignore, .vscode/, and README.md. The exported init() API can also receive a non-empty destination without the CLI guard.

Could the rollback snapshot the destination before rendering the variant, then remove only paths newly created by the variant? A regression test should create an allowed pre-existing sentinel—ideally .git/HEAD, plus .env or README.md—trigger a missing/old-pnpm failure, and verify that the sentinel survives while pnpm-workspace.yaml is removed. This is a data-loss blocker for the current sequencing.

so0k and others added 2 commits October 11, 2026 22:02
… fails

The rollback after a failed base pass removed every entry in the
destination, including a .git directory or README that the empty
directory check allows. It now removes only what the variant pass added.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017s2LYuggMYP9LUupxcu9Q1
…fold pass

init() scaffolds the base template once; the base post hook copies the
variant's sibling directory into the project before installing, so a
failed prerequisite check has nothing to roll back and whatever the
directory held before init is never touched.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017s2LYuggMYP9LUupxcu9Q1
…e project

A remote template is scaffolded as-is whatever its directory is called;
only a template shipped with the CLI can be a variant or narrow the
--dist validation. Inside a pnpm workspace, `pnpm list` reports every
project, so the listing now reads the entry for the working directory.

The pnpm version pin accepts only a complete version, and a packageManager
field pinned to a scoped registry URL resolves to Yarn Berry.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017s2LYuggMYP9LUupxcu9Q1
@so0k
so0k merged commit 81da164 into open-constructs:main Oct 12, 2026
263 checks passed
so0k added a commit that referenced this pull request Oct 12, 2026
…etrics and consent (#411)

The CLI stops sending anything to `checkpoint-api.hashicorp.com`. Usage
analytics now go to the project's own Sentry as counted metrics, behind
a separate `sendUsageTelemetry` consent flag in `cdktf.json`. Resolves
#48.

### What changes

- The HashiCorp transport (`commons/src/checkpoint.ts`) and its test are
deleted, and `nock` leaves `cli-core`. The user and project ids move to
`commons/src/identity.ts`. `commons/src/telemetry.ts` holds the whole
contract: the consent gate, the metrics, and the single bounded
`flushTelemetry`.
- Consent: `initializErrorReporting` prompts once per unset flag (stdin
and stdout are TTYs, not CI) and saves the answer to `cdktf.json`;
`convert` asks before it chdirs into its temporary project. The first
decision captured in a process wins: a nested command (`convert` →
`init` → `get`, `init` → `get`, `provider add` → `get`) returns from
reporting init without reading flags, prompting or building a second
client. `parseConfig`, the usage reader and the crash reader share one
tri-state reader: booleans and `"true"`/`"false"` count, anything else
reads as unset. Usage telemetry follows `CHECKPOINT_DISABLE` > decision
at command start > `sendUsageTelemetry` > on; with only usage consent no
error events are sent.
- Run model: a run counts once as `cli.command.invoked` at start, then
once as `cli.command.completed` or `cli.command.error`, so `error /
invoked` is a failure rate. A nested operation (a deploy's synth, init's
get) adds only its own metrics; `init` completes after its nested get
succeeds.
- Failure paths that used to `process.exit(1)` (synth code-maker guard,
`watch --auto-approve`, Terraform availability check) throw
`Errors.Usage`, reaching the single failure path. The two self-exiting
synth paths count and flush themselves.
- `cli.error` counts every error built by the `Errors` factories by type
and command (never message or context); `cli.command.error` counts
failed runs. A handled Usage error counts only as `cli.error`.
- Command scope, consent and run state live in a `Symbol.for` store
(`process-state.ts`), because the esbuild bundles each carry their own
copy of commons.

| Metric | When emitted | Attributes (base: `command`, `ci`, `language`)
|
|---|---|---|
| `cli.command.invoked` | once per run, at start | base only |
| `cli.command.completed` | once per successful run | base only |
| `cli.command.error` | once per failed run | base + `error_type`
(`Usage`, `External`, `Internal`, `unexpected`) |
| `cli.synth.duration` | each synth, ms distribution | base only |
| `cli.error` | each error from the `Errors` factories | `type`,
`command` only |

Sentry itself adds the random install id (`~/.cdktf/config.json`),
release `cdktn-cli-<version>`, environment `production`, and server
`cdktn-cli`. Never sent: stack names, ids, paths, hostname or username,
error messages and context, `SENTRY_*` values.

### Migration notes

- cdktn sends no data to HashiCorp. The new `sendUsageTelemetry` flag is
independent of `sendCrashReports`; the six templates carry it.
- Interactive runs ask once about each unset flag. The crash-reporting
prompt also appears now where `sendCrashReports` is missing; it never
fired before because a missing key was read as "no".
- `provider list` and `provider upgrade` now initialise reporting like
the other commands, so their first interactive run in a project with
unset flags shows the prompts before the output.
- CI and piped runs never prompt: usage telemetry stays on by default
(now to Sentry), crash reporting stays off. Builds without a Sentry DSN
send nothing.

### Coverage

- Counted: `convert`, `deploy`, `destroy`, `diff`, `get`, `init`,
`list`, `output`, `synth`, `watch`, `provider add`, `provider list`,
`provider upgrade`. Not counted: `login` (handles a credential), `debug`
(must work when the environment is broken, without consent or reporting
init), shell completion, `--help`, `--version` and unknown commands (no
handler runs).
- A package-manager attribute is a follow-up after #422.

### Testing

- Unit: a real v10 client with a capturing transport asserts the metric
names, attributes and the exact multiset of run metrics; raw-envelope
scans assert no host identity; the consent matrix and the config
normalisation tables.
- Handler level: `convert` prompts and persists before its chdir, and
never prompts on piped stdin; each former `process.exit` guard yields
one `cli.command.error` and one flush.
- Bundle-level delivery is covered by the e2e in #414.

Stack: 3 of 6 — #409 → #410 → **#411** → #412 → #413 → #414

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
so0k added a commit that referenced this pull request Oct 12, 2026
… package manager in usage metrics (#412)

Every usage metric now carries the environment it ran in: the installed
Terraform or OpenTofu binary and version, the target versions the
project declares, the OS and architecture, and the project's package
manager. This answers which binaries, platforms and package managers
people actually run. Part of #48.

### What changes

- The base attribute set of every metric grows by the attributes below
(`commons/src/telemetry.ts`). No new metrics are added.
- `commons/src/terraform.ts` probes the binary with `<binary> version`,
lazily, at most once per process, shared across bundle copies via
process state. The probe is killed after 1500 ms. A failed or timed-out
probe reports `binary: unknown`; a binary that cannot be spawned reports
`missing`. This replaces the `terraform version -json` call that ran at
module import in every commons copy regardless of consent; with usage
telemetry off, metrics trigger no probe.
- `cdktn debug` uses the same probe and prints `"terraform": null` when
it fails.
- `cli-core` captures the project's target attributes once at init from
the project that is running, so later metrics in the run carry the same
values.
- Values are validated before they become attributes: versions are
reduced to `MAJOR.MINOR.PATCH` and sent only for a recognised product;
ranges are canonical semver or the literal `invalid`. No path, binary
location or free text is forwarded.
- The package manager is detected once at command start in the project
the run started in, and is omitted when it cannot be determined. Only
members of a closed set are sent.

| Attribute | Value | Source |
|---|---|---|
| `os`, `arch` | `process.platform`, `process.arch` | Node |
| `binary` | `terraform`, `opentofu`, `unknown`, `missing` | version
probe |
| `binary_version` | `MAJOR.MINOR.PATCH`, only for `terraform` or
`opentofu` | version probe |
| `target_terraform`, `target_opentofu` | canonical semver range, else
`invalid` | `targetVersions` in `cdktf.json`, else the CLI defaults |
| `targets_declared` | boolean | `cdktf.json` has a `targetVersions`
block |
| `validate_installed_binary` | boolean | `validateInstalledBinary ===
true` in `cdktf.json` |
| `package_manager` | `npm`, `pnpm`, `yarn`, `yarn-berry` (TypeScript);
`pip`, `pipenv` (Python); `maven`, `gradle` (Java); `nuget`; `go` |
TypeScript: `detectNodePackageManager` from #422. Python: `pipenv` if
the `app` command uses it, else `pip`. Java: `build.gradle` present,
else `maven`. C# and Go: constant |

All are added to every metric that carries the base attributes
(`command`, `ci`, `language`, from #411), except `cli.error`, which
keeps only `type` and `command`.

### Not in this PR

- A shell wrapper named `terraform` that runs the real binary as a child
is killed only at the wrapper, so the probe can wait for the child to
close stdout. Shims that exec or symlink (tfenv, asdf, mise) are
unaffected. Fixing it means changing `exec` in `commons/src/util.ts`.

### Testing

- Unit: the sorted attribute key set of `cli.command.invoked` is pinned,
so an extra attribute fails; target attributes captured at init appear
on later metrics.
- Unit with fixture binaries: the probe runs once, a hanging binary
resolves `unknown` at the timeout, a missing binary resolves `missing`,
an unrecognised product sends no version.
- Table-driven validation of versions and ranges, including prerelease
and build text.
- Package manager: each detected value appears on `invoked` and on the
terminal metric; it is absent outside a project, and a detector result
outside the closed set is dropped.

Stack: 4 of 6 — #409 → #410 → #411 → **#412** → #413 → #414

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
so0k pushed a commit that referenced this pull request Oct 27, 2026
🤖 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants