Pipeline: Value of CfnOutput is different if used in a PolicyStatement vs a property of `envFromCfnOutputs`
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
### Describe the bug
I'm creating a bucket in a Pipeline stage and saving the bucketName property as a `CfnOutput`. I use that output in a stage poststep in a shell command (using `envFromCfnOutputs`) and to generate a new PolicyStatement. The value of the name in the policy statement is different than the value of the ENV variable in the shell.
### Expected Behavior
The values should be the same no matter where the output is used.
### Current Behavior
The CfnOutput displays different values depending on where used.
### Reproduction Steps
Create a new bucket:
```
export class MyStack extends Stack {
public readonly bucketName: CfnOutput
constructor(scope: Construct, id: string, props: StackProps) {
const bucket = new Bucket(this, 'myBucket', {
removalPolicy: RemovalPolicy.DESTROY,
autoDeleteObjects: true,
});
this.bucketName = new CfnOutput(this, 'bucketName', {
value: bucket.bucketName
});
}
}
```
'Hoist' the value up the pipeline stage:
```
export class MyStage extends Stage {
public readonly bucketName: CfnOutput;
constructor(scope: Construct, id: string, props: StageProps) {
super(scope, id, props);
const stack = new MyStack(this, 'myStack', props);
this.bucketName = stack.bucketName
}
}
```
Create the pipeline and use the stage, add a poststep
```
export class MyPipeline extends Stack {
constructor(scope: Construct, id: string, props: StackProps) {
super(scope, id, props);
const source = CodePipelineSource.connection(...);
const stage = new MyStage(this, 'stage');
const synth = new CodeBuildStep('Synth', {
input: source,
commands: ['npm ci', 'npm run build', 'npm run cdk synth']
});
// generate a post step that builds my frontend and moves to the bucket
// I have to do this later, because I use some other values such as the URL
// to an API gateway in my React Code, so I can't use bucketDeploy in the stage
const frontend = this.getFrontendStep(source, stage.bucketName);
const pipeline = new CodePipeline(this, 'pipeline', {
pipelineName: 'myPipeline',
synth
});
const pipelineStage = pipeline.addStage(stage);
pipelineStage.addPost(frontend);
}
getFrontendStep(source: CodePipelineSource, bucketName: CfnOutput) {
// notice the echo shell command this value is CORRECT
// the CfnOutput value in the policy statement is INCORRECT
return new CodeBuildStep('frontend', {
input: source,
commands: [
'echo $AWS_FRONTEND_BUCKET_NAME',
'cd frontend',
'npm ci',
'npm run build',
'aws s3 sync ./dist/ s3://$AWS_FRONTEND_BUCKET_NAME/ --delete'
],
rolePolicyStatements: [
new PolicyStatement({
effect: Effect.ALLOW,
actions: ["S3:*"],
resources: [
`arn:aws:s3:::${bucketName.value}`,
`arn:aws:s3:::${bucketName.value}/*`
]
})
],
primaryOutputDirectory: 'frontend/dist',
envFromCfnOutputs: {
AWS_FRONTEND_BUCKET_NAME: bucketName
}
})
}
}
```
### Possible Solution
_No response_
### Additional Information/Context
_No response_
### CDK CLI Version
2.37.0
### Framework Version
_No response_
### Node.js Version
16.16.0
### OS
Mac
### Language
Typescript
### Language Version
Typescript 4.7.4
### Other information
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.