diff --git a/.github/workflows/prod-build-deploy-azure.yml b/.github/workflows/prod-build-deploy-azure.yml index e638f8189e..a7fa1e28b6 100644 --- a/.github/workflows/prod-build-deploy-azure.yml +++ b/.github/workflows/prod-build-deploy-azure.yml @@ -26,9 +26,14 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 15 env: - IMAGE_TAG_BASE: ${{ secrets.PROD_REGISTRY_SERVER }}/${{ github.repository }} + DOCKER_IMAGE: ${{ secrets.PROD_REGISTRY_SERVER }}/${{ github.repository }}:${{ github.sha }} steps: + - name: 'Az CLI login' + uses: azure/login@66d2e78565ab7af265d2b627085bc34c73ce6abb + with: + creds: ${{ secrets.PROD_AZURE_CREDENTIALS }} + - name: 'Docker login' uses: azure/docker-login@81744f9799e7eaa418697cb168452a2882ae844a with: @@ -68,10 +73,65 @@ jobs: context: . push: true target: 'production_early_access' - tags: ${{ env.IMAGE_TAG_BASE }}:${{ github.sha }}, ${{ env.IMAGE_TAG_BASE }}:production + tags: ${{ env.DOCKER_IMAGE }} cache-from: type=gha cache-to: type=gha,mode=max + - name: 'Update docker-compose.prod.yaml template file' + run: | + sed 's|#{IMAGE}#|${DOCKER_IMAGE}|g' docker-compose.prod.tmpl.yaml > docker-compose.prod.yaml + + - name: 'Apply updated docker-compose.prod.yaml config to preview slot' + run: | + az webapp config container set --multicontainer-config-type COMPOSE --multicontainer-config-file docker-compose.prod.yaml --slot preview -n ghdocs-prod -g docs-prod + + # Watch preview slot instances to see when all the instances are ready + - name: Check that preview slot is ready + uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d + env: + CHECK_INTERVAL: 10000 + with: + script: | + import { execSync } from '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('preview') + 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 preview app version aligns with *this* github action workflow commit sha + - name: 'Swap preview slot to production' + run: | + az webapp deployment slot swap --slot preview --target-slot production -n ghdocs-prod -g docs-prod + # TODO - enable this when we disable the other production deploy # - name: Purge Fastly edge cache # env: diff --git a/docker-compose.prod.tmpl.yaml b/docker-compose.prod.tmpl.yaml new file mode 100644 index 0000000000..dc43db072d --- /dev/null +++ b/docker-compose.prod.tmpl.yaml @@ -0,0 +1,48 @@ +version: '3.7' + +services: + ghdocs-prod: + image: '#{IMAGE}#' + ports: + - '4000:4000' + environment: + NODE_ENV: ${NODE_ENV} + DD_API_KEY: ${DD_API_KEY} + COOKIE_SECRET: ${COOKIE_SECRET} + HYDRO_ENDPOINT: ${HYDRO_ENDPOINT} + HYDRO_SECRET: ${HYDRO_SECRET} + HAYSTACK_URL: ${HAYSTACK_URL} + WEB_CONCURRENCY: ${WEB_CONCURRENCY} + HEROKU_APP_NAME: ${HEROKU_APP_NAME} + ENABLED_LANGUAGES: ${ENABLED_LANGUAGES} + DEPLOYMENT_ENV: ${DEPLOYMENT_ENV} + HEROKU_PRODUCTION_APP: true + PORT: 4000 + DD_AGENT_HOST: datadog-agent + labels: + com.datadoghq.ad.logs: '[{"source": "node", "service": "docs"}]' + depends_on: + - datadog-agent + restart: always + + datadog-agent: + image: datadog/agent:7.32.3 + ports: + - '8125:8125' + environment: + DD_API_KEY: ${DD_API_KEY} + DD_LOGS_ENABLED: true + DD_PROCESS_AGENT_ENABLED: true + DD_RUNTIME_METRICS_ENABLED: true + DD_DOGSTATSD_NON_LOCAL_TRAFFIC: true + DD_AGENT_HOST: datadog-agent + DD_HEALTH_PORT: 5555 + DD_LOGS_CONFIG_CONTAINER_COLLECT_ALL: true + DD_LOGS_CONFIG_DOCKER_CONTAINER_USE_FILE: true + DD_CONTAINER_EXCLUDE: 'name:datadog-agent' + DD_DOGSTATSD_TAGS: 'service:ghdocs env:production' + volumes: + - /home/LogFiles:/var/lib/docker/containers:ro + - ${WEBAPP_STORAGE_HOME}/opt/datadog-agent/run:/opt/datadog-agent/run:rw + - /proc/:/host/proc/:ro + - /sys/fs/cgroup/:/host/sys/fs/cgroup:ro