* Bump actions/checkout from 2.3.4 to 2.3.5
Bumps [actions/checkout](https://github.com/actions/checkout) from 2.3.4 to 2.3.5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](5a4ac9002d...1e204e9a92)
---
updated-dependencies:
- dependency-name: actions/checkout
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
* test
* removing test, works
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Grace Park <gracepark@github.com>
259 lines
9.0 KiB
YAML
259 lines
9.0 KiB
YAML
name: Production - Build and Deploy
|
|
|
|
# **What it does**: Builds and deploys the default branch to production
|
|
# **Why we have it**: To enable us to deploy the latest to production whenever necessary rather than relying on PR merges.
|
|
# **Who does it impact**: All contributors.
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
deployments: write
|
|
|
|
concurrency:
|
|
group: '${{ github.workflow }}'
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
build-and-deploy:
|
|
if: ${{ github.repository == 'github/docs-internal'}}
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 15
|
|
steps:
|
|
- name: Check out repo
|
|
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
|
|
with:
|
|
persist-credentials: 'false'
|
|
lfs: 'true'
|
|
|
|
- name: Check out LFS objects
|
|
run: git lfs checkout
|
|
|
|
- name: Setup node
|
|
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
|
|
with:
|
|
node-version: 16.8.x
|
|
cache: npm
|
|
|
|
# Required for `npm pkg ...` command support
|
|
- name: Update to npm@^7.20.0
|
|
run: npm install --global npm@^7.20.0
|
|
|
|
- name: Install dependencies
|
|
run: npm ci
|
|
|
|
- name: Clone early access
|
|
run: node script/early-access/clone-for-build.js
|
|
env:
|
|
DOCUBOT_REPO_PAT: ${{ secrets.DOCUBOT_REPO_PAT }}
|
|
GIT_BRANCH: main
|
|
|
|
- name: Build
|
|
run: npm run build
|
|
|
|
- name: Remove development-only dependencies
|
|
run: npm prune --production
|
|
|
|
- name: Remove all npm scripts
|
|
run: npm pkg delete scripts
|
|
|
|
- name: Set npm script for Heroku build to noop
|
|
run: npm set-script heroku-postbuild "echo 'Application was pre-built!'"
|
|
|
|
- name: Create a gzipped archive
|
|
run: |
|
|
tar -cz --file=app.tar.gz \
|
|
node_modules/ \
|
|
.next/ \
|
|
assets/ \
|
|
content/ \
|
|
data/ \
|
|
includes/ \
|
|
lib/ \
|
|
middleware/ \
|
|
translations/ \
|
|
server.mjs \
|
|
package*.json \
|
|
.npmrc \
|
|
feature-flags.json \
|
|
next.config.js \
|
|
app.json \
|
|
Procfile
|
|
|
|
- name: Install the development dependencies again
|
|
run: npm install
|
|
|
|
- name: Create a Heroku build source
|
|
id: build-source
|
|
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d
|
|
env:
|
|
HEROKU_API_TOKEN: ${{ secrets.HEROKU_API_TOKEN }}
|
|
with:
|
|
script: |
|
|
const { owner, repo } = context.repo
|
|
|
|
if (owner !== 'github') {
|
|
throw new Error(`Repository owner must be 'github' but was: ${owner}`)
|
|
}
|
|
if (repo !== 'docs-internal') {
|
|
throw new Error(`Repository name must be 'docs-internal' but was: ${repo}`)
|
|
}
|
|
|
|
const Heroku = require('heroku-client')
|
|
const heroku = new Heroku({ token: process.env.HEROKU_API_TOKEN })
|
|
|
|
try {
|
|
const { source_blob: sourceBlob } = await heroku.post('/sources')
|
|
const { put_url: uploadUrl, get_url: downloadUrl } = sourceBlob
|
|
|
|
core.setOutput('upload_url', uploadUrl)
|
|
core.setOutput('download_url', downloadUrl)
|
|
} catch (error) {
|
|
if (error.statusCode === 503) {
|
|
console.error('💀 Heroku may be down! Please check its Status page: https://status.heroku.com/')
|
|
}
|
|
throw error
|
|
}
|
|
|
|
# See: https://devcenter.heroku.com/articles/build-and-release-using-the-api#sources-endpoint
|
|
- name: Upload to the Heroku build source
|
|
env:
|
|
UPLOAD_URL: ${{ steps.build-source.outputs.upload_url }}
|
|
run: |
|
|
curl "$UPLOAD_URL" \
|
|
-X PUT \
|
|
-H 'Content-Type:' \
|
|
--data-binary @app.tar.gz
|
|
|
|
- name: Install one-off development-only dependencies
|
|
run: npm install --no-save --include=optional esm
|
|
|
|
- name: Deploy
|
|
id: deploy
|
|
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
HEROKU_API_TOKEN: ${{ secrets.HEROKU_API_TOKEN }}
|
|
HEROKU_PRODUCTION_APP_NAME: ${{ secrets.HEROKU_PRODUCTION_APP_NAME }}
|
|
HYDRO_ENDPOINT: ${{ secrets.HYDRO_ENDPOINT }}
|
|
HYDRO_SECRET: ${{ secrets.HYDRO_SECRET }}
|
|
SOURCE_BLOB_URL: ${{ steps.build-source.outputs.download_url }}
|
|
DELAY_FOR_PREBOOT: 'true'
|
|
ALLOWED_POLLING_FAILURES_PER_PHASE: '15'
|
|
with:
|
|
script: |
|
|
const {
|
|
GITHUB_TOKEN,
|
|
HEROKU_API_TOKEN,
|
|
HEROKU_PRODUCTION_APP_NAME,
|
|
SOURCE_BLOB_URL,
|
|
DELAY_FOR_PREBOOT
|
|
} = process.env
|
|
|
|
// Exit if GitHub Actions PAT is not found
|
|
if (!GITHUB_TOKEN) {
|
|
throw new Error('You must supply a GITHUB_TOKEN environment variable!')
|
|
}
|
|
|
|
// Exit if Heroku API token is not found
|
|
if (!HEROKU_API_TOKEN) {
|
|
throw new Error('You must supply a HEROKU_API_TOKEN environment variable!')
|
|
}
|
|
|
|
// Exit if Heroku App name is not found
|
|
if (!HEROKU_PRODUCTION_APP_NAME) {
|
|
throw new Error('You must supply a HEROKU_PRODUCTION_APP_NAME environment variable!')
|
|
}
|
|
|
|
// Workaround to allow us to load ESM files with `require(...)`
|
|
const esm = require('esm')
|
|
require = esm({})
|
|
|
|
const { default: getOctokit } = require('./script/helpers/github')
|
|
const { default: deployToProduction } = require('./script/deployment/deploy-to-production')
|
|
|
|
// This helper uses the `GITHUB_TOKEN` implicitly!
|
|
// We're using our usual version of Octokit vs. the provided `github`
|
|
// instance to avoid versioning discrepancies.
|
|
const octokit = getOctokit()
|
|
|
|
try {
|
|
await deployToProduction({
|
|
octokit,
|
|
includeDelayForPreboot: DELAY_FOR_PREBOOT !== 'false',
|
|
// These parameters will ONLY be set by Actions
|
|
sourceBlobUrl: SOURCE_BLOB_URL,
|
|
runId: context.runId
|
|
})
|
|
} catch (error) {
|
|
console.error(`Failed to deploy to production: ${error.message}`)
|
|
console.error(error)
|
|
throw error
|
|
}
|
|
|
|
- name: Mark the deployment as inactive if timed out
|
|
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d
|
|
if: ${{ steps.deploy.outcome == 'cancelled' }}
|
|
env:
|
|
DEPLOYMENT_ID: ${{ steps.deploy.outputs.deploymentId }}
|
|
LOG_URL: ${{ steps.deploy.outputs.logUrl }}
|
|
with:
|
|
script: |
|
|
const { DEPLOYMENT_ID, LOG_URL } = process.env
|
|
const { owner, repo } = context.repo
|
|
|
|
if (!DEPLOYMENT_ID) {
|
|
throw new Error('A deployment wasn't created before a timeout occurred!')
|
|
}
|
|
|
|
await github.repos.createDeploymentStatus({
|
|
owner,
|
|
repo,
|
|
deployment_id: DEPLOYMENT_ID,
|
|
state: 'error',
|
|
description: 'The deployment step timed out. See workflow logs.',
|
|
log_url: LOG_URL,
|
|
// The 'ant-man' preview is required for `state` values of 'inactive', as well as
|
|
// the use of the `log_url`, `environment_url`, and `auto_inactive` parameters.
|
|
// The 'flash' preview is required for `state` values of 'in_progress' and 'queued'.
|
|
mediaType: {
|
|
previews: ['ant-man', 'flash'],
|
|
},
|
|
})
|
|
console.log('⏲️ Deployment status: error - The deployment timed out...')
|
|
|
|
- name: Purge Fastly edge cache
|
|
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d
|
|
env:
|
|
FASTLY_TOKEN: ${{ secrets.FASTLY_TOKEN }}
|
|
FASTLY_SERVICE_ID: ${{ secrets.FASTLY_SERVICE_ID }}
|
|
FASTLY_SURROGATE_KEY: 'all-the-things'
|
|
with:
|
|
script: |
|
|
// Workaround to allow us to load ESM files with `require(...)`
|
|
const esm = require('esm')
|
|
require = esm({})
|
|
|
|
const { default: purgeEdgeCache } = require('./script/deployment/purge-edge-cache')
|
|
|
|
try {
|
|
await purgeEdgeCache()
|
|
} catch (error) {
|
|
console.error(`Failed to purge the edge cache: ${error.message}`)
|
|
console.error(error)
|
|
throw error
|
|
}
|
|
|
|
- name: Send Slack notification if workflow failed
|
|
uses: someimportantcompany/github-actions-slack-message@f8d28715e7b8a4717047d23f48c39827cacad340
|
|
if: ${{ failure() }}
|
|
with:
|
|
channel: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }}
|
|
bot-token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}
|
|
color: failure
|
|
text: Production deployment failed at commit ${{ github.sha }}. See https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
|