Skip to content

Commit

Permalink
VACMS-17023 nightly archive workflow (#478)
Browse files Browse the repository at this point in the history
  • Loading branch information
tjheffner authored Mar 29, 2024
1 parent 9f23308 commit 8d7da21
Show file tree
Hide file tree
Showing 24 changed files with 621 additions and 0 deletions.
153 changes: 153 additions & 0 deletions .github/workflows/archive.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
name: Nightly Archive

permissions:
id-token: write # This is required for requesting the JWT for AWS creds
contents: read # This is required for actions/checkout

on:
# Schedule; currently once nightly, at 7:20 UTC.
schedule:
- cron: 20 7 * * *

env:
BUILD_TYPE: vagovprod
APP_ENV: prod
NODE_EXTRA_CA_CERTS: /etc/ssl/certs/ca-certificates.crt

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 }}

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 }}

build:
name: Archive static build on S3
timeout-minutes: 60
runs-on: [self-hosted, asg]
needs: [validate-build-status, login-to-amazon-ecr]
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: ${{ env.NODE_EXTRA_CA_CERTS }}
APP_ENV: ${{ env.APP_ENV }}
ports:
- 80
volumes:
- /etc/ssl/certs:/etc/ssl/certs
steps:

- name: Checkout next-build
uses: actions/checkout@v4
with:
repository: department-of-veterans-affairs/next-build
ref: ${{ needs.validate-build-status.outputs.TAG }}
path: main

- 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: Gather vets-website assets
run: cd main && yarn setup

- name: Build site
uses: nick-fields/retry@v3
with:
max_attempts: 3
retry_on: error
timeout_minutes: 30
command: cd main && yarn export --DRUPAL_CLIENT_ID ${{ secrets.PROD_DRUPAL_CLIENT_ID }} --DRUPAL_CLIENT_SECRET ${{ secrets.PROD_DRUPAL_CLIENT_SECRET }} --USE_REDIS=false

- name: Build sitemap
run: cd main && yarn build:sitemap

- name: Compress built site for archive
run: tar -c main/out/ -cf ${{ env.BUILD_TYPE }}.tar.bz2 .

- 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: Upload archive to S3
run: aws s3 cp ${{ env.BUILD_TYPE }}.tar.bz2 s3://vetsgov-website-builds-s3-upload/next-build/${{needs.validate-build-status.outputs.REF}}/${{ env.BUILD_TYPE }}.tar.bz2 --acl public-read --region us-gov-west-1 --no-progress
env:
SRC: ./out/
DEST: s3://next-content.www.va.gov
36 changes: 36 additions & 0 deletions .github/workflows/fetch-latest-release/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
## Note
This is a local adaptation of Greg Ziegan's useful [fetch-latest-release](https://github.com/gregziegan/fetch-latest-release) action. It has been moved here in order to update its dependencies and to grant us control over it.

