Skip to content

fix: select deployed target's stack at Persist instead of stackNames[0]#1612

Merged
aidandaly24 merged 1 commit into
mainfrom
fix/deploy-target-stack-selection
Jun 23, 2026
Merged

fix: select deployed target's stack at Persist instead of stackNames[0]#1612
aidandaly24 merged 1 commit into
mainfrom
fix/deploy-target-stack-selection

Conversation

@aidandaly24

Copy link
Copy Markdown
Contributor

Description

agentcore deploy --target <name> failed at the Persist deployment state step when the
target was not the first entry in aws-targets.json, erroring with Stack <first-target> does not exist — even though the requested target's stack deployed successfully. AWS resources were
left running while deployed-state.json was never written (orphaned infrastructure with no local
pointer for teardown/status).

Root cause. The vended CDK app (src/assets/cdk/bin/cdk.ts) synthesizes one stack per
target
in aws-targets.json, so synthResult.stackNames contains every target's stack. The
deploy flow used stackNames[0] for the deployability check and the Persist step
(getStackOutputs / buildDeployedState), while the deploy and diff steps correctly used
toStackName(project, target). When the deployed --target wasn't first in the file,
stackNames[0] pointed at a different (usually undeployed) stack, so DescribeStacks at Persist
threw.

Fix. Introduce a pure selectTargetStack(stackNames, projectName, targetName) that matches the
deterministic toStackName(project, target) against the synthesized stacks — making selection
ordering-independent — and returns a clear ValidationError (naming the synthesized stacks and
the expected one) if the target's stack is absent. That selected stack name is now authoritative for
the deployability check (scoped to the single stack instead of looping DescribeStacks over every
target), diff, deploy, and Persist. The redundant targetStackName local is removed.

Single-target projects are unaffected (where stackNames[0] happened to already be the right stack).

Scope note (for reviewers)

This fixes the CLI deploy path (handleDeploy). The TUI deploy path (useDeployFlow.ts)
has a separate, related multi-target limitation — it has no --target selector (the --target
flag always routes to the CLI path), always uses awsTargets[0]/stackNames[0] (which are mutually
consistent, so it is not the same cross-mismatch bug), and persists state for only the first of N
deployed targets. That is intentionally out of scope here and should be tracked as a follow-up;
the new selectTargetStack is exported so it can be reused there.

Related Issue

No existing GitHub issue. Reported via internal feedback:

  • Aperture: 9013745d-b4aa-4b20-a1ca-e03fa712ffbf
  • SIM: V2260713830

Documentation PR

N/A — bug fix, no user-facing documentation change.

Type of Change

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

Testing

How have you tested the change?

  • I ran npm run test:unit and npm run test:integ
  • 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 — N/A, src/assets/ not modified

Unit (selectTargetStack) — 6 cases: ordering (--target qa with qa first vs. second),
single-target, underscore normalization, empty assembly, and target-with-no-matching-stack. Verified
red→green by reintroducing stackNames[0] (the ordering tests fail) and reverting (they pass).
Full suites: unit 5415 passed, integ 310 passed, typecheck clean, lint 0 errors.

End-to-end on live CloudFormation (us-east-1) with a 2-target project
(default first, qa second):

Build Command Result
main (before) deploy --target qa --yes --json ❌ Deploy step ✓ (qa stack CREATE_COMPLETE) → PersistStack with id AgentCore-<project>-default does not exist; deployed-state.json left {"targets":{}}
this branch (after) deploy --target qa --yes --json {"success":true,"targetName":"qa","stackName":"AgentCore-<project>-qa", ...}; Persist SUCCESS; deployed-state.json keyed under qa; only the qa stack created/described

All test CloudFormation stacks and resources were torn down after verification.

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 — N/A
  • 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.

The vended CDK app synthesizes one stack per target in aws-targets.json,
so synthResult.stackNames contains every target's stack. The deploy flow
used stackNames[0] for the deployability check and the Persist step
(getStackOutputs / buildDeployedState), while deploy/diff correctly used
toStackName(project, target). When --target was not first in
aws-targets.json, Persist described the wrong (often undeployed) stack and
failed with "Stack <first-target> does not exist", leaving AWS resources
live with an empty deployed-state.json.

Add a pure selectTargetStack(stackNames, project, target) that matches the
deterministic toStackName, making selection ordering-independent, and make
that stack name authoritative for the deployability check (now scoped to
the single stack), diff, deploy, and Persist. Remove the redundant
targetStackName.

Verified end-to-end on CloudFormation: deploy --target qa (qa second in
aws-targets.json) failed at Persist before the fix and succeeds after,
recording deployed-state under qa.
@aidandaly24 aidandaly24 requested a review from a team June 23, 2026 14:54
@github-actions github-actions Bot added the size/s PR size: S label Jun 23, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Jun 23, 2026
@github-actions github-actions Bot added the agentcore-harness-reviewing AgentCore Harness review in progress label Jun 23, 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 Jun 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Package Tarball

aws-agentcore-0.20.2.tgz

How to install

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

@agentcore-cli-automation agentcore-cli-automation left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LGTM — narrow, well-targeted bug fix.

A few things I checked and liked:

  • Correctness of the selection logic. selectTargetStack matches against the deterministic toStackName(project, target) from import-utils.ts (lines 298–300), which is the same formula the vended CDK app uses in src/assets/cdk/bin/cdk.ts (lines 19–21), so the CLI's selection stays in lockstep with synthesis (including underscore→dash normalization, covered by the test on actions.test.ts:82-85).

  • Behavior change in the deployability check is the right call. Switching checkStackDeployability(target.region, [stackName]) (actions.ts:459) from the full stackNames array to just the deployed target's stack means a sibling target's in-progress/failed stack can't spuriously block this deploy. The inline comment makes the intent clear.

  • Threading is complete. All four downstream uses of the selected name (deployability check, diff, deploy, persist via getStackOutputs/buildDeployedState) now consume the same stackName, and the dead targetStackName local is gone with no stragglers (grep targetStackName src/ is empty).

  • Tests are clean. The new selectTargetStack cases test a pure function with real inputs — no mocking — and explicitly cover the ordering-independence regression (actions.test.ts:67-75) plus the empty-assembly and no-matching-stack failure modes. Author also reports red→green verification by reintroducing stackNames[0].

  • Scope is appropriately narrow. The TUI path's analogous stackNames[0] in useDeployFlow.ts:265 is correctly called out as out-of-scope in the PR description, and selectTargetStack is exported so the follow-up can reuse it. Worth opening a tracking issue if one doesn't already exist.

No blocking issues.

@github-actions github-actions Bot removed the agentcore-harness-reviewing AgentCore Harness review in progress label Jun 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 36.99% 13527 / 36564
🔵 Statements 36.27% 14383 / 39652
🔵 Functions 31.62% 2320 / 7337
🔵 Branches 30.78% 8915 / 28962
Generated in workflow #3763 for commit bef4616 by the Vitest Coverage Report Action

@aidandaly24 aidandaly24 merged commit 93d104c into main Jun 23, 2026
34 checks passed
@aidandaly24 aidandaly24 deleted the fix/deploy-target-stack-selection branch June 23, 2026 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/s PR size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants