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:
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:
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
- 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).
- 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`.
- Without an intervening full (non-hotswap) deploy, switch credentials and run `cdk watch` again for the same stack name against Account B.
- `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.
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:
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:
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
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
A fix (folding the resolved environment into the cache key) plus a regression test is up in a PR shortly.