Skip to content

Instantly share code, notes, and snippets.

@nkhine
Created June 17, 2021 11:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nkhine/f282055a2e3127d23a95df46deaec0d8 to your computer and use it in GitHub Desktop.
Save nkhine/f282055a2e3127d23a95df46deaec0d8 to your computer and use it in GitHub Desktop.
S3 SPA Pipeline
import { App, RemovalPolicy } from '@aws-cdk/core';
import { MultistackStack, MultistackProps } from './stacks/multistack';
import { PipelineStack, PipelineStackProps } from './stacks/pipeline';
const prodEnv = {
account: '***',
region: 'eu-west-1',
};
const app = new App();
const prod: MultistackProps = {
env: prodEnv,
encryptBucket: false,
rootDocument: 'index.html',
errorDocument: '404.html',
envBranch: 'main',
bucketRemovalPolicy: RemovalPolicy.RETAIN,
appName: 'NFT',
};
const pipeline: PipelineStackProps = {
env: prodEnv,
encryptBucket: false,
rootDocument: 'index.html',
errorDocument: '404.html',
envBranch: 'main',
bucketRemovalPolicy: RemovalPolicy.RETAIN,
appName: 'NKHINE',
repository: { owner: 'nkhine', name: 'spa', branch: 'main' },
};
new MultistackStack(app, 'NKHINE-PROD', prod);
new PipelineStack(app, 'PIPELINE-NKHINE-PROD', pipeline);
app.synth();
import {
Construct,
CfnOutput,
StackProps,
RemovalPolicy,
} from '@aws-cdk/core';
import { SPADeploy } from 'cdk-spa-deploy';
import TaggingStack from './tagging';
export interface MultistackProps extends StackProps {
encryptBucket?: boolean;
rootDocument: string;
errorDocument: string;
bucketRemovalPolicy?: RemovalPolicy;
envBranch: string;
appName?: string;
}
export class MultistackStack extends TaggingStack {
constructor(scope: Construct, id: string, props: MultistackProps) {
super(scope, id, props);
const siteCDN = new SPADeploy(this, 'Website', { encryptBucket: props.encryptBucket })
.createSiteWithCloudfront({
indexDoc: props.rootDocument,
websiteFolder: '../front/build',
});
// Outputs
new CfnOutput(this, 'siteCDN', {
value: siteCDN.distribution.distributionDomainName,
description: 'Site CDN',
});
}
}
import {
PipelineProject,
ComputeType,
BuildSpec,
LinuxBuildImage,
// BuildEnvironmentVariableType,
} from '@aws-cdk/aws-codebuild';
import { Artifact, Pipeline } from '@aws-cdk/aws-codepipeline';
import { CodeBuildAction, CodeStarConnectionsSourceAction } from '@aws-cdk/aws-codepipeline-actions'; // , S3DeployAction
import {
Role,
ServicePrincipal,
PolicyDocument,
PolicyStatement,
Effect,
} from '@aws-cdk/aws-iam';
import { Construct, Stack } from '@aws-cdk/core';
import { MultistackProps } from './multistack';
export interface PipelineStackProps extends MultistackProps {
repository: RepositoryProps;
// siteBucket: WebsiteBucket;
}
export interface RepositoryProps {
owner: string;
name: string;
branch: string;
}
export class PipelineStack extends Stack {
constructor(scope: Construct, id: string, props: PipelineStackProps) {
super(scope, id, props);
const pipeline = new Pipeline(this, 'pipeline', {
pipelineName: props.appName + '-pipeline',
});
const sourceArtifact = new Artifact('source');
const CodeBuildRole = new Role(this, 'CodeBuildRole', {
assumedBy: new ServicePrincipal('codebuild.amazonaws.com'),
inlinePolicies: {
CodeBuildNestedCFNAccessPolicy: new PolicyDocument({
statements: [
new PolicyStatement({
effect: Effect.ALLOW,
actions: ['*'],
resources: ['*'],
}),
],
}),
},
});
const codebuildProjects = {
build: new PipelineProject(this, 'SPA-Build', {
projectName: 'SPA-Build',
role: CodeBuildRole,
environment: {
buildImage: LinuxBuildImage.STANDARD_5_0,
computeType: ComputeType.LARGE,
},
buildSpec: BuildSpec.fromObject({
version: '0.2',
phases: {
pre_build: {
commands: [
'cd front',
'npm install',
],
},
build: {
commands: [
'npm run build',
],
},
},
artifacts: {
'base-directory': 'front/build',
'files': [
'**/*',
],
},
cache: {
paths: [
'./node_modules/**/*',
],
},
}),
}),
deploy: new PipelineProject(this, 'SPA-Deploy', {
projectName: 'SPA-Deploy',
role: CodeBuildRole,
environment: {
buildImage: LinuxBuildImage.STANDARD_5_0,
computeType: ComputeType.LARGE,
},
buildSpec: BuildSpec.fromObject({
version: '0.2',
phases: {
pre_build: {
commands: [
'echo "Running SPA Deploy..."',
],
},
build: {
commands: [
'echo "FIXME SPA Deploy..."',
],
},
},
}),
}),
};
// Pipeline stages
const sourceStage = pipeline.addStage({
stageName: 'Source',
});
// aws codestar-connections list-connections
const gitHubSourceAction = new CodeStarConnectionsSourceAction({
actionName: 'GitHubSource',
owner: props.repository.owner,
repo: props.repository.name,
output: sourceArtifact,
branch: props.repository.branch,
connectionArn: 'arn:aws:codestar-connections:eu-west-1:***:connection/c02d63a7-ac16-4330-b27c-0ab1d1e61155',
});
sourceStage.addAction(gitHubSourceAction);
// Build
const buildArtifact = new Artifact('build');
const buildStage = pipeline.addStage({
stageName: 'Build',
placement: {
justAfter: sourceStage,
},
});
const reactBuildAction = new CodeBuildAction({
actionName: 'ReactBuild',
input: sourceArtifact,
outputs: [buildArtifact],
project: codebuildProjects.build,
});
buildStage.addAction(reactBuildAction);
// Deploy
const deployArtifact = new Artifact('deploy');
const deployStage = pipeline.addStage({
stageName: 'Deploy',
placement: {
justAfter: buildStage,
},
});
const reactDeployAction = new CodeBuildAction({
actionName: 'ReactDeploy',
input: sourceArtifact,
outputs: [deployArtifact],
project: codebuildProjects.deploy,
});
// const reactDeployAction1 = new S3DeployAction({
// actionName: 'ReactDeploy',
// input: sourceArtifact,
// bucket: MultistackStack
// });
deployStage.addAction(reactDeployAction);
}
}
import { Construct, Stack, StackProps, Tags } from '@aws-cdk/core';
export default class TaggingStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
Tags.of(this).add('Name', 'Name');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment