Skip to content

content-release

content-release #11900

name: Content Release
on:
repository_dispatch:
types: [content-release]
workflow_dispatch:
concurrency:
group: content-release-prod
env:
CMS_NOTIFICATIONS_SLACK: CJT90C0UT # cms-notifications
VFS_PLATFORM_BUILDS_SLACK: C0MQ281DJ # vfs-platform-builds
BROKEN_LINKS_SLACK: C030F5WV2TF # content-broken-links
CONTENT_BUILD_CHANNEL_ID: C02VD909V08 #status-content-build
NODE_EXTRA_CA_CERTS: /etc/ssl/certs/ca-certificates.crt
BUILDTYPE: vagovprod
DEPLOY_BUCKET: content.www.va.gov
DRUPAL_ADDRESS: https://prod.cms.va.gov
INSTANCE_TYPE: m6i.4xlarge
MAXIMUM_HEAP: 5000
# secrets.ACTIONS_RUNNER_DEBUG is set to 'true' when re-running a workflow with debug.
ACTIONS_RUNNER_DEBUG: ${{ secrets.ACTIONS_RUNNER_DEBUG }}
jobs:
validate-build-status:
name: Validate Build Status
runs-on: [self-hosted, asg]
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@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
- name: Notify CMS - Starting
uses: ./.github/workflows/authenticated-cms-request
with:
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
url: ${{ env.DRUPAL_ADDRESS }}/api/content_release/starting
method: GET
- name: Install dependencies
uses: ./.github/workflows/install
with:
key: ${{ hashFiles('yarn.lock') }}
yarn_cache_folder: ~/.cache/yarn
path: |
~/.cache/yarn
node_modules
- name: Get latest release
id: get-latest-release
uses: ./.github/workflows/fetch-latest-release
- name: Validate build status
run: node ./script/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: [self-hosted, asg]
needs: validate-build-status
steps:
- name: Checkout
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
- 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 content-build coming up (using ${{ needs.validate-build-status.outputs.TAG }}). <https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}>"}}]}]}'
channel_id: ${{ env.CONTENT_BUILD_CHANNEL_ID }}
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
build:
name: Build
runs-on: [self-hosted, asg]
needs:
- validate-build-status
timeout-minutes: 60
defaults:
run:
working-directory: content-build
outputs:
vagovprod_buildtime: ${{ env.vagovprod_buildtime }}
BUILD_START_TIME: ${{ steps.export-build-start-time.outputs.BUILD_START_TIME }}
BUILD_END_TIME: ${{ steps.export-build-end-time.outputs.BUILD_END_TIME }}
CONTENT_BUILD_START_TIME: ${{ steps.export-content-build-start-time.outputs.CONTENT_BUILD_START_TIME }}
CONTENT_BUILD_END_TIME: ${{ steps.export-content-build-end.outputs.CONTENT_BUILD_END_TIME }}
GQL_QUERY_DURATION: ${{ steps.export-gql-query-duration.outputs.GQL_QUERY_DURATION }}
GQL_PAGE_COUNT: ${{ steps.export-gql-page-count.outputs.GQL_PAGE_COUNT }}
ARCHIVE_END_TIME: ${{ steps.export-archive-end-time.outputs.ARCHIVE_END_TIME }}
env:
CHROMEDRIVER_FILEPATH: /usr/local/share/chrome_driver/chromedriver
steps:
- name: Export build start time
id: export-build-start-time
run: echo BUILD_START_TIME=$(date +"%s") >> $GITHUB_OUTPUT
working-directory: ${{ github.workspace }}
- name: Checkout vagov-content
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
with:
repository: department-of-veterans-affairs/vagov-content
path: vagov-content
- name: Checkout content-build
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
with:
path: content-build
ref: ${{ needs.validate-build-status.outputs.REF }}
- name: Get Node version
id: get-node-version
run: echo NODE_VERSION=$(cat .nvmrc) >> $GITHUB_OUTPUT
- name: Setup Node
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
with:
node-version: ${{ steps.get-node-version.outputs.NODE_VERSION }}
- name: Setup Yarn
run: npm i -g [email protected]
- name: Cache dependencies
id: cache-dependencies
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
with:
path: |
.cache/yarn
**/node_modules
key: ${{ steps.get-node-version.outputs.NODE_VERSION }}-on-demand-runner-${{ hashFiles('**/yarn.lock') }}
restore-keys: ${{ steps.get-node-version.outputs.NODE_VERSION }}-on-demand-runner-
- name: Install dependencies
uses: nick-invision/retry@943e742917ac94714d2f408a0e8320f2d1fcafcd # v2.8.3
with:
command: cd content-build && yarn install --frozen-lockfile --prefer-offline
max_attempts: 3
timeout_minutes: 7
env:
YARN_CACHE_FOLDER: .cache/yarn
- name: Wait for the CMS to be ready
uses: ./content-build/.github/workflows/wait-for-cms-ready
- name: Export content build start time
id: export-content-build-start-time
run: echo CONTENT_BUILD_START_TIME=$(date +"%s") >> $GITHUB_OUTPUT
working-directory: ${{ github.workspace }}
- name: Get buildtime
id: buildtime
run: |
BUILDTIME=$(date +%s)
echo buildtime=$BUILDTIME >> $GITHUB_OUTPUT
echo "${{ env.BUILDTYPE }}_buildtime=$BUILDTIME" >> $GITHUB_ENV
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef # v2.0.0
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: set Drupal prod password
uses: department-of-veterans-affairs/action-inject-ssm-secrets@d8e6de3bde4dd728c9d732baef58b3c854b8c4bb # latest
with:
ssm_parameter: /cms/prod/drupal_api_users/content_build_api/password
env_variable_name: DRUPAL_PASSWORD
- name: set Drupal prod username
uses: department-of-veterans-affairs/action-inject-ssm-secrets@d8e6de3bde4dd728c9d732baef58b3c854b8c4bb # latest
with:
ssm_parameter: /cms/prod/drupal_api_users/content_build_api/username
env_variable_name: DRUPAL_USERNAME
- name: Notify CMS - In Progress
uses: ./content-build/.github/workflows/authenticated-cms-request
with:
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
url: ${{ env.DRUPAL_ADDRESS }}/api/content_release/inprogress
method: GET
- name: Get verbose level
if: ${{ env.ACTIONS_RUNNER_DEBUG == 'true' }}
run: echo "VERBOSE_BUILD= --verbose" >> $GITHUB_ENV
- name: Build
run: |
set -eo pipefail
NODE_OPTIONS=--max-old-space-size=${{ env.MAXIMUM_HEAP }} yarn build:content_release --buildtype=${{ env.BUILDTYPE }} --asset-source=local --drupal-address=${{ env.DRUPAL_ADDRESS }} --drupal-user=${{ env.DRUPAL_USERNAME }} --drupal-password="${{ env.DRUPAL_PASSWORD }}" --pull-drupal --drupal-max-parallel-requests=15 --no-drupal-proxy ${{env.VERBOSE_BUILD}} | tee build-output.txt
timeout-minutes: 40
env:
NODE_ENV: production
- name: Export content build end time
id: export-content-build-end
run: echo CONTENT_BUILD_END_TIME=$(date +"%s") >> $GITHUB_OUTPUT
working-directory: ${{ github.workspace }}
- name: Export gql query duration
id: export-gql-query-duration
run: echo GQL_QUERY_DURATION=$(cat build-output.txt | grep -oP 'queries in \d+s' | grep -oP '\d+') >> $GITHUB_OUTPUT
- name: Export gql page count
id: export-gql-page-count
run: echo GQL_PAGE_COUNT=$(cat build-output.txt | grep -oP 'with \d+ pages' | grep -oP '\d+') >> $GITHUB_OUTPUT
- name: Set vars for CMS-triggered runs
if: ${{ github.event_name == 'repository_dispatch' }}
run: |
echo "DEPLOY_ENV=prod" >> $GITHUB_ENV
echo "BUILD_TRIGGER=cms" >> $GITHUB_ENV
- name: Build JSON object for step metrics
run: |
cat build/${{env.BUILDTYPE}}/metalsmith-step-metrics.json | \
jq '.series[].tags[0] = "env:${{env.DEPLOY_ENV}}"' | \
jq '.series[].tags[1] = "build_number:${{github.run_number}}"' | \
jq '.series[].tags[2] = "instance_type:${{env.INSTANCE_TYPE}}"' | \
jq '.series[].tags[3] = "heap_size:${{env.MAXIMUM_HEAP}}"' | \
jq '.series[].tags[4] = "trigger:${{env.BUILD_TRIGGER}}"' > metrics.json
- 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: 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
- name: Check broken links
id: get-broken-link-info
run: node ./script/github-actions/check-broken-links-blocks.js ${{ env.BUILDTYPE }}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef # v2.0.0
if: ${{ steps.get-broken-link-info.outputs.UPLOAD_AND_NOTIFY == '1' && always() }}
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 Slack app token
uses: department-of-veterans-affairs/action-inject-ssm-secrets@d8e6de3bde4dd728c9d732baef58b3c854b8c4bb # latest
if: ${{ steps.get-broken-link-info.outputs.UPLOAD_AND_NOTIFY == '1' && always() }}
with:
ssm_parameter: /devops/github_actions_slack_socket_token
env_variable_name: SLACK_APP_TOKEN
- name: Get Slack bot token
uses: department-of-veterans-affairs/action-inject-ssm-secrets@d8e6de3bde4dd728c9d732baef58b3c854b8c4bb # latest
if: ${{ steps.get-broken-link-info.outputs.UPLOAD_AND_NOTIFY == '1' && always() }}
with:
ssm_parameter: /devops/github_actions_slack_bot_user_token
env_variable_name: SLACK_BOT_TOKEN
- name: Get role from Parameter Store
uses: department-of-veterans-affairs/action-inject-ssm-secrets@d8e6de3bde4dd728c9d732baef58b3c854b8c4bb # latest
if: ${{ steps.get-broken-link-info.outputs.UPLOAD_AND_NOTIFY == '1' && always() }}
with:
ssm_parameter: /frontend-team/github-actions/parameters/AWS_FRONTEND_NONPROD_ROLE
env_variable_name: AWS_FRONTEND_NONPROD_ROLE
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef # v2.0.0
if: ${{ steps.get-broken-link-info.outputs.UPLOAD_AND_NOTIFY == '1' && always() }}
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
role-to-assume: ${{ env.AWS_FRONTEND_NONPROD_ROLE }}
role-duration-seconds: 900
role-session-name: vsp-frontendteam-githubaction
- name: Upload broken links file
if: ${{ steps.get-broken-link-info.outputs.UPLOAD_AND_NOTIFY == '1' && always() }}
run: aws s3 cp ./logs/${{ env.BUILDTYPE }}-broken-links.json s3://vetsgov-website-builds-s3-upload/broken-link-reports/${{ env.BUILDTYPE }}-broken-links.json --acl public-read --region us-gov-west-1
- name: Notify content broken links channel about broken links
uses: slackapi/slack-github-action@007b2c3c751a190b6f0f040e47ed024deaa72844 # v1.23.0
id: notify-content-broken-links
if: ${{ steps.get-broken-link-info.outputs.UPLOAD_AND_NOTIFY == '1' && always() }}
continue-on-error: true
env:
SSL_CERT_DIR: /etc/ssl/certs
SLACK_BOT_TOKEN: ${{ env.SLACK_BOT_TOKEN }}
with:
payload: ${{ steps.get-broken-link-info.outputs.SLACK_BLOCKS }}
channel-id: ${{ env.BROKEN_LINKS_SLACK }}
- name: Generate build details
run: |
cat > build/${{ env.BUILDTYPE }}/BUILD.txt << EOF
BUILDTYPE=${{ env.BUILDTYPE }}
NODE_ENV=production
BRANCH_NAME=$(echo "${GITHUB_REF#refs/heads/}")
CHANGE_TARGET=null
RUN_ID=${{ github.run_id }}
RUN_NUMBER=${{ github.run_number }}
REF=${{ needs.validate-build-status.outputs.REF }}
TAG=${{ needs.validate-build-status.outputs.TAG }}
BUILDTIME=${{ steps.buildtime.outputs.buildtime }}
EOF
- name: Prearchive
run: node ./script/prearchive.js --buildtype=${{ env.BUILDTYPE }}
- name: Compress build
run: tar -C build/${{ env.BUILDTYPE }} -cf ${{ env.BUILDTYPE }}.tar.bz2 .
- name: Export build end time
id: export-build-end-time
run: echo BUILD_END_TIME=$(date +"%s") >> $GITHUB_OUTPUT
working-directory: ${{ github.workspace }}
# Archive build by uploading it to S3
- name: Show build archive size
run: |
df -h
du -h ${{ env.BUILDTYPE }}.tar.bz2
- name: Configure AWS credentials (1)
uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef # v2.0.0
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 role from Parameter Store
uses: department-of-veterans-affairs/action-inject-ssm-secrets@d8e6de3bde4dd728c9d732baef58b3c854b8c4bb # latest
with:
ssm_parameter: /frontend-team/github-actions/parameters/AWS_FRONTEND_NONPROD_ROLE
env_variable_name: AWS_FRONTEND_NONPROD_ROLE
- name: Configure AWS Credentials (2)
uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef # v2.0.0
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
role-to-assume: ${{ env.AWS_FRONTEND_NONPROD_ROLE }}
role-duration-seconds: 900
role-session-name: vsp-frontendteam-githubaction
- name: Upload build
run: aws s3 cp ${{ env.BUILDTYPE }}.tar.bz2 s3://vetsgov-website-builds-s3-upload/content-build/${{needs.validate-build-status.outputs.REF}}/${{ env.BUILDTYPE }}.tar.bz2 --acl public-read --region us-gov-west-1 --no-progress
- name: Export archive end time
id: export-archive-end-time
run: echo ARCHIVE_END_TIME=$(date +"%s") >> $GITHUB_OUTPUT
deploy:
name: Deploy
runs-on: [self-hosted, asg]
needs:
- validate-build-status
- build
outputs:
DEPLOY_END_TIME: ${{ steps.export-deploy-end-time.outputs.DEPLOY_END_TIME }}
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
- name: Configure AWS credentials (1)
uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef # v2.0.0
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 role from Parameter Store
uses: department-of-veterans-affairs/action-inject-ssm-secrets@d8e6de3bde4dd728c9d732baef58b3c854b8c4bb # latest
with:
ssm_parameter: /frontend-team/github-actions/parameters/AWS_FRONTEND_PROD_ROLE
env_variable_name: AWS_FRONTEND_PROD_ROLE
- name: Configure AWS Credentials (2)
uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef # v2.0.0
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
role-to-assume: ${{ env.AWS_FRONTEND_PROD_ROLE }}
role-duration-seconds: 900
role-session-name: vsp-frontendteam-githubaction
- name: Deploy
run: ./script/github-actions/deploy.sh -s $SRC -d $DEST -v
env:
SRC: s3://vetsgov-website-builds-s3-upload/content-build/${{needs.validate-build-status.outputs.REF}}/${{env.BUILDTYPE}}.tar.bz2
DEST: s3://${{ env.DEPLOY_BUCKET }}
- name: Wait for the CMS to be ready
uses: ./.github/workflows/wait-for-cms-ready
- name: Notify CMS - Complete
uses: ./.github/workflows/authenticated-cms-request
with:
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
url: ${{ env.DRUPAL_ADDRESS }}/api/content_release/complete
method: GET
- name: CMS GovDelivery callback
uses: ./.github/workflows/authenticated-cms-request
with:
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
url: ${{ env.DRUPAL_ADDRESS }}/api/govdelivery_bulletins/queue?EndTime=${{ needs.build.outputs.vagovprod_buildtime }}&src=gha&runId=${{ github.run_id }}&runNumber=${{ github.run_number }}
method: GET
# A failure here should not prevent the workflow from continuing.
continue-on-error: true
- name: Export deploy end time
id: export-deploy-end-time
run: echo DEPLOY_END_TIME=$(date +"%s") >> $GITHUB_OUTPUT
notify-success:
name: Notify Success
runs-on: [self-hosted, asg]
needs:
- validate-build-status
- deploy
steps:
- name: Checkout
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
- name: Wait for the CMS to be ready
uses: ./.github/workflows/wait-for-cms-ready
- name: Notify CMS - Ready
uses: ./.github/workflows/authenticated-cms-request
with:
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
url: ${{ env.DRUPAL_ADDRESS }}/api/content_release/ready
method: GET
notify-success-slack:
name: Notify Success (Slack)
runs-on: [self-hosted, asg]
needs:
- validate-build-status
- deploy
steps:
- name: Notify Slack
uses: department-of-veterans-affairs/platform-release-tools-actions/slack-notify@8c496a4b0c9158d18edcd9be8722ed0f79e8c5b4 #
continue-on-error: true
with:
payload: '{"attachments": [{"color": "#2EB67D","blocks": [{"type": "section","text": {"type": "mrkdwn","text": "content release using ${{ needs.validate-build-status.outputs.TAG }} is complete."}}]}]}'
channel_id: ${{ env.CONTENT_BUILD_CHANNEL_ID }}
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
notify-failure:
name: Notify Failure
runs-on: [self-hosted, asg]
if: |
(failure() && needs.deploy.result != 'success')
needs: deploy
steps:
- name: Checkout
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef # v2.0.0
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: Wait for the CMS to be ready
uses: ./.github/workflows/wait-for-cms-ready
- name: Notify CMS - Error
uses: ./.github/workflows/authenticated-cms-request
with:
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
url: ${{ env.DRUPAL_ADDRESS }}/api/content_release/error
method: GET
- name: Get Datadog token 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: Build JSON object
run: |
jq --null-input '{}' | \
jq '.title = "VA.gov CMS content release has failed"' | \
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:content-build"' | \
jq '.tags[2] = "workflow:content-release"' | \
jq '.tags[3] = "env:${{env.DEPLOY_ENV}}"' | \
jq '.tags[5] = "status:${{needs.deploy.result}}"' | \
jq '.tags[6] = "trigger:${{env.BUILD_TRIGGER}}"' | \
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
notify-failure-slack:
name: Notify Failure (Slack)
runs-on: [self-hosted, asg]
if: |
(failure() && needs.deploy.result != 'success')
needs: deploy
steps:
- name: Notify Slack
uses: department-of-veterans-affairs/platform-release-tools-actions/slack-notify@8c496a4b0c9158d18edcd9be8722ed0f79e8c5b4
continue-on-error: true
with:
payload: >
{
"attachments": [
{
"color": "#2EB67D",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": ":bangbang: <!subteam^S010U41C30V|cms-helpdesk> Content release using ${{ needs.validate-build-status.outputs.TAG || 'an unknown version' }} has failed."
}
}
]
}
]
}
channel_id: ${{ env.CONTENT_BUILD_CHANNEL_ID }}
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
record-metrics:
name: Record metrics in Datadog
runs-on: [self-hosted, asg]
needs:
- build
- deploy
- validate-build-status
env:
METRIC_NAMESPACE: dsva_vagov.content_build
steps:
- name: Checkout
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
- 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=prod" >> $GITHUB_ENV
echo "BUILD_TRIGGER=cms" >> $GITHUB_ENV
- name: Calculate durations
run: |
echo "SETUP_DURATION=$(expr ${{needs.build.outputs.BUILD_START_TIME}} - ${{needs.validate-build-status.outputs.APPROX_WORKFLOW_START_TIME}})" >> $GITHUB_ENV
echo "BUILD_DURATION=$(expr ${{needs.build.outputs.BUILD_END_TIME}} - ${{needs.build.outputs.BUILD_START_TIME}})" >> $GITHUB_ENV
echo "CONTENT_BUILD_DURATION=$(expr ${{needs.build.outputs.CONTENT_BUILD_END_TIME}} - ${{needs.build.outputs.CONTENT_BUILD_START_TIME}})" >> $GITHUB_ENV
echo "ARCHIVE_DURATION=$(expr ${{needs.build.outputs.ARCHIVE_END_TIME}} - ${{needs.build.outputs.BUILD_END_TIME}})" >> $GITHUB_ENV
echo "DEPLOY_DURATION=$(expr ${{needs.deploy.outputs.DEPLOY_END_TIME}} - ${{needs.build.outputs.ARCHIVE_END_TIME}})" >> $GITHUB_ENV
echo "OVERALL_DURATION=$(expr ${{needs.deploy.outputs.DEPLOY_END_TIME}} - ${{needs.validate-build-status.outputs.APPROX_WORKFLOW_START_TIME}})" >> $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}}.build.gql.pages"' | \
jq '.series[2].points[0] = [${{env.NOW}}, ${{needs.build.outputs.GQL_PAGE_COUNT}}]' | \
jq '.series[3].metric = "${{env.METRIC_NAMESPACE}}.build.gql.duration"' | \
jq '.series[3].points[0] = [${{env.NOW}}, ${{needs.build.outputs.GQL_QUERY_DURATION}}]' | \
jq '.series[4].metric = "${{env.METRIC_NAMESPACE}}.build.content-build.duration"' | \
jq '.series[4].points[0] = [${{env.NOW}}, ${{env.CONTENT_BUILD_DURATION}}]' | \
jq '.series[5].metric = "${{env.METRIC_NAMESPACE}}.archive.duration"' | \
jq '.series[5].points[0] = [${{env.NOW}}, ${{env.ARCHIVE_DURATION}}]' | \
jq '.series[6].metric = "${{env.METRIC_NAMESPACE}}.deploy.duration"' | \
jq '.series[6].points[0] = [${{env.NOW}}, ${{env.DEPLOY_DURATION}}]' | \
jq '.series[7].metric = "${{env.METRIC_NAMESPACE}}.overall.duration"' | \
jq '.series[7].points[0] = [${{env.NOW}}, ${{env.OVERALL_DURATION}}]' | \
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@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef # v2.0.0
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