Merge pull request #19 from osarukun/dependabot/npm_and_yarn/json5-1.0.2 #2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Azure 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 | |
# This allows a subsequently queued workflow run to take priority over | |
# previously queued runs but NOT interrupt currently executing runs | |
concurrency: | |
group: '${{ github.workflow }}' | |
cancel-in-progress: false | |
jobs: | |
azure-prod-build-and-deploy: | |
if: ${{ github.repository == 'github/docs-internal' }} | |
runs-on: ubuntu-latest | |
timeout-minutes: 20 | |
environment: | |
name: production | |
url: 'https://docs.github.com' | |
env: | |
DOCKER_IMAGE: ${{ secrets.PROD_REGISTRY_SERVER }}/${{ github.repository }}:${{ github.sha }} | |
DOCKER_IMAGE_CACHE_REF: ${{ secrets.PROD_REGISTRY_SERVER }}/${{ github.repository }}:main-production | |
steps: | |
- name: 'Az CLI login' | |
uses: azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf | |
with: | |
creds: ${{ secrets.PROD_AZURE_CREDENTIALS }} | |
- name: 'Docker login' | |
uses: azure/docker-login@81744f9799e7eaa418697cb168452a2882ae844a | |
with: | |
login-server: ${{ secrets.PROD_REGISTRY_SERVER }} | |
username: ${{ secrets.PROD_REGISTRY_USERNAME }} | |
password: ${{ secrets.PROD_REGISTRY_PASSWORD }} | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@94ab11c41e45d028884a99163086648e898eed25 | |
- name: Check out repo | |
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 | |
with: | |
ref: ${{ github.sha }} | |
# To prevent issues with cloning early access content later | |
persist-credentials: 'false' | |
lfs: 'true' | |
- name: Check out LFS objects | |
run: git lfs checkout | |
- name: Setup node | |
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561 | |
with: | |
node-version: 16.14.x | |
cache: npm | |
- name: Clone docs-early-access | |
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 | |
with: | |
repository: github/docs-early-access | |
token: ${{ secrets.DOCUBOT_REPO_PAT }} | |
path: docs-early-access | |
ref: main | |
- name: Merge docs-early-access repo's folders | |
run: .github/actions-scripts/merge-early-access.sh | |
- name: 'Build and push image' | |
uses: docker/build-push-action@7f9d37fa544684fb73bfe4835ed7214c255ce02b | |
with: | |
context: . | |
push: true | |
target: production | |
tags: ${{ env.DOCKER_IMAGE }}, ${{ env.DOCKER_IMAGE_CACHE_REF }} | |
cache-from: type=registry,ref=${{ env.DOCKER_IMAGE_CACHE_REF }} | |
cache-to: type=registry,mode=max,ref=${{ env.DOCKER_IMAGE_CACHE_REF }} | |
- name: 'Update docker-compose.prod.yaml template file' | |
run: | | |
sed 's|#{IMAGE}#|${{ env.DOCKER_IMAGE }}|g' docker-compose.prod.tmpl.yaml > docker-compose.prod.yaml | |
- name: 'Apply updated docker-compose.prod.yaml config to staging slot' | |
run: | | |
az webapp config container set --multicontainer-config-type COMPOSE --multicontainer-config-file docker-compose.prod.yaml --slot staging -n ghdocs-prod -g docs-prod | |
# Watch staging slot instances to see when all the instances are ready | |
- name: Check that staging slot is ready | |
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d | |
env: | |
CHECK_INTERVAL: 10000 | |
with: | |
script: | | |
const { execSync } = require('child_process') | |
const getStatesForSlot = (slot) => { | |
return JSON.parse( | |
execSync( | |
`az webapp list-instances --slot ${slot} --query "[].state" -n ghdocs-prod -g docs-prod`, | |
{ encoding: 'utf8' } | |
) | |
) | |
} | |
let hasStopped = false | |
const waitDuration = parseInt(process.env.CHECK_INTERVAL, 10) || 10000 | |
async function doCheck() { | |
const states = getStatesForSlot('staging') | |
console.log(`Instance states:`, states) | |
// We must wait until at-least 1 instance has STOPPED to know we're looking at the "next" deployment and not the "previous" one | |
// That way we don't immediately succeed just because all the previous instances were READY | |
if (!hasStopped) { | |
hasStopped = states.some((s) => s === 'STOPPED') | |
} | |
const isAllReady = states.every((s) => s === 'READY') | |
if (hasStopped && isAllReady) { | |
process.exit(0) // success | |
} | |
console.log(`checking again in ${waitDuration}ms`) | |
setTimeout(doCheck, waitDuration) | |
} | |
doCheck() | |
# TODO - make a request to verify the staging app version aligns with *this* github action workflow commit sha | |
- name: 'Swap staging slot to production' | |
run: | | |
az webapp deployment slot swap --slot staging --target-slot production -n ghdocs-prod -g docs-prod | |
- name: Purge Fastly edge cache | |
env: | |
FASTLY_TOKEN: ${{ secrets.FASTLY_TOKEN }} | |
FASTLY_SERVICE_ID: ${{ secrets.FASTLY_SERVICE_ID }} | |
FASTLY_SURROGATE_KEY: 'every-deployment' | |
run: npm install got && .github/actions-scripts/purge-fastly-edge-cache.js | |
- 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 (Azure) failed at commit ${{ github.sha }}. See https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} |