How to deploy SPA to S3 using CDK in a pipeline
See original GitHub issueI have a single page react application that I want to host in S3. The source is in git and I would like to set up a Pipeline such that when I push to master it fetches the source, builds it and deploys to S3. Pretty straight forward. I have created a CDK stack for deploying to S3, and it looks like this:
import { Construct, StackProps, Stack, RemovalPolicy, CfnParameter } from '@aws-cdk/core';
import { Bucket, HttpMethods } from "@aws-cdk/aws-s3";
import { BucketDeployment, Source, ISource } from "@aws-cdk/aws-s3-deployment";
import { CloudFrontWebDistribution } from '@aws-cdk/aws-cloudfront';
export default function createReactStack(scope: Construct, name: string, props?: StackProps) {
const stack = new Stack(scope, `${name}-React`, props);
// This works locally...
const source = Source.asset('../react/build');
// ... but in the pipeline I need the following line
const source = createSourceAsset(stack);
const bucket = createBucket(stack);
createDeploySourceToBucket(stack, source, bucket);
createCloudFront(stack, bucket);
return stack;
}
function createSourceAsset(stack: Stack) {
const bucketName = new CfnParameter(stack, `${stack.stackName}-bucketName`).valueAsString;
const zipFile = new CfnParameter(stack, `${stack.stackName}-zipFile`).valueAsString;
return Source.bucket(Bucket.fromBucketName(stack, 'bucketName', bucketName), zipFile);
}
function createBucket(stack: Stack): Bucket {
return new Bucket(stack, `${stack.stackName}.Bucket`, {
removalPolicy: RemovalPolicy.DESTROY,
websiteIndexDocument: 'index.html',
websiteErrorDocument: 'index.html',
publicReadAccess: true,
cors: [
{
allowedOrigins: ['*'],
allowedMethods: [HttpMethods.GET],
}
]
});
}
function createDeploySourceToBucket(stack: Stack, source: ISource, bucket: Bucket) {
return new BucketDeployment(stack, `${stack.stackName}.BucketDeployment`, {
sources: [source],
destinationBucket: bucket
});
}
function createCloudFront(stack: Stack, bucket: Bucket) {
new CloudFrontWebDistribution(stack, `${stack.stackName}.CloudFront`, {
originConfigs: [
{
s3OriginSource: {
s3BucketSource: bucket
},
behaviors: [
{ isDefaultBehavior: true }
]
}
]
});
}
This works well from a local environment, I’m able to run cdk synth
and cdk deploy
to deploy this stack.
But I don’t want to manually deploy it, I want to set up a pipeline to deploy it. My pipeline has 4 stages:
- Get the source (using
S3SourceAction
) - Build the react SPA app (using
CodeBuildAction
) - Synth the CloudFormation templates (using
CodeBuildAction
) - Deploy the stack based on the template (using
CloudFormationCreateUpdateStackAction
)
The first three steps are straight forward, but the last step seems impossible to achieve.
I’ve tried using CloudFormationCreateUpdateStackAction
, like this:
new CloudFormationCreateUpdateStackAction({
actionName: `Deploy-Cdk`,
templatePath: input.atPath(
`${stackName}.template.json`
),
stackName,
adminPermissions: true,
extraInputs: [source],
parameterOverrides: {
[`${stackName}-bucketName`]: source.s3Location.bucketName,
[`${stackName}-zipFile`]: source.s3Location.objectKey
}
})
But when I do I get an error in the pipeline like this:
These seem to be parameters needed by BucketDeployment
, and their values are magically set by cdk deploy
but not by CloudFormationCreateUpdateStackAction
. How can I make this work in Pipeline? The assetParameters seem to have two hashes as part of them, how can I generate them correctly?
Issue Analytics
- State:
- Created 4 years ago
- Comments:10 (6 by maintainers)
Top GitHub Comments
It’s all doable - from your description, I thought the Bucket and CloudFrontWebDistribution were all that the SPA needed, so I didn’t see much value in adding a CloudFormation Stack to the Pipeline. But it’s certainly doable:
Closing this issue for now until #3437 is merged. Feel free to reopen