-
Notifications
You must be signed in to change notification settings - Fork 0
/
pipeline-reactjs.yml
355 lines (317 loc) · 12.1 KB
/
pipeline-reactjs.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
AWSTemplateFormatVersion: "2010-09-09"
Description: CloudFormation template for ReactJS application deployment pipeline
Parameters:
CodeCommitRepositoryName:
Type: String
Description: Name of CodeCommit repository to be used with the pipeline eg. my-repository
MinLength: 1
BuildBranch:
Type: String
Description: Branch of repository used to trigger builds
MinLength: 1
Default: main
DevDeploymentCrossAccountRoleArn:
Type: String
Description: ARN for the cross account role that has been created in the prod account to fascilitate to deployment. eg. arn:aws:iam::123456789:role/crossaccount-deployment-role
MinLength: 1
ProdDeploymentCrossAccountRoleArn:
Type: String
Description: ARN for the cross account role that has been created in the prod account to fascilitate to deployment. eg. arn:aws:iam::123456789:role/crossaccount-deployment-role
MinLength: 1
DestinationStackName:
Type: String
Description: Name of stack assocaited with the Application that will be deployed to other accounts eg. react-cors-spa
MinLength: 1
CloudFormationFile:
Type: String
Description: Path to CloudFormation file that defines the AWS resources for running the application
MinLength: 1
Default: react-cors-spa-stack.yaml
DeploymentRegion:
Type: String
Description: The region that resources will be deployed to
AllowedValues : [ "us-east-1", "ap-southeast-2" ]
Default: us-east-1
Resources:
CodeBuildArtifactBuild:
Type: AWS::CodeBuild::Project
Properties:
Name: !Sub ${AWS::StackName}-build-artifacts
ServiceRole: !Ref CodeBuildArtifactBuildRole
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/standard:5.0
Artifacts:
Type: CODEPIPELINE
Source:
Type: CODEPIPELINE
BuildSpec: |
version: 0.2
env:
shell: bash
phases:
install:
runtime-versions:
nodejs: 14
build:
on-failure: ABORT
commands:
- # install dependencies
- yarn install --frozen-lockfile
- # Execute tests
- CI=true yarn test --passWithNoTests
- # generate deployment artifacts
- yarn build
artifacts:
files:
- 'build/**/*'
- '*.yaml'
cache:
paths:
- 'node_modules/**'
TimeoutInMinutes: 10
CodeBuildArtifactDeploy:
Type: AWS::CodeBuild::Project
Properties:
Name: !Sub ${AWS::StackName}-deploy-artifacts
ServiceRole: !Ref CodeBuildArtifactDeployRole
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/standard:5.0
EnvironmentVariables:
- Name: CROSS_ACCOUNT_DEPLOYMENT_ROLE_ARN
Value: PLACEHOLDER_OVERRIDDEN_BY_PIPELINE
- Name: DESTINATION_ENVIRONMENT
Value: PLACEHOLDER_OVERRIDDEN_BY_PIPELINE
- Name: DESTINATION_STACK_NAME
Value: !Ref DestinationStackName
- Name: YAML_FILE
Value: !Ref CloudFormationFile
- Name: DESTINATION_REGION
Value: !Ref DeploymentRegion
Artifacts:
Type: CODEPIPELINE
Source:
Type: CODEPIPELINE
BuildSpec: |
version: 0.2
env:
shell: bash
phases:
pre_build:
on-failure: ABORT
commands:
- # Assume temporary credentials using cross-account role
- creds_json=$(aws sts assume-role --role-arn $CROSS_ACCOUNT_DEPLOYMENT_ROLE_ARN --role-session-name codebuild)
- echo $creds_json
- export AWS_ACCESS_KEY_ID=$(echo $creds_json | jq -r '.Credentials.AccessKeyId')
- export AWS_SECRET_ACCESS_KEY=$(echo $creds_json | jq -r '.Credentials.SecretAccessKey')
- export AWS_SESSION_TOKEN=$(echo $creds_json | jq -r '.Credentials.SessionToken')
- # Print info about the current user for debugging purposes
- aws sts get-caller-identity
build:
on-failure: ABORT
commands:
- stack_name="${DESTINATION_ENVIRONMENT}-${DESTINATION_STACK_NAME}"
- # Deploy CloudFormation Template
- aws cloudformation deploy --template-file $YAML_FILE --stack-name $stack_name --capabilities CAPABILITY_NAMED_IAM --region $DESTINATION_REGION
- # Extract Outputs from CloudFormation Template
- stack_outputs_json=$(aws cloudformation describe-stacks --stack-name $stack_name --region $DESTINATION_REGION | jq -r '.Stacks[0].Outputs')
- bucket_name=$(echo $stack_outputs_json | jq -r '.[] | select(.OutputKey=="BucketName") | .OutputValue')
- distribution_url=$(echo $stack_outputs_json | jq -r '.[] | select(.OutputKey=="CFDistributionURL") | .OutputValue')
- distribution_id=$(echo $stack_outputs_json | jq -r '.[] | select(.OutputKey=="CFDistributionId") | .OutputValue')
- # Sync files to S3 Bucket associated with CloudFront distribution
- aws s3 sync "./build/" "s3://${bucket_name}/" --delete
- # Invalidate the cache of the CloudFront distrubtion (force it to return latest content)
- aws cloudfront create-invalidation --distribution-id $distribution_id --paths "/*"
TimeoutInMinutes: 10
CodePipelineArtifactBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${AWS::StackName}-pipeline-bucket
CodePipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
Name: !Sub ${AWS::StackName}-pipeline
ArtifactStore:
Type: S3
Location: !Ref CodePipelineArtifactBucket
RoleArn: !GetAtt CodePipelineRole.Arn
RestartExecutionOnUpdate: false
Stages:
- Name: Source
Actions:
# Retrieve source from CodeCommit
- Name: Retrieve-Source
ActionTypeId:
Category: Source
Owner: AWS
Version: 1
Provider: CodeCommit
OutputArtifacts:
- Name: SourceOutput
Configuration:
RepositoryName: !Ref CodeCommitRepositoryName
BranchName: !Ref BuildBranch
RunOrder: 10
- Name: Build
Actions:
# Build application and output artifacts
- Name: Build-App
ActionTypeId:
Category: Build
Owner: AWS
Version: 1
Provider: CodeBuild
InputArtifacts:
- Name: SourceOutput
OutputArtifacts:
- Name: BuildOutput
Configuration:
ProjectName: !Ref CodeBuildArtifactBuild
RunOrder: 20
- Name: Deploy-Dev
Actions:
# Deploy application to dev
- Name: Deploy-To-Dev
ActionTypeId:
Category: Build
Owner: AWS
Version: 1
Provider: CodeBuild
InputArtifacts:
- Name: BuildOutput
Configuration:
ProjectName: !Ref CodeBuildArtifactDeploy
EnvironmentVariables: !Sub |
[
{"name":"CROSS_ACCOUNT_DEPLOYMENT_ROLE_ARN","value":"${DevDeploymentCrossAccountRoleArn}","type":"PLAINTEXT"},
{"name":"DESTINATION_ENVIRONMENT","value":"dev","type":"PLAINTEXT"}
]
RunOrder: 30
- Name: Deploy-Prod
Actions:
# Manual step for approving deployments to prod
- Name: Approve-Prod-Deploy
ActionTypeId:
Category: Approval
Owner: AWS
Version: 1
Provider: Manual
RunOrder: 40
# Deploy application to prod
- Name: Deploy-To-Prod
ActionTypeId:
Category: Build
Owner: AWS
Version: 1
Provider: CodeBuild
InputArtifacts:
- Name: BuildOutput
Configuration:
ProjectName: !Ref CodeBuildArtifactDeploy
EnvironmentVariables: !Sub |
[
{"name":"CROSS_ACCOUNT_DEPLOYMENT_ROLE_ARN","value":"${ProdDeploymentCrossAccountRoleArn}","type":"PLAINTEXT"},
{"name":"DESTINATION_ENVIRONMENT","value":"prod","type":"PLAINTEXT"}
]
RunOrder: 50
CodeBuildArtifactBuildRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyName: BuildArtifacts
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: !Sub 'arn:aws:logs:*:*:log-group:/aws/codebuild/${AWS::StackName}-build-artifacts:log-stream:*'
- Effect: Allow
Action:
- s3:GetObject
- s3:GetObjectVersion
- s3:PutObject
Resource: !Sub 'arn:aws:s3:::${CodePipelineArtifactBucket}/*'
CodeBuildArtifactDeployRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyName: DeployArtifacts
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- sts:AssumeRole
Resource:
- !Ref DevDeploymentCrossAccountRoleArn
- !Ref ProdDeploymentCrossAccountRoleArn
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: !Sub 'arn:aws:logs:*:*:log-group:/aws/codebuild/${AWS::StackName}-deploy-artifacts:log-stream:*'
- Effect: Allow
Action:
- s3:GetObject
- s3:GetObjectVersion
Resource: !Sub 'arn:aws:s3:::${CodePipelineArtifactBucket}/*'
CodePipelineRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
Effect: Allow
Principal:
Service: codepipeline.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyName: CodePipeline
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- s3:GetObject
- s3:GetObjectVersion
- s3:PutObject
Resource: !Sub 'arn:aws:s3:::${CodePipelineArtifactBucket}/*'
- Effect: Allow
Action:
- codecommit:GetBranch
- codecommit:GetCommit
- codecommit:UploadArchive
- codecommit:GetUploadArchiveStatus
Resource: !Sub "arn:aws:codecommit:*:*:${CodeCommitRepositoryName}"
- Effect: Allow
Action:
- codebuild:StartBuild
- codebuild:BatchGetBuilds
Resource:
- !GetAtt CodeBuildArtifactBuild.Arn
- !GetAtt CodeBuildArtifactDeploy.Arn