Skip to content

chore(deps): use caret ranges for unbundled runtime dependencies - #503

Merged
so0k merged 2 commits into
open-constructs:mainfrom
X-Guardian:chore/deps-semver-ranges
Oct 13, 2026
Merged

so0k merged 2 commits into
open-constructs:mainfrom
X-Guardian:chore/deps-semver-ranges

Conversation

@X-Guardian

@X-Guardian X-Guardian commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Description

The published @cdktn/* packages pin every runtime dependency to an exact version. When one of those dependencies ships a security patch, users can't pick it up with npm update, npm audit fix or a lockfile refresh. They have to wait for a CDKTN release or add overrides.

This PR switches runtime dependencies to ^ ranges in the packages whose dependencies install into the user's node_modules:

Package Now ranged
@cdktn/hcl2cdk @babel/generator, @babel/template, @babel/types, camelcase, deep-equal, glob, graphology, graphology-types, reserved-words, zod
@cdktn/commons ci-info, cross-spawn, follow-redirects, fs-extra, log4js, semver, strip-ansi, validator
@cdktn/provider-schema deepmerge, fs-extra, semver
@cdktn/provider-generator fs-extra, glob
@cdktn/hcl2json fs-extra
cdktn-cli yargs

cdktn-cli marks yargs and @cdktn/hcl2cdk as esbuild externals. That makes them, and everything hcl2cdk depends on, real installs on the user's machine.

Where exact pins still apply:

  • @cdktn/cli-core, cdktn core, and the rest of cdktn-cli's dependencies. cli-core is bundled into cdktn-cli by esbuild, and cdktn ships its dependencies as bundledDependencies, so a range would never reach users. For these packages, a security fix still needs a CDKTN release.
  • constructs, codemaker, jsii, jsii-pacmak and jsii-rosetta. They have to match the jsii toolchain, and the upgrade workflow already excludes them.
  • @sentry/node in @cdktn/commons. cdktn-cli bundles one copy of commons and loads a second from node_modules through the external @cdktn/hcl2cdk. The Sentry SDK shares its client only between copies of the same SDK version, so the installed copy has to resolve the same version as the bundled one, or its breadcrumbs and errors are dropped. It stays exact alongside the pins in cli-core and cdktn-cli.
  • prettier 2.8.8 in hcl2cdk. It formats cdktn convert output, so even a minor bump could change generated code.

Lockfile. Besides the new ranges, pnpm install merged a few indirect dependencies onto versions the repo already uses. These are all patch or minor bumps:

  • @babel/types 7.29.0 → 7.29.7
  • semver 7.8.0 → 7.8.5
  • hasown 2.0.2 → 2.0.4
  • side-channel 1.1.0 → 1.1.1
  • @jridgewell/sourcemap-codec 1.5.0 → 1.6.0

Three packages drop out of the lockfile. The repo's own installs still resolve exactly through the lockfile and minimumReleaseAge.

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
  • 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

@X-Guardian
X-Guardian requested a review from a team as a code owner October 12, 2026 17:56

@so0k so0k 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.

One change is needed before it merges: @sentry/node in @cdktn/commons has to stay exact.

I'll push that fix commit to this branch, so there is nothing you need to do for it.

@sentry/node must stay exact in @cdktn/commons

cdktn-cli ends up with two copies of @cdktn/commons at runtime:

  • one compiled into the esbuild bundle, with @sentry/node frozen at 10.73.0;
  • one loaded from node_modules through @cdktn/hcl2cdk, which is an esbuild external and resolves its own @sentry/node.

The Sentry SDK keeps its global state under a key that includes the SDK version (__SENTRY__[SDK_VERSION] in @sentry/core's carrier.js). Two copies share the client the CLI initialises only when they are the same version. Today both are 10.73.0. With ^10.73.0 a fresh install resolves 10.76.2, and the breadcrumbs and errors raised from the installed copy (the convert path) go to a scope with no client. Nothing crashes and nothing is logged; the data is dropped.

The range also buys little here: the copy the CLI actually initialises is the bundled one, which only a CDKTN release can change.

This comes from reading packages/cdktn-cli/build.ts and the SDK source;

The fix is a one-line revert in packages/@cdktn/commons/package.json plus the matching specifier in pnpm-lock.yaml. The resolved version does not change. The description's table should drop @sentry/node from the @cdktn/commons row and list it under the exact pins.

sherif

sherif@1.13.0 goes from 20 issues on main to 27 on this branch. All seven new ones are multiple-dependency-versions errors from the exact/ranged split:

Dependency Exact in Ranged in
@sentry/node cli-core, cdktn-cli commons
semver cli-core, cdktn, cdktn-cli commons, provider-schema
strip-ansi cli-core, cdktn-cli commons
ci-info cli-core commons
cross-spawn cli-core commons
zod cli-core hcl2cdk
glob cdktn-cli hcl2cdk, provider-generator

Only @sentry/node has a runtime consequence. The other six are specifier inconsistencies: the repo still resolves one version of each through the lockfile. They are not blocking for this PR. They do work against the cleanup tracked in #246, where today's main report is now posted, so the follow-up there needs to settle how the bundled packages declare these dependencies before sherif can be enforced in CI.

Notes

  • This changes what users' installs resolve, so it needs a release-notes line.
  • The lockfile also moves @babel/generator 7.29.1 → 7.29.7 and @babel/helper-validator-identifier 7.28.5 → 7.29.7, which the description does not list.
  • The earlier red check was read.test.ts hitting Jest's 5-second default while downloading a provider. It passed on re-run with no code change.

cdktn-cli bundles commons with @sentry/node 10.73.0, and also loads a
second copy of commons from node_modules through the external
@cdktn/hcl2cdk. The Sentry SDK shares its client only between copies of
the same SDK version, so a ranged install (10.76.2 today) would leave
the installed copy without a client and drop its breadcrumbs and errors.
@so0k
so0k enabled auto-merge (squash) October 13, 2026 02:58
@so0k
so0k merged commit e722357 into open-constructs:main Oct 13, 2026
265 checks passed
so0k added a commit that referenced this pull request Oct 24, 2026
Add sherif to the Quality workflow so mismatched dependency specifiers
and unsorted dependency keys fail PR CI. knip only checks whether a
dependency is used, not how it is declared across the workspace.

Bring main to zero findings:
- sort the three unordered dependency blocks
- align tsx, tsc-files and the Babel specifiers of
  tools/generate-function-bindings with the rest of the workspace
- use caret ranges for ci-info, cross-spawn, fs-extra, glob, semver,
  strip-ansi and zod in the bundled packages (cli-core, cdktn-cli,
  cdktn) to match the installed packages (#503). The lockfile resolves
  the same versions, so the bundled output does not change.
- ignore prettier, @types/prettier and constructs, whose differing
  specifiers are intentional
- ignore packages-without-package-json, which flags workspace globs
  that match plain grouping directories

Refs #246
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.

3 participants