Skip to content

feat: manage vended CDK project dependencies with minor-version pinning#1777

Open
jesseturner21 wants to merge 5 commits into
mainfrom
feat/managed-dependency-pinning
Open

feat: manage vended CDK project dependencies with minor-version pinning#1777
jesseturner21 wants to merge 5 commits into
mainfrom
feat/managed-dependency-pinning

Conversation

@jesseturner21

@jesseturner21 jesseturner21 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Description

Problem

The CLI vends projects with caret (^) dependency ranges in agentcore/cdk/package.json, so any upstream minor release (@aws/agentcore-cdk, aws-cdk-lib, …) can land in a customer's project without any CLI change — breaking template code or the CLI's ability to interact with the project. The CLI needs to own these versions on the customer's behalf while staying out of the way of dependencies the customer added themselves.

Solution

Pin to minor, let patches float. Managed dependencies are written as tilde ranges (~x.y.z); @aws/agentcore-cdk (L3 constructs, prerelease-versioned) is pinned exactly. A dependency is "managed" iff its name appears in the CLI's vended asset src/assets/cdk/package.json — that asset, baked into each CLI release, is the single source of truth for both the managed list and the known-good versions. Everything else in the customer's file is never touched.

On every agentcore deploy (headless and TUI), a preflight step:

  1. Skew check — if the project declares a managed dep with a higher minor/major than this CLI expects (e.g. a teammate on a newer CLI updated it), throw: "This project requires a newer version of the AgentCore CLI. Run npm install -g @aws/agentcore@latest and retry." Higher patch is fine — that's the point of tilde.
  2. Migrate — projects created before pinning (caret ranges) are rewritten to the pinned form with a one-time explanation.
  3. Sync — managed deps are updated to the current CLI's values; user-added deps are left byte-for-byte untouched; non-semver specifiers (file: bundled-tarball overrides, git:, …) are skipped with a warning, never rewritten.
  4. Install (only if something changed) — run an incremental npm install in agentcore/cdk/ that reconciles the edited package.json against the existing lockfile; node_modules and the lockfile are never deleted, so user-added deps keep their resolved versions and installs stay warm. The install also runs as a self-heal when node_modules is missing even with a matching manifest. If the install fails, the pre-rewrite package.json is restored so a retry recomputes the same plan and re-attempts the install. No-op deploys stay fast.
  5. Report — print a summary of every change (old → new per dep, plus "Dependencies you added yourself were not changed.").

Preview modes: --dry-run and --diff run the sync in check-only mode — the notice reports what a real deploy would change (future tense), but nothing is written and no install runs.

Teardown: teardown deploys are never blocked by the sync — both skew and write/install failures downgrade to warnings, so dependency pinning can never prevent destroying a cost-incurring stack.

Opt-out: agentcore config disableDependencyManagement true skips migrate/sync/reinstall entirely; the skew check still runs but downgrades to a warning and deploy proceeds — an escape hatch if we ever ship a bad pin, and support for teams with their own dependency tooling.

High-level implementation

  • src/lib/dependency-management/ (new, self-contained) — one deep module behind a single function, syncManagedDependencies({vendedPackageJsonPath, projectDir, disabled}), designed to lift into the planned CLI refactor unchanged (zero imports from src/cli/). Internals: semver.ts (prerelease-aware parse/compare — the existing parseSemVer drops -alpha.N tags, which here would make an alpha downgrade look like a no-op), policy.ts (pure plan computation), messages.ts (single source of user-facing wording), and the rewrite/clean-reinstall logic. All notices/warnings are returned as data on the result; callers only display them, so the headless and TUI paths can't drift.
  • ErrorsCliVersionTooOldError (errorSource: 'user') and DependencySyncError ('client') in src/lib/errors/types.ts, registered in the telemetry ErrorName enum. All failure paths throw typed errors — never process.exit() — so telemetry classification keeps working.
  • Vended asset pinnedsrc/assets/cdk/package.json converted to the policy form, with tilde bases bumped to what today's caret ranges actually resolve to (e.g. constructs ^10.0.0~10.7.0, not ~10.0.0) so migration never silently downgrades an existing project. @aws/agentcore-cdk exact-pinned to 0.1.0-alpha.45.
  • Deploy integrationensureManagedDependencies() adapter (src/cli/operations/deploy/dependency-sync.ts) resolves the vended asset via getTemplatePath and reads the global-config opt-out; called as a "Sync CDK dependencies" step between validate and build in handleDeploy (actions.ts) and TUI preflight (useCdkPreflight.ts). The summary rides on DeployResult (so --json gets structured data; the human notice goes through onNotice, suppressed under --json), renders in the TUI DeployScreen, and feeds five new dep_sync_* deploy telemetry attributes.
  • ConfigdisableDependencyManagement added to GlobalConfigSchemaStrict; the generic agentcore config <key> <value> command handles it with no command changes.

