diff --git a/.github/workflows/archive.yml b/.github/workflows/archive.yml new file mode 100644 index 000000000..09bf2432a --- /dev/null +++ b/.github/workflows/archive.yml @@ -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 diff --git a/.github/workflows/fetch-latest-release/README.md b/.github/workflows/fetch-latest-release/README.md new file mode 100644 index 000000000..a77f1be83 --- /dev/null +++ b/.github/workflows/fetch-latest-release/README.md @@ -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 diff --git a/.github/workflows/fetch-latest-release/action.yml b/.github/workflows/fetch-latest-release/action.yml new file mode 100644 index 000000000..6b7c27088 --- /dev/null +++ b/.github/workflows/fetch-latest-release/action.yml @@ -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. diff --git a/.github/workflows/fetch-latest-release/index.js b/.github/workflows/fetch-latest-release/index.js new file mode 100644 index 000000000..21c03e267 --- /dev/null +++ b/.github/workflows/fetch-latest-release/index.js @@ -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}`) +} diff --git a/.yarn/cache/@actions-github-npm-6.0.0-555bf7818c-81831a7837.zip b/.yarn/cache/@actions-github-npm-6.0.0-555bf7818c-81831a7837.zip new file mode 100644 index 000000000..ea4c426f5 Binary files /dev/null and b/.yarn/cache/@actions-github-npm-6.0.0-555bf7818c-81831a7837.zip differ diff --git a/.yarn/cache/@actions-http-client-npm-2.2.1-1cd331df79-c51c003cd6.zip b/.yarn/cache/@actions-http-client-npm-2.2.1-1cd331df79-c51c003cd6.zip new file mode 100644 index 000000000..a759e8e96 Binary files /dev/null and b/.yarn/cache/@actions-http-client-npm-2.2.1-1cd331df79-c51c003cd6.zip differ diff --git a/.yarn/cache/@octokit-auth-token-npm-4.0.0-9ad78a752f-d78f4dc48b.zip b/.yarn/cache/@octokit-auth-token-npm-4.0.0-9ad78a752f-d78f4dc48b.zip new file mode 100644 index 000000000..1772a6eb1 Binary files /dev/null and b/.yarn/cache/@octokit-auth-token-npm-4.0.0-9ad78a752f-d78f4dc48b.zip differ diff --git a/.yarn/cache/@octokit-core-npm-5.1.0-6f995d9055-170d16f557.zip b/.yarn/cache/@octokit-core-npm-5.1.0-6f995d9055-170d16f557.zip new file mode 100644 index 000000000..153b15b27 Binary files /dev/null and b/.yarn/cache/@octokit-core-npm-5.1.0-6f995d9055-170d16f557.zip differ diff --git a/.yarn/cache/@octokit-endpoint-npm-9.0.4-1b64d334f9-ed1b64a448.zip b/.yarn/cache/@octokit-endpoint-npm-9.0.4-1b64d334f9-ed1b64a448.zip new file mode 100644 index 000000000..5c8adfa1e Binary files /dev/null and b/.yarn/cache/@octokit-endpoint-npm-9.0.4-1b64d334f9-ed1b64a448.zip differ diff --git a/.yarn/cache/@octokit-graphql-npm-7.0.2-b5522f5b29-05a752c4c2.zip b/.yarn/cache/@octokit-graphql-npm-7.0.2-b5522f5b29-05a752c4c2.zip new file mode 100644 index 000000000..6fa875139 Binary files /dev/null and b/.yarn/cache/@octokit-graphql-npm-7.0.2-b5522f5b29-05a752c4c2.zip differ diff --git a/.yarn/cache/@octokit-openapi-types-npm-20.0.0-1aac079689-23ff761375.zip b/.yarn/cache/@octokit-openapi-types-npm-20.0.0-1aac079689-23ff761375.zip new file mode 100644 index 000000000..52b884624 Binary files /dev/null and b/.yarn/cache/@octokit-openapi-types-npm-20.0.0-1aac079689-23ff761375.zip differ diff --git a/.yarn/cache/@octokit-plugin-paginate-rest-npm-9.2.1-9310cd3549-554ad17a7d.zip b/.yarn/cache/@octokit-plugin-paginate-rest-npm-9.2.1-9310cd3549-554ad17a7d.zip new file mode 100644 index 000000000..1a7170d1b Binary files /dev/null and b/.yarn/cache/@octokit-plugin-paginate-rest-npm-9.2.1-9310cd3549-554ad17a7d.zip differ diff --git a/.yarn/cache/@octokit-plugin-request-log-npm-4.0.1-bc9d8da84b-fd8c0a2014.zip b/.yarn/cache/@octokit-plugin-request-log-npm-4.0.1-bc9d8da84b-fd8c0a2014.zip new file mode 100644 index 000000000..baca4a2ef Binary files /dev/null and b/.yarn/cache/@octokit-plugin-request-log-npm-4.0.1-bc9d8da84b-fd8c0a2014.zip differ diff --git a/.yarn/cache/@octokit-plugin-rest-endpoint-methods-npm-10.4.1-3fc380dbdf-3e0e95515c.zip b/.yarn/cache/@octokit-plugin-rest-endpoint-methods-npm-10.4.1-3fc380dbdf-3e0e95515c.zip new file mode 100644 index 000000000..b9ba5a946 Binary files /dev/null and b/.yarn/cache/@octokit-plugin-rest-endpoint-methods-npm-10.4.1-3fc380dbdf-3e0e95515c.zip differ diff --git a/.yarn/cache/@octokit-request-error-npm-5.0.1-eda589102d-a681341e43.zip b/.yarn/cache/@octokit-request-error-npm-5.0.1-eda589102d-a681341e43.zip new file mode 100644 index 000000000..ac2bc4ac4 Binary files /dev/null and b/.yarn/cache/@octokit-request-error-npm-5.0.1-eda589102d-a681341e43.zip differ diff --git a/.yarn/cache/@octokit-request-npm-8.2.0-27c446977b-24dd2c9676.zip b/.yarn/cache/@octokit-request-npm-8.2.0-27c446977b-24dd2c9676.zip new file mode 100644 index 000000000..c00e72583 Binary files /dev/null and b/.yarn/cache/@octokit-request-npm-8.2.0-27c446977b-24dd2c9676.zip differ diff --git a/.yarn/cache/@octokit-rest-npm-20.0.2-4561cebc71-5c56ac23f0.zip b/.yarn/cache/@octokit-rest-npm-20.0.2-4561cebc71-5c56ac23f0.zip new file mode 100644 index 000000000..99f898368 Binary files /dev/null and b/.yarn/cache/@octokit-rest-npm-20.0.2-4561cebc71-5c56ac23f0.zip differ diff --git a/.yarn/cache/@octokit-types-npm-12.6.0-3f6eea3eb3-850235f425.zip b/.yarn/cache/@octokit-types-npm-12.6.0-3f6eea3eb3-850235f425.zip new file mode 100644 index 000000000..d11e7ae31 Binary files /dev/null and b/.yarn/cache/@octokit-types-npm-12.6.0-3f6eea3eb3-850235f425.zip differ diff --git a/.yarn/cache/before-after-hook-npm-2.2.3-d79e3d6608-a1a2430976.zip b/.yarn/cache/before-after-hook-npm-2.2.3-d79e3d6608-a1a2430976.zip new file mode 100644 index 000000000..b03fd8f3e Binary files /dev/null and b/.yarn/cache/before-after-hook-npm-2.2.3-d79e3d6608-a1a2430976.zip differ diff --git a/.yarn/cache/deprecation-npm-2.3.1-e19c92d6e7-f56a05e182.zip b/.yarn/cache/deprecation-npm-2.3.1-e19c92d6e7-f56a05e182.zip new file mode 100644 index 000000000..943bc441b Binary files /dev/null and b/.yarn/cache/deprecation-npm-2.3.1-e19c92d6e7-f56a05e182.zip differ diff --git a/.yarn/cache/universal-user-agent-npm-6.0.1-0388aac597-fdc8e1ae48.zip b/.yarn/cache/universal-user-agent-npm-6.0.1-0388aac597-fdc8e1ae48.zip new file mode 100644 index 000000000..363fb2854 Binary files /dev/null and b/.yarn/cache/universal-user-agent-npm-6.0.1-0388aac597-fdc8e1ae48.zip differ diff --git a/package.json b/package.json index 523e2da70..95b0b0d88 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/scripts/github-actions/validate-build-status.js b/scripts/github-actions/validate-build-status.js new file mode 100644 index 000000000..5aff59e84 --- /dev/null +++ b/scripts/github-actions/validate-build-status.js @@ -0,0 +1,138 @@ +/* eslint-disable no-console */ +/* eslint-disable camelcase */ +const { Octokit } = require('@octokit/rest') + +const { GITHUB_TOKEN: auth, GITHUB_REPOSITORY } = process.env +const args = process.argv.slice(2) +const timeout = 2 // minutes +const commitSHA = args[0] +const [owner, repo] = GITHUB_REPOSITORY.split('/') + +const octokit = new Octokit({ auth }) + +const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)) + +/** + * uses octokit request for github action run_id provided + * @param {number} run_id + */ +function getJobsFailed(run_id) { + const params = { + owner, + repo, + run_id, + } + return octokit.rest.actions + .listJobsForWorkflowRun(params) + .then((response) => { + if (response.status !== 200) { + throw new Error( + `Response ${response.status} from ${response.url}. Aborting.` + ) + } + return response.data + }) + .then(({ jobs }) => { + jobs.forEach(({ name, html_url, conclusion }) => { + if (conclusion === 'success') return + const isFailure = conclusion === 'failure' + const annotationMessage = isFailure + ? `::error::Job "${name}" has failed` + : `::warning::Job "${name}" has been cancelled` + console.log( + `${annotationMessage}. For more details, please see ${html_url}` + ) + }) + }) +} + +/** + * uses octokit request for github action to get workflow with matching SHA + * @param {number} page + */ +function getLatestWorkflow(page) { + const params = { + owner, + repo, + workflow_id: 'ci.yml', + branch: 'main', + per_page: '50', + page, + } + return octokit.rest.actions + .listWorkflowRuns(params) + .then((response) => { + if (response.status !== 200) { + throw new Error( + `Response ${response.status} from ${response.url}. Aborting.` + ) + } + return response.data + }) + .then(({ workflow_runs }) => { + if (workflow_runs.length === 0) { + throw new Error('No workflows found. Aborting.') + } + + const workflow = workflow_runs.find( + ({ head_sha }) => head_sha === commitSHA + ) + if (workflow) return workflow + console.log('Workflow not found in current page. Checking next page.') + return getLatestWorkflow(page + 1) + }) +} + +/** + * Validates the workflow + * @param {Object} workflow + * @returns true, false, undefined + */ +function validateWorkflowSuccess(workflow) { + const { status, conclusion, head_commit, html_url } = workflow + console.log(`Validating commit ${head_commit.id}. Workflow: ${html_url}`) + + if (conclusion === 'failure') return false + + const isWorkflowInProgress = + status === 'in_progress' || status === null || status === 'queued' + + if (isWorkflowInProgress) return undefined + + if (conclusion === 'success') { + console.log('All checks succeeded') + return true + } + + throw new Error( + `Unexpected workflow result: ${JSON.stringify({ status, conclusion })}` + ) +} + +/** + * Checks Github Actions url. Loops recursively until error is thrown. + */ +async function main() { + try { + const page = 1 + const workflow = await getLatestWorkflow(page) + const success = validateWorkflowSuccess(workflow) + + if (success === undefined) { + console.log(`Check runs still pending. Sleeping for ${timeout} minutes`) + await sleep(timeout * 60 * 1000) + await main() + return + } + + if (!success) { + await getJobsFailed(workflow.id) + process.exit(1) + } + } catch (e) { + console.error(e) + process.exit(1) + } +} + +main() diff --git a/yarn.lock b/yarn.lock index 53cedcb80..634a73457 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22,6 +22,18 @@ __metadata: languageName: node linkType: hard +"@actions/github@npm:^6.0.0": + version: 6.0.0 + resolution: "@actions/github@npm:6.0.0" + dependencies: + "@actions/http-client": ^2.2.0 + "@octokit/core": ^5.0.1 + "@octokit/plugin-paginate-rest": ^9.0.0 + "@octokit/plugin-rest-endpoint-methods": ^10.0.0 + checksum: 81831a78377175d8825fc0b94247ff366c0e87ad1dfa48df9b30b8659506f216dcf1e2d3124fcd318839b92c24ba20165e238b3cc11a34db89c69c40825e9ccf + languageName: node + linkType: hard + "@actions/http-client@npm:^2.0.1": version: 2.2.0 resolution: "@actions/http-client@npm:2.2.0" @@ -32,6 +44,16 @@ __metadata: languageName: node linkType: hard +"@actions/http-client@npm:^2.2.0": + version: 2.2.1 + resolution: "@actions/http-client@npm:2.2.1" + dependencies: + tunnel: ^0.0.6 + undici: ^5.25.4 + checksum: c51c003cd697289136c0e81c0f9b8e57a9bb1a038dc7c9a91a71c02f4ae5e27ef7d3e305aefa7c815604049209d114c06e9991a5c5eaa055508519329267f962 + languageName: node + linkType: hard + "@adobe/css-tools@npm:^4.3.2": version: 4.3.2 resolution: "@adobe/css-tools@npm:4.3.2" @@ -3232,6 +3254,131 @@ __metadata: languageName: node linkType: hard +"@octokit/auth-token@npm:^4.0.0": + version: 4.0.0 + resolution: "@octokit/auth-token@npm:4.0.0" + checksum: d78f4dc48b214d374aeb39caec4fdbf5c1e4fd8b9fcb18f630b1fe2cbd5a880fca05445f32b4561f41262cb551746aeb0b49e89c95c6dd99299706684d0cae2f + languageName: node + linkType: hard + +"@octokit/core@npm:^5.0.0, @octokit/core@npm:^5.0.1": + version: 5.1.0 + resolution: "@octokit/core@npm:5.1.0" + dependencies: + "@octokit/auth-token": ^4.0.0 + "@octokit/graphql": ^7.0.0 + "@octokit/request": ^8.0.2 + "@octokit/request-error": ^5.0.0 + "@octokit/types": ^12.0.0 + before-after-hook: ^2.2.0 + universal-user-agent: ^6.0.0 + checksum: 170d16f5577df484116238ce04e2dbd6b45d8e96b4680fee657ae22fcafb311af8df8a14ae80610f41c1a85493c927910698019a761914ff4b0323ddbabcc9a4 + languageName: node + linkType: hard + +"@octokit/endpoint@npm:^9.0.0": + version: 9.0.4 + resolution: "@octokit/endpoint@npm:9.0.4" + dependencies: + "@octokit/types": ^12.0.0 + universal-user-agent: ^6.0.0 + checksum: ed1b64a448f478e5951a043ef816d634a5a1f584519cbf2f374ceac058f82a16e52f078f156aa8b8cbcab7b0590348d94294fc83c9b4eebd42a820a5f10db81c + languageName: node + linkType: hard + +"@octokit/graphql@npm:^7.0.0": + version: 7.0.2 + resolution: "@octokit/graphql@npm:7.0.2" + dependencies: + "@octokit/request": ^8.0.1 + "@octokit/types": ^12.0.0 + universal-user-agent: ^6.0.0 + checksum: 05a752c4c2d84fc2900d8e32e1c2d1ee98a5a14349e651cb1109d0741e821e7417a048b1bb40918534ed90a472314aabbda35688868016f248098925f82a3bfa + languageName: node + linkType: hard + +"@octokit/openapi-types@npm:^20.0.0": + version: 20.0.0 + resolution: "@octokit/openapi-types@npm:20.0.0" + checksum: 23ff7613750f8b5790a0cbed5a2048728a7909e50d726932831044908357a932c7fc0613fb7b86430a49d31b3d03a180632ea5dd936535bfbc1176391a199e96 + languageName: node + linkType: hard + +"@octokit/plugin-paginate-rest@npm:^9.0.0": + version: 9.2.1 + resolution: "@octokit/plugin-paginate-rest@npm:9.2.1" + dependencies: + "@octokit/types": ^12.6.0 + peerDependencies: + "@octokit/core": 5 + checksum: 554ad17a7dcfd7028e321ffcae233f8ae7975569084f19d9b6217b47fb182e2604145108de7a9029777e6dc976b27b2dd7387e2e47a77532a72e6c195880576d + languageName: node + linkType: hard + +"@octokit/plugin-request-log@npm:^4.0.0": + version: 4.0.1 + resolution: "@octokit/plugin-request-log@npm:4.0.1" + peerDependencies: + "@octokit/core": 5 + checksum: fd8c0a201490cba00084689a0d1d54fc7b5ab5b6bdb7e447056b947b1754f78526e9685400eab10d3522bfa7b5bc49c555f41ec412c788610b96500b168f3789 + languageName: node + linkType: hard + +"@octokit/plugin-rest-endpoint-methods@npm:^10.0.0": + version: 10.4.1 + resolution: "@octokit/plugin-rest-endpoint-methods@npm:10.4.1" + dependencies: + "@octokit/types": ^12.6.0 + peerDependencies: + "@octokit/core": 5 + checksum: 3e0e95515ccb7fdd5e5cff32a5e34a688fd275c6703caf786f7c49820e2bf2a66e7d845ba4eae4d03c307c1950ea417e34a17055b25b46e2019123b75b394c56 + languageName: node + linkType: hard + +"@octokit/request-error@npm:^5.0.0": + version: 5.0.1 + resolution: "@octokit/request-error@npm:5.0.1" + dependencies: + "@octokit/types": ^12.0.0 + deprecation: ^2.0.0 + once: ^1.4.0 + checksum: a681341e43b4da7a8acb19e1a6ba0355b1af146fa0191f2554a98950cf85f898af6ae3ab0b0287d6c871f5465ec57cb38363b96b5019f9f77ba6f30eca39ede5 + languageName: node + linkType: hard + +"@octokit/request@npm:^8.0.1, @octokit/request@npm:^8.0.2": + version: 8.2.0 + resolution: "@octokit/request@npm:8.2.0" + dependencies: + "@octokit/endpoint": ^9.0.0 + "@octokit/request-error": ^5.0.0 + "@octokit/types": ^12.0.0 + universal-user-agent: ^6.0.0 + checksum: 24dd2c96769aa52df19fdbf4058dfd06dc3a799121250c10ec5fbea4c43ec0183639a2beccc84053df2c298c18892ed8fbf722f1ca5271003feaac5290272beb + languageName: node + linkType: hard + +"@octokit/rest@npm:^20.0.2": + version: 20.0.2 + resolution: "@octokit/rest@npm:20.0.2" + dependencies: + "@octokit/core": ^5.0.0 + "@octokit/plugin-paginate-rest": ^9.0.0 + "@octokit/plugin-request-log": ^4.0.0 + "@octokit/plugin-rest-endpoint-methods": ^10.0.0 + checksum: 5c56ac23f063a5375ae5a0609e6477d90afac872eccd07002870f9dd62755037282a74c15c90c848b76b64ea4b5af52f32720b8a1b7b133e758118d11d2c0e34 + languageName: node + linkType: hard + +"@octokit/types@npm:^12.0.0, @octokit/types@npm:^12.6.0": + version: 12.6.0 + resolution: "@octokit/types@npm:12.6.0" + dependencies: + "@octokit/openapi-types": ^20.0.0 + checksum: 850235f425584499a2266d5c585c1c2462ae11e25c650567142f3342cb9ce589c8c8fed87705811ca93271fd28c68e1fa77b88b67b97015d7b63d269fa46ed05 + languageName: node + linkType: hard + "@open-draft/deferred-promise@npm:^2.2.0": version: 2.2.0 resolution: "@open-draft/deferred-promise@npm:2.2.0" @@ -7605,6 +7752,13 @@ __metadata: languageName: node linkType: hard +"before-after-hook@npm:^2.2.0": + version: 2.2.3 + resolution: "before-after-hook@npm:2.2.3" + checksum: a1a2430976d9bdab4cd89cb50d27fa86b19e2b41812bf1315923b0cba03371ebca99449809226425dd3bcef20e010db61abdaff549278e111d6480034bebae87 + languageName: node + linkType: hard + "better-opn@npm:^3.0.2": version: 3.0.2 resolution: "better-opn@npm:3.0.2" @@ -9194,6 +9348,13 @@ __metadata: languageName: node linkType: hard +"deprecation@npm:^2.0.0": + version: 2.3.1 + resolution: "deprecation@npm:2.3.1" + checksum: f56a05e182c2c195071385455956b0c4106fe14e36245b00c689ceef8e8ab639235176a96977ba7c74afb173317fac2e0ec6ec7a1c6d1e6eaa401c586c714132 + languageName: node + linkType: hard + "dequal@npm:^2.0.2, dequal@npm:^2.0.3": version: 2.0.3 resolution: "dequal@npm:2.0.3" @@ -14729,6 +14890,7 @@ __metadata: resolution: "next-build@workspace:." dependencies: "@actions/core": ^1.10.1 + "@actions/github": ^6.0.0 "@axe-core/playwright": ^4.8.2 "@department-of-veterans-affairs/component-library": ^33.0.0 "@department-of-veterans-affairs/formation": ^10.1.0 @@ -14736,6 +14898,7 @@ __metadata: "@faker-js/faker": ^8.4.1 "@fortawesome/fontawesome-free": ^6.5.1 "@next/env": ^14.1.0 + "@octokit/rest": ^20.0.2 "@playwright/test": ^1.40.1 "@storybook/addon-a11y": ^7.6.13 "@storybook/addon-actions": ^7.6.14 @@ -19371,6 +19534,13 @@ __metadata: languageName: node linkType: hard +"universal-user-agent@npm:^6.0.0": + version: 6.0.1 + resolution: "universal-user-agent@npm:6.0.1" + checksum: fdc8e1ae48a05decfc7ded09b62071f571c7fe0bd793d700704c80cea316101d4eac15cc27ed2bb64f4ce166d2684777c3198b9ab16034f547abea0d3aa1c93c + languageName: node + linkType: hard + "universalify@npm:^0.2.0": version: 0.2.0 resolution: "universalify@npm:0.2.0"