This is similar to [content-build's adaptation](https://github.com/department-of-veterans-affairs/content-build/blob/main/.github/workflows/fetch-latest-release/README.md)

## fetch-latest-release
A tiny GitHub action to fetch the latest GitHub release for a given repository

## Inputs

| Parameter | Description | Required | Default |
| ------------------- | ------------------------------------------------------------------------------------------ | -------- | ------------ |
| `github_token` | A Github token, usually `${{ github.token }}`. | N | `${{ github.token }}` |
| `repo_path` | Provide a "owner/repo" string for fetching from a different repo. | N | The current repo |

## Output

- `url` The HTTP URL for this release
- `assets_url`: The REST API HTTP URL for this release's assets
- `upload_url`: The REST API HTTP URL for uploading to this release
- `html_url`: The REST API HTTP URL for this release
- `id`: ''
- `node_id`: The unique identifier for accessing this release in the GraphQL API
- `tag_name`: The name of the release's Git tag
- `target_commitish`: ''
- `name`: The title of the release
- `body`: The description of the release
- `draft`: Whether or not the release is a draft
- `prerelease`: Whether or not the release is a prerelease
- `author_id`: ''
- `author_node_id`: The unique identifier for accessing this release's author in the GraphQL API
- `author_url`: The REST API HTTP URL for this release's author
- `author_login`: The username used to login.
- `author_html_url`: The HTTP URL for this release's author
- `author_type`: ''
- `author_site_admin`: Whether or not this user is a site administrator
56 changes: 56 additions & 0 deletions .github/workflows/fetch-latest-release/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@

name: Fetch Latest Release
description: A tiny GitHub action to fetch the latest GitHub release for a given repository
author: Greg Ziegan
branding:
color: green
icon: tag

runs:
using: node20
main: index.js

inputs:
github_token:
description: A Github token for the repo, usually `{{ github.token }}`.
required: false
default: ${{ github.token }}
repo_path:
description: Provide a "owner/repo" string for fetching from a different repo.
required: false

outputs:
url:
description: The HTTP URL for this release
assets_url:
description: The REST API HTTP URL for this release's assets
upload_url:
description: The REST API HTTP URL for uploading to this release
html_url:
description: The REST API HTTP URL for this release
id:
description: ''
node_id:
description: The unique identifier for accessing this release in the GraphQL API
tag_name:
description: The name of the release's Git tag
target_commitish:
description: ''
name:
description: The title of the release.
draft:
description: Whether or not the release is a draft
author_id:
description: ''
author_node_id:
description: The unique identifier for accessing this release's author in the GraphQL API
author_url:
description: The REST API HTTP URL for this release's author
author_login:
description: The username used to login.
author_html_url:
description: The HTTP URL for this release's author
author_type:
description: ''
author_site_admin:
description: Whether or not this user is a site administrator.
66 changes: 66 additions & 0 deletions .github/workflows/fetch-latest-release/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
const core = require('@actions/core')
const github = require('@actions/github')

const customRepo = (repoPath) => {
const segments = repoPath.split('/', 2)

if (segments.length < 2) {
core.info('Please provide a repository in the format `owner/repo`.')
}

return segments
}

const repoInput = core.getInput('repo_path')

const [owner, repo] = repoInput
? customRepo(repoInput)
: process.env['GITHUB_REPOSITORY'].split('/', 2)

const octokit = new github.getOctokit(
core.getInput('github_token', { required: true })
)

async function run() {
let latestRelease

core.info(`Fetching the latest release for \`${owner}/${repo}\``)

try {
latestRelease = await octokit.rest.repos.getLatestRelease({
owner,
repo,
})
} catch (error) {
core.info('Could not fetch the latest release. Have you made one yet?')
core.setFailed(error)
}

const { data } = latestRelease

core.setOutput('url', data.url)
core.setOutput('assets_url', data.assets_url)
core.setOutput('upload_url', data.upload_url)
core.setOutput('html_url', data.html_url)
core.setOutput('id', data.id.toString())
core.setOutput('node_id', data.node_id)
core.setOutput('tag_name', data.tag_name)
core.setOutput('target_commitish', data.target_commitish)
core.setOutput('name', data.name)
core.setOutput('body', data.body)
core.setOutput('draft', data.draft)
core.setOutput('prerelease', data.prerelease)
core.setOutput('author_id', data.author.id.toString())
core.setOutput('author_node_id', data.author.node_id)
core.setOutput('author_url', data.author.url)
core.setOutput('author_login', data.author.login)
core.setOutput('author_html_url', data.author.html_url)
core.setOutput('author_type', data.author.type)
core.setOutput('author_site_admin', data.author.site_admin)
}

try {
run()
} catch (error) {
core.setFailed(`Action failed with error ${error}`)
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,12 @@
},
"dependencies": {
"@actions/core": "^1.10.1",
"@actions/github": "^6.0.0",
"@department-of-veterans-affairs/component-library": "^33.0.0",
"@department-of-veterans-affairs/formation": "^10.1.0",
"@department-of-veterans-affairs/web-components": "^4.45.31",
"@fortawesome/fontawesome-free": "^6.5.1",
"@octokit/rest": "^20.0.2",
"@storybook/react": "^7.6.3",
"@types/react-gtm-module": "^2.0.3",
"axios": "^1.6.3",
Expand Down
Loading

0 comments on commit 8d7da21

Please sign in to comment.