· 6 years ago · Jul 30, 2019, 12:26 PM
1import cdk = require('@aws-cdk/core');
2import cicd = require('@aws-cdk/app-delivery');
3import codebuild = require('@aws-cdk/aws-codebuild');
4import codepipeline = require('@aws-cdk/aws-codepipeline');
5import codepipelineActions = require('@aws-cdk/aws-codepipeline-actions');
6import iam = require('@aws-cdk/aws-iam');
7
8export interface PipelineSourceProps {
9 branch: string;
10 oauthTokenSecretArn: string;
11 owner: string;
12 repo: string;
13}
14
15interface CicdStackProps extends cdk.StackProps {
16 source: PipelineSourceProps;
17 stacks: cdk.Stack[];
18}
19
20export class CicdStack extends cdk.Stack {
21 private props: CicdStackProps;
22
23 public constructor(scope: cdk.Construct, id: string, props: CicdStackProps) {
24 super(scope, id, props);
25
26 this.props = props;
27
28 const sourceOutput = new codepipeline.Artifact();
29 const buildOutput = new codepipeline.Artifact();
30 const pipeline = new codepipeline.Pipeline(this, 'CodePipeline', {
31 pipelineName: this.stackName,
32 restartExecutionOnUpdate: true,
33 stages: [
34 {
35 stageName: 'Source',
36 actions: [this.createSourceAction(sourceOutput)],
37 },
38 {
39 stageName: 'Build',
40 actions: [this.createBuildAction(sourceOutput, buildOutput)],
41 },
42 ],
43 });
44
45 /**
46 * Update
47 */
48 pipeline.addStage({
49 stageName: 'Update',
50 actions: [new cicd.PipelineDeployStackAction({ adminPermissions: true, input: buildOutput, stack: this })],
51 });
52
53 /**
54 * Deploy
55 */
56 props.stacks.forEach((stack): void => {
57 pipeline.addStage({
58 stageName: stack.stackName,
59 actions: [new cicd.PipelineDeployStackAction({ adminPermissions: true, input: buildOutput, stack })],
60 });
61 });
62 }
63
64 private createSourceAction(output: codepipeline.Artifact): codepipelineActions.Action {
65 const { props: { source: { branch, owner, oauthTokenSecretArn, repo } } } = this;
66
67 return new codepipelineActions.GitHubSourceAction({
68 actionName: 'GitHub',
69 branch,
70 oauthToken: cdk.SecretValue.secretsManager(oauthTokenSecretArn),
71 output,
72 owner,
73 repo,
74 });
75 }
76
77 private createBuildAction(input: codepipeline.Artifact, output: codepipeline.Artifact): codepipelineActions.Action {
78 const project = new codebuild.PipelineProject(this, 'CodeBuild', {
79 environment: { buildImage: codebuild.LinuxBuildImage.UBUNTU_14_04_NODEJS_10_1_0 },
80 environmentVariables: {
81 STACKS: {
82 value: this.props.stacks.concat(this).map((stack): string => stack.stackName).join(' '),
83 type: codebuild.BuildEnvironmentVariableType.PLAINTEXT,
84 },
85 },
86 projectName: this.node.id,
87 });
88
89 project.addToRolePolicy(new iam.PolicyStatement({ resources: ['*'], actions: ['cloudformation:DescribeStacks'] }));
90
91 return new codepipelineActions.CodeBuildAction({ actionName: 'CodeBuild', project, input, outputs: [output] });
92 }
93}
94
95export default CicdStack;
96
97# bin/cdk.ts
98const cicdStackProductionSource = {
99 oauthTokenSecretArn: GITHUB_OAUTH_TOKEN_SECRET_ARN[ecsStackProduction.region],
100 owner: 'ChrisLahaye',
101 repo: 'Lemonade-CDK',
102 branch: 'master',
103};
104
105new CicdStack(app, 'CicdStackProduction1', {
106 source: cicdStackProductionSource,
107 stacks: [
108 ecsStackProduction,
109 apiServiceProduction,
110 appServiceProduction,
111 backendServiceProduction,
112 grafanaServiceProduction,
113 landingServiceProduction,
114 prometheusServiceProduction,
115 ],
116})
117
118# patch app-delivery
119diff --git a/node_modules/@aws-cdk/app-delivery/lib/pipeline-deploy-stack-action.js b/node_modules/@aws-cdk/app-delivery/lib/pipeline-deploy-stack-action.js
120index 981c39b..2904ce0 100644
121--- a/node_modules/@aws-cdk/app-delivery/lib/pipeline-deploy-stack-action.js
122+++ b/node_modules/@aws-cdk/app-delivery/lib/pipeline-deploy-stack-action.js
123@@ -32,7 +32,8 @@ class PipelineDeployStackAction extends cdk.Construct {
124 changeSetName,
125 runOrder: createChangeSetRunOrder,
126 stackName: props.stack.stackName,
127- templatePath: props.input.atPath(`${props.stack.stackName}.template.yaml`),
128+ templateConfiguration: props.input.atPath(`${props.stack.stackName}.configuration.json`),
129+ templatePath: props.input.atPath(`${props.stack.stackName}.template.json`),
130 adminPermissions: props.adminPermissions,
131 deploymentRole: props.role,
132 capabilities,
133
134# buildspec
135version: 0.2
136phases:
137 install:
138 commands:
139 - apt-get update
140 - apt-get install -y jq
141 - npm install
142 build:
143 commands:
144 - npm run build
145 - npm run cdk synth $STACKS -- -o dist
146 - |
147 echo -n $STACKS | xargs -d' ' -I{} bash -c "
148 aws cloudformation describe-stacks --stack-name {} \
149 | jq '.Stacks[0].Parameters | {Parameters: (map({ (.ParameterKey) : .ParameterValue } ) | add)}' \
150 > dist/{}.configuration.json \
151 || echo \{\} \
152 > dist/{}.configuration.json" \;
153artifacts:
154 base-directory: dist
155 files: '**/*'