aws / aws/aws-cdk

DefaultStackSynthesizer: App level synthesizer leaks assets between Stacks when specified

Open
#29,071 2 comments 1 reaction 0 assignees View on GitHub
@aws-cdk/assets bug effort/medium p2
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

### Describe the bug

I am working on a multi-stack App with multiple specified account targets (via the env property on each Stack). When specifying the property defaultStackSynthesizer on the App I started facing deployment issues I had never faced before. The output implied that the specific Stack I was trying to deploy wanted to publish assets belonging to other stacks.

By looking at the manifest for each Stack I was able to verify this. This issue does not present itself if you have all Stacks configured to deploy to the same account. I assume the same goes if they are all account agnostic. While the deployment failures are not irrelevant I think the underlying issue of the wrong assets being added to manifests is the key here.

### Expected Behavior

The Stack manifests only contain relevant files.

### Current Behavior

The Stack manifests contains assets belonging to other stacks. Screenshot of manifest for Stack attached to App after another Stack:
![image](https://github.com/aws/aws-cdk/assets/45800844/0b9987bb-ff47-4b21-ba99-5fe0a0461ae2)

Note how it not only contains its own template but also the template for StackA.

### Reproduction Steps

1. Create a new project using "npx cdk init app --language=typescript"
2. Modify the app to instantiate a DefaultStackSynthesizer, no props needed
3. Add two Stacks that use this App as scope
4. Synth using "npx cdk synth"
5. Check Stack manifests under cdk.out

I have also taken the liberty of creating a repository which highlights the issue: [CDK Assets leak](https://github.com/castodius/cdk-assets-leak). The cdk.out directory is commited and this [file](https://github.com/castodius/cdk-assets-leak/blob/main/cdk.out/StackB.assets.json) highlights the issue with more than one template being present.

### Possible Solution

I have located the source of the issue in DefaultStackSynthesizer. It stems from reusableBind
![image](https://github.com/aws/aws-cdk/assets/45800844/0fc83a31-1ebc-490e-afb4-8a0c4634e0d5)

It copies the DefaultStackSynthesizer, however this only partially works since the class instance contains another class instance and the reference is kept. The reference to the assetManifest is kept and all Stacks end up sharing the same AssetManifestBuilder.
![image](https://github.com/aws/aws-cdk/assets/45800844/574586fd-3bad-4cf4-b662-0b7bd4050698)

This snippet of code highlights why this is an issue:
```javscript
const helper = {
value: 1
}

const wrapper = {
foo: helper
}

// prints 1
console.log(wrapper.foo.value)

const copy1 = Object.create(wrapper)
copy1.foo.value = 2

// prints 2 since the reference to helper was kept
console.log(wrapper.foo.value)
```

### Additional Information/Context

I will create a PR soon that should fix this.

### CDK CLI Version

2.127.0 (build 6c90efc)

### Framework Version

_No response_

### Node.js Version

v20.10.0

### OS

Sonoma 14.2.1

### Language

TypeScript

### Language Version

_No response_

### Other information

_No response_

Contributor guide

Open the contributing guide

Research direction

Start with DefaultStackSynthesizer and its reusableBind path, then inspect how the nested AssetManifestBuilder reference is retained. Reproduce the issue with two stacks using npx cdk synth and compare their cdk.out manifests; done means each Stack manifest contains only its relevant assets.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
infrastructure
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.