Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VACMS-17023 nightly archive workflow #478

Merged
merged 14 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 158 additions & 0 deletions .github/workflows/archive.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
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:

# todo: make sure this uses latest tagged release
- name: Checkout next-build
uses: actions/checkout@v4
with:
repository: department-of-veterans-affairs/next-build
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: Show build archive size
tjheffner marked this conversation as resolved.
Show resolved Hide resolved
run: |
df -h
du -h ${{ 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
Loading