-
Notifications
You must be signed in to change notification settings - Fork 6
448 lines (391 loc) · 18.1 KB
/
content-release.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
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
name: Content Release
permissions:
id-token: write # This is required for requesting the JWT for AWS creds
contents: read # This is required for actions/checkout
on:
repository_dispatch:
types: [content-release]
workflow_run:
workflows: ['Create Production Tag']
types: [completed]
branches: [main]
workflow_call:
inputs:
build_type:
type: string
description: "Environment this workflow runs against"
required: true
default: 'PROD'
workflow_dispatch:
inputs:
build_type:
type: choice
description: "Environment this workflow runs against"
required: true
default: 'PROD'
options:
- dev
- staging
- prod
concurrency:
group: ${{ inputs.build_type || 'prod' }}
env:
SLACK_CHANNEL: C06DSBT7CBW #status-next-build
jobs:
# This is necessary to get credentials to use the private ECR image defined in the build job container.
login-to-amazon-ecr:
runs-on: ubuntu-latest
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: us-gov-west-1
role-to-assume: ${{ vars.AWS_ASSUME_ROLE }}
mask-aws-account-id: 'false'
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
with:
mask-password: 'false'
outputs:
docker_username: ${{ steps.login-ecr.outputs.docker_username_008577686731_dkr_ecr_us_gov_west_1_amazonaws_com }}
docker_password: ${{ steps.login-ecr.outputs.docker_password_008577686731_dkr_ecr_us_gov_west_1_amazonaws_com }}
# Ensure latest build from main is passing CI, grab the latest published tag for content-release
validate-build-status:
name: Validate Build Status
runs-on: ubuntu-latest
outputs:
REF: ${{ steps.get-latest-release.outputs.target_commitish }}
TAG: ${{ steps.get-latest-release.outputs.tag_name }}
APPROX_WORKFLOW_START_TIME: ${{ steps.export-approx-workflow-start-time.outputs.APPROX_WORKFLOW_START_TIME }}
timeout-minutes: 15
steps:
- name: Export approximate workflow start time
id: export-approx-workflow-start-time
run: echo APPROX_WORKFLOW_START_TIME=$(date +"%s") >> $GITHUB_OUTPUT
- name: Checkout
uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20 # the validate-build-status requires node12, node16, node20...
- name: Setup Yarn
run: |
corepack enable
corepack install -g --cache-only .yarn/releases/corepack.tgz
- name: Install dependencies
run: yarn
- name: Get latest release
id: get-latest-release
uses: ./.github/workflows/fetch-latest-release
- name: Validate build status
run: node ./scripts/github-actions/validate-build-status.js ${{ steps.get-latest-release.outputs.target_commitish }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
notify-start-slack:
name: Notify Start (Slack)
runs-on: ubuntu-latest
needs: validate-build-status
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Notify Slack
uses: department-of-veterans-affairs/platform-release-tools-actions/slack-notify@8c496a4b0c9158d18edcd9be8722ed0f79e8c5b4 # main
continue-on-error: true
with:
payload: '{"attachments": [{"color": "#2EB67D","blocks": [{"type": "section","text": {"type": "mrkdwn","text": "Stand by, content release for next-build coming up (using ${{ needs.validate-build-status.outputs.TAG }}). <https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}>"}}]}]}'
channel_id: ${{ env.SLACK_CHANNEL }}
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
build:
name: Build static pages & deploy to S3
timeout-minutes: 60
runs-on: [self-hosted, asg]
needs: [validate-build-status, login-to-amazon-ecr]
outputs:
DEPLOY_END_TIME: ${{ steps.export-deploy-end-time.outputs.DEPLOY_END_TIME }}
DEPLOY_START_TIME: ${{ steps.export-deploy-start-time.outputs.DEPLOY_START_TIME }}
BUILD_START_TIME: ${{ steps.export-build-start-time.outputs.BUILD_START_TIME }}
BUILD_END_TIME: ${{ steps.export-build-end-time.outputs.BUILD_END_TIME }}
SETUP_START_TIME: ${{ steps.export-setup-start-time.outputs.SETUP_START_TIME }}
SETUP_END_TIME: ${{ steps.export-setup-end-time.outputs.SETUP_END_TIME }}
YARN_OUTPUT: ${{ steps.export-yarn-output.outputs.YARN_OUTPUT }}
container:
image: 008577686731.dkr.ecr.us-gov-west-1.amazonaws.com/node-18.19.0-bullseye:latest
credentials:
username: ${{ needs.login-to-amazon-ecr.outputs.docker_username }}
password: ${{ needs.login-to-amazon-ecr.outputs.docker_password }}
# Certs added for the self hosted runner
env:
NODE_EXTRA_CA_CERTS: /etc/ssl/certs/ca-certificates.crt
APP_ENV: ${{ inputs.build_type || 'prod' }}
ports:
- 80
volumes:
- /etc/ssl/certs:/etc/ssl/certs
steps:
- name: Export setup start time
id: export-setup-start-time
run: echo SETUP_START_TIME=$(date +"%s") >> $GITHUB_OUTPUT
- name: Checkout next-build
uses: actions/checkout@v4
with:
repository: department-of-veterans-affairs/next-build
#ref: ${{ needs.validate-build-status.outputs.TAG }}
ref: ${{ github.head_ref || github.ref_name }}
path: main
sparse-checkout-cone-mode: false
- name: Checkout vets-website
uses: actions/checkout@v4
with:
repository: department-of-veterans-affairs/vets-website
path: vets-website
- name: Install awscli
run: |
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip -o awscliv2.zip
./aws/install
- uses: actions/setup-node@v4
with:
node-version: 18
- name: Setup Yarn
run: |
cd main
corepack enable
corepack install -g --cache-only .yarn/releases/corepack.tgz
- name: Install dependencies
run: cd main && yarn
- name: Export setup end time
id: export-setup-end-time
run: echo SETUP_END_TIME=$(date +"%s") >> $GITHUB_OUTPUT
- name: Export build start time
id: export-build-start-time
run: echo BUILD_START_TIME=$(date +"%s") >> $GITHUB_OUTPUT
- name: Gather vets-website assets
run: cd main && yarn setup
- name: Build site
id: export-yarn-output
uses: nick-fields/retry@v3
with:
max_attempts: 3
retry_on: error
timeout_minutes: 70
command: |
cd main && BUILD_OPTION=static yarn export --DRUPAL_CLIENT_ID ${{ secrets.PROD_DRUPAL_CLIENT_ID }} --DRUPAL_CLIENT_SECRET ${{ secrets.PROD_DRUPAL_CLIENT_SECRET }} --no-USE_REDIS | tee yarnoutput
echo YARN_OUTPUT=$(<yarnoutput) >> $GITHUB_OUTPUT
ls
ls out
if [[ $? -ne 0 ]]; then
echo "One or more pages failed to build. Exiting."
exit 1
else
cd out
ls -l
fi
- name: Build sitemap
run: cd main && yarn build:sitemap
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: us-gov-west-1
role-to-assume: ${{ vars.AWS_ASSUME_ROLE }}
role-duration-seconds: 900
- name: Export build end time
id: export-build-end-time
run: echo BUILD_END_TIME=$(date +"%s") >> $GITHUB_OUTPUT
- name: Export deploy start time
id: export-deploy-start-time
run: echo DEPLOY_START_TIME=$(date +"%s") >> $GITHUB_OUTPUT
- if: inputs.build_type == 'dev'
name: Deploy to S3
run: |
cd main && ./scripts/github-actions/deploy.sh -s $SRC -d $DEST -v
ls
env:
SRC: ./out/
DEST: s3://next-content.dev.va.gov
- if: inputs.build_type == 'staging'
name: Deploy to S3
run: |
cd main && ./scripts/github-actions/deploy.sh -s $SRC -d $DEST -v
ls
cd out
ls -l
env:
SRC: ./out/
DEST: s3://next-content.staging.va.gov
- if: inputs.build_type == 'prod'
name: Deploy to S3
run: cd main && ./scripts/github-actions/deploy.sh -s $SRC -d $DEST -v
env:
SRC: ./out/
DEST: s3://next-content.www.va.gov
- if: inputs.build_type == ''
name: Deploy to S3
run: cd main && ./scripts/github-actions/deploy.sh -s $SRC -d $DEST -v
env:
SRC: ./out/
DEST: s3://next-content.www.va.gov
- name: Export deploy end time
id: export-deploy-end-time
run: echo DEPLOY_END_TIME=$(date +"%s") >> $GITHUB_OUTPUT
notify-success:
name: Notify Success
needs: [validate-build-status, build]
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Notify Slack
uses: department-of-veterans-affairs/platform-release-tools-actions/slack-notify@8c496a4b0c9158d18edcd9be8722ed0f79e8c5b4 # main
continue-on-error: true
with:
payload: '{"attachments": [{"color": "#07711E","blocks": [{"type": "section","text": {"type": "mrkdwn","text": "Successfully released content to S3 with next-build release: ${{ needs.validate-build-status.outputs.TAG }}"}}]}]}'
channel_id: ${{ env.SLACK_CHANNEL }}
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: us-gov-west-1
role-to-assume: ${{ vars.AWS_ASSUME_ROLE }}
role-duration-seconds: 900
- name: Get Datadog token from Parameter Store
uses: department-of-veterans-affairs/action-inject-ssm-secrets@d8e6de3bde4dd728c9d732baef58b3c854b8c4bb # latest
with:
# The parameter name here is misleading. In Datadog, it's defined as CMS_CI_DD_API_KEY, for use across all CMS CI, not just content-build.
ssm_parameter: /dsva-vagov/content-build/GHA_CONTENT_BUILD_DATADOG_API_KEY
env_variable_name: GHA_CONTENT_BUILD_DATADOG_API_KEY
- name: Build JSON object
run: |
jq --null-input '{}' | \
jq '.title = "VA.gov CMS content release was successful (next-build)"' | \
jq '.text = "VA.gov Content release ${{github.run_id}} completed at \(now|strftime("%Y-%m-%d %H:%M:%S"))! https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}"' | \
jq '.date_happened = now' | \
jq '.aggregation_key = "content release ${{github.run_id}}"' | \
jq '.tags[0] = "project:vagov"' | \
jq '.tags[1] = "repo:next-build"' | \
jq '.tags[2] = "workflow:content-release"' | \
jq '.tags[3] = "env:${{ inputs.build_type || 'prod' }}"' | \
jq '.tags[5] = "status:${{needs.build.result}}"' | \
jq '.alert_type = "success"' > event.json
- name: Send event to Datadog
run: |
curl -X POST "https://api.ddog-gov.com/api/v1/events" \
-H "Content-Type: text/json" \
-H "DD-API-KEY: ${{ env.GHA_CONTENT_BUILD_DATADOG_API_KEY }}" \
-d @- < event.json
notify-failure:
name: Notify Failure
runs-on: ubuntu-latest
needs: build
if: ${{ failure() || cancelled() }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Notify Slack
uses: department-of-veterans-affairs/platform-release-tools-actions/slack-notify@8c496a4b0c9158d18edcd9be8722ed0f79e8c5b4 # main
continue-on-error: true
with:
payload: '{"attachments": [{"color": "#D33834","blocks": [{"type": "section","text": {"type": "mrkdwn","text": ">:warning: The latest content-release failed to complete: <https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}>"}}]}]}'
channel_id: ${{ env.SLACK_CHANNEL }}
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: us-gov-west-1
role-to-assume: ${{ vars.AWS_ASSUME_ROLE }}
role-duration-seconds: 900
- name: Get Datadog token from Parameter Store
uses: department-of-veterans-affairs/action-inject-ssm-secrets@d8e6de3bde4dd728c9d732baef58b3c854b8c4bb # latest
with:
# The parameter name here is misleading. In Datadog, it's defined as CMS_CI_DD_API_KEY, for use across all CMS CI, not just content-build.
ssm_parameter: /dsva-vagov/content-build/GHA_CONTENT_BUILD_DATADOG_API_KEY
env_variable_name: GHA_CONTENT_BUILD_DATADOG_API_KEY
- name: Build JSON object
run: |
jq --null-input '{}' | \
jq '.title = "VA.gov CMS content release has failed (next-build)"' | \
jq '.text = "VA.gov Content release ${{github.run_id}} failed at \(now|strftime("%Y-%m-%d %H:%M:%S"))! https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}"' | \
jq '.date_happened = now' | \
jq '.aggregation_key = "content release ${{github.run_id}}"' | \
jq '.tags[0] = "project:vagov"' | \
jq '.tags[1] = "repo:next-build"' | \
jq '.tags[2] = "workflow:content-release"' | \
jq '.tags[3] = "env:${{ inputs.build_type || 'prod' }}"' | \
jq '.tags[5] = "status:${{needs.build.result}}"' | \
jq '.alert_type = "error"' > event.json
- name: Send event to Datadog
run: |
curl -X POST "https://api.ddog-gov.com/api/v1/events" \
-H "Content-Type: text/json" \
-H "DD-API-KEY: ${{ env.GHA_CONTENT_BUILD_DATADOG_API_KEY }}" \
-d @- < event.json
record-metrics:
name: Record metrics in Datadog
runs-on: [ubuntu-latest]
needs:
- build
- validate-build-status
env:
METRIC_NAMESPACE: dsva_vagov.next_build
steps:
- name: Checkout
uses: actions/checkout@v4
#uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Get current timestamp
run: echo "NOW=$(date +"%s")" >> $GITHUB_ENV
- name: Set vars for CMS-triggered runs
if: ${{ github.event_name == 'repository_dispatch' }}
run: |
echo "DEPLOY_ENV=${{ inputs.build_type || 'prod' }}" >> $GITHUB_ENV
echo "BUILD_TRIGGER=cms" >> $GITHUB_ENV
# Calculate all of our metrics that we send to data dog
- name: Calculate durations
run: |
echo "SETUP_DURATION=$(expr ${{needs.build.outputs.SETUP_END_TIME}} - ${{needs.build.outputs.SETUP_START_TIME}})" >> $GITHUB_ENV
echo "BUILD_DURATION=$(expr ${{needs.build.outputs.BUILD_END_TIME}} - ${{needs.build.outputs.BUILD_START_TIME}})" >> $GITHUB_ENV
echo "NEXT_BUILD_DURATION=$(expr ${{needs.build.outputs.BUILD_END_TIME}} - ${{needs.build.outputs.BUILD_START_TIME}})" >> $GITHUB_ENV
echo "OVERALL_DURATION=$(expr ${{needs.build.outputs.DEPLOY_END_TIME}} - ${{needs.validate-build-status.outputs.APPROX_WORKFLOW_START_TIME}})" >> $GITHUB_ENV
echo "DEPLOY_DURATION=$(expr ${{needs.build.outputs.DEPLOY_END_TIME}} - ${{needs.build.outputs.DEPLOY_START_TIME}})" >> $GITHUB_ENV
echo "${{needs.build.outputs.YARN_OUTPUT}}" >> yarnoutput
echo "BUILT_PAGES=$(grep -oE "*\/([0-9]{4,})" ./yarnoutput| head -1 | sed 's/\///g')" >> $GITHUB_ENV
- name: Build JSON object
run: |
jq --null-input '{}' | \
jq '.series[0].metric = "${{env.METRIC_NAMESPACE}}.setup.duration"' | \
jq '.series[0].points[0] = [${{env.NOW}}, ${{env.SETUP_DURATION}}]' | \
jq '.series[1].metric = "${{env.METRIC_NAMESPACE}}.build.duration"' | \
jq '.series[1].points[0] = [${{env.NOW}}, ${{env.BUILD_DURATION}}]' | \
jq '.series[2].metric = "${{env.METRIC_NAMESPACE}}.deploy.duration"' | \
jq '.series[2].points[0] = [${{env.NOW}}, ${{env.DEPLOY_DURATION}}]' | \
jq '.series[3].metric = "${{env.METRIC_NAMESPACE}}.overall.duration"' | \
jq '.series[3].points[0] = [${{env.NOW}}, ${{env.OVERALL_DURATION}}]' | \
jq '.series[4].metric = "${{env.METRIC_NAMESPACE}}.built.pages"' | \
jq '.series[4].points[0] = [${{env.NOW}}, ${{env.BUILT_PAGES}}]' | \
jq '.series[].tags[0] = "env:${{env.DEPLOY_ENV}}"' | \
jq '.series[].tags[1] = "build_number:${{github.run_number}}"' | \
jq '.series[].tags[2] = "status:${{needs.deploy.result}}"' | \
jq '.series[].tags[3] = "trigger:${{env.BUILD_TRIGGER}}"' > metrics.json
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-gov-west-1
- name: Get Datadog api key from Parameter Store
uses: department-of-veterans-affairs/action-inject-ssm-secrets@d8e6de3bde4dd728c9d732baef58b3c854b8c4bb # latest
with:
ssm_parameter: /dsva-vagov/content-build/GHA_CONTENT_BUILD_DATADOG_API_KEY
env_variable_name: GHA_CONTENT_BUILD_DATADOG_API_KEY
- name: Get Datadog app key from Parameter Store
uses: department-of-veterans-affairs/action-inject-ssm-secrets@d8e6de3bde4dd728c9d732baef58b3c854b8c4bb # latest
with:
ssm_parameter: /dsva-vagov/content-build/GHA_CONTENT_BUILD_DATADOG_APP_KEY
env_variable_name: GHA_CONTENT_BUILD_DATADOG_APP_KEY
- name: Send metrics to Datadog
run: |
curl -X POST "https://api.ddog-gov.com/api/v1/series" \
-H "Content-Type: text/json" \
-H "DD-API-KEY: ${{ env.GHA_CONTENT_BUILD_DATADOG_API_KEY }}" \
-d @- < metrics.json