hotswap template cache is not keyed by target environment, can reuse stale state across accounts/regions
- Dominant language
- TypeScript
- Stars
- 105
- Forks
- 122
- Avg merge
- 1d 17h
- Merged PRs (30d)
- 71
Description
### Describe the bug
The on-disk hotswap cache written by \`hotswap-template-cache.ts\` (\`/.hotswap-cache/.json\`) is keyed only by the cloud assembly directory and the stack name:
```ts
function cachePath(assemblyDir: string, stackName: string): string {
return path.join(assemblyDir, CACHE_DIR, `${stackName}.json`);
}
```
The cached payload stores the last-deployed root template and, for nested stacks, the physical stack names — both of which are meaningful only for the specific AWS account/region they were captured against. Nothing in the cache key or the cached data records which environment produced it.
\`hotswapDeployment()\` in \`hotswap-deployments.ts\` resolves the target environment via \`sdkProvider.resolveEnvironment(stack.environment)\` and then unconditionally trusts whatever is in the cache file for that stack name:
```ts
const resolvedEnv = await sdkProvider.resolveEnvironment(stack.environment);
...
const hotswapCache = await readHotswapTemplateCache(stack.assembly.directory, stack.stackName, stack.template);
const currentTemplate = hotswapCache ?? await loadCurrentTemplateWithNestedStacks(stack, sdk);
```
The only place the cache is invalidated is after a full CloudFormation deployment (\`invalidateHotswapTemplateCache\`, called from \`deploy-stack.ts\`). Switching the *target environment* between hotswap-only sessions never invalidates it.
### Impact / repro
1. A CDK app resolves its environment from CLI credentials at deploy time (a common pattern for per-developer sandbox accounts, or simply switching \`AWS_PROFILE\`/\`CDK_DEFAULT_ACCOUNT\` without re-synthesizing).
2. Run \`cdk watch\` (hotswap) against Account A for stack \`MyStack\`. On success, \`writeHotswapTemplateCache\` persists Account A's deployed template and physical resource names to \`cdk.out/.hotswap-cache/MyStack.json\`.
3. Without an intervening full (non-hotswap) deploy, switch credentials and run \`cdk watch\` again for the same stack name against Account B.
4. \`readHotswapTemplateCache\` returns Account A's stale cache. The hotswap diff is computed against Account A's deployed state instead of Account B's, and any hotswap operations that rely on the cached physical resource names target Account A's resource identifiers while using an SDK client authenticated for Account B.
This can cause a hotswap to silently skip changes that are actually needed, or to attempt an operation against a physical resource name that doesn't exist (or, worse, happens to collide with an unrelated resource) in the new account/region.
### Expected behavior
The hotswap cache should never be usable across two different target environments — a cache entry written for one account/region should not be readable when hotswapping the same stack name against a different account/region.
### Where
- \`packages/@aws-cdk/toolkit-lib/lib/api/hotswap/hotswap-template-cache.ts\`
- \`packages/@aws-cdk/toolkit-lib/lib/api/hotswap/hotswap-deployments.ts\`
- \`packages/@aws-cdk/toolkit-lib/lib/api/deployments/deploy-stack.ts\`
A fix (folding the resolved environment into the cache key) plus a regression test is up in a PR shortly.
Contributor guide
Research direction
Start with packages/@aws-cdk/toolkit-lib/lib/api/hotswap/hotswap-template-cache.ts and hotswap-deployments.ts, then inspect the environment resolution and cache invalidation path in deploy-stack.ts. Add a regression test covering hotswap sessions for different account or region targets, and verify the cache is not reused across environments.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, typescript
- Domain
- cloud, devops
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100