Related Issue

Closes #1540

Documentation PR

N/A — behavior is self-describing via the deploy-time notices; can follow up in agent-docs if wanted.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Other (please describe):

Testing

40 new unit tests in src/lib/dependency-management/__tests__/ (16 sync + 12 policy + 12 semver), plus new useDevDeploy cases for the dev-flow notice/warnings:

  • sync.test.ts — end-to-end through the public function against a real temp project dir (only the npm subprocess mocked), one test per design-doc behavior: no-op deploy touches nothing and prints nothing; caret project migrates + installs incrementally (npm install invoked, node_modules/lockfile never deleted, migration notice includes the opt-out hint) while a user-added lodash survives untouched; missing node_modules self-heals with an install even when the manifest matches; higher-minor project throws CliVersionTooOldError with the upgrade wording; opted-out skew warns and leaves the file byte-identical; deleted managed dep is restored; file:bundled-agentcore-cdk.tgz override is skipped with a warning; npm failure wraps in DependencySyncError and restores the original manifest so a retry recomputes and reinstalls; unreadable package.json wraps in DependencySyncError; rewrite preserves user key order and unknown fields.

  • policy.test.ts — plan computation: skew on higher minor and major but not higher patch; prerelease-aware skew on the exact pin (alpha.50 > alpha.45 detected, older alpha upgraded); devDependencies managed and the user's section respected; user deps never touched.

  • semver.test.ts — prerelease ordering (0.1.0-alpha.19 < 0.1.0-alpha.20 < 0.1.0), specifier classification (exact/tilde/caret), and unsupported forms (file:, git+https:, workspace:, *, latest, compound ranges).

  • I ran npm run test:unit and npm run test:integ (unit: 411 files / 5956 tests pass; integ not run — no integ coverage touched)

  • I ran npm run typecheck

  • I ran npm run lint

  • If I modified src/assets/, I ran npm run test:update-snapshots and committed the updated snapshots

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the
terms of your choice.

@jesseturner21
jesseturner21 requested a review from a team July 16, 2026 19:46
@github-actions github-actions Bot added size/xl PR size: XL agentcore-harness-reviewing AgentCore Harness review in progress labels Jul 16, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Jul 16, 2026
@github-actions github-actions Bot removed the agentcore-harness-reviewing AgentCore Harness review in progress label Jul 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Package Tarball

aws-agentcore-0.24.1.tgz

How to install

gh release download pr-1777-tarball --repo aws/agentcore-cli --pattern "*.tgz" --dir /tmp/pr-tarball
npm install -g /tmp/pr-tarball/aws-agentcore-0.24.1.tgz

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Jul 16, 2026
@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 40.09% 14959 / 37307
🔵 Statements 39.37% 15957 / 40523
🔵 Functions 34.21% 2550 / 7453
🔵 Branches 33.59% 9980 / 29703
Generated in workflow #4143 for commit e026010 by the Vitest Coverage Report Action

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Jul 17, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Jul 17, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Jul 17, 2026
…mational warnings don't exit 2

The bundled-tarball override (file:bundled-agentcore-cdk.tgz) always yields a
'left unmanaged' dep-sync warning in e2e/dev builds. Merging depSync.warnings
into postDeployWarnings made every such deploy exit 2, failing e2e deploy
assertions. Dep-sync warnings are informational: print them from
printDeployResult (headless CLI) instead — the TUI and dev paths already
render result.dependencySync.warnings separately.
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Jul 17, 2026
…ilure, persist dev notice, print warnings on failed deploys, never block teardown

Round-2 review fixes for managed dependency pinning (#1540):

- handleDeploy: every explicit failure return after the sync step now
  carries dependencySync, so dep_sync_* telemetry and the rewrite notice
  survive deploys that fail at a later step (not just the catch path).
- syncManagedDependencies: on npm install failure, restore the pre-rewrite
  package.json before throwing DependencySyncError — otherwise a retry sees
  a matching manifest plus a stale node_modules, skips the install, and
  deploys against the old installed tree (the exact skew the feature
  prevents). Tests pin restore + successful retry.
- Dev TUI: the dep-sync notice/warnings arrived in the same render batch
  that transitioned out of 'deploying', so they were visible for at most
  one frame. They now persist into the post-deploy modes (harness chooser /
  InvokeScreen) and print to the normal buffer on the browser-launch path.
- Headless CLI: the non-JSON failure branch now prints
  dependencySync.notice/warnings to stderr, so a failed deploy still
  explains the package.json rewrite and any downgraded skew.
- Teardown: DependencySyncError (write/install failure) at both sync call
  sites is downgraded to a warning via teardownSyncFailureResult and the
  teardown proceeds — extending the treatSkewAsWarning invariant that
  nothing about pinning may block destroying a cost-incurring stack.
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xl PR size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: CLI should manage dependencies of created projects.

1 participant