Skip to content
Merged
Changes from all 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
30 changes: 26 additions & 4 deletions .github/workflows/deploy-backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ on:
type: boolean
required: false
default: false
rollback:
description: "Roll dev back to the image that was live before the last deploy (no build, no tests). Ignored on main."
type: boolean
required: false
default: false

# Queue overlapping deploys to the SAME environment rather than cancelling (a
# cancelled run mid-deploy could leave .deploy/ state and the running
Expand All @@ -82,6 +87,7 @@ env:
jobs:
build:
name: Build and push image
if: ${{ !inputs.rollback }}
runs-on: ubuntu-latest
timeout-minutes: 45
permissions:
Expand Down Expand Up @@ -250,6 +256,9 @@ jobs:
smoke-tests:
name: Smoke Tests
needs: deploy
# Repo variable SKIP_DEV_TESTS=true skips the dev test gates (e.g. while the
# test owner is away). main ignores it: prod deploys are always gated.
if: github.ref_name == 'main' || vars.SKIP_DEV_TESTS != 'true'
# No `environment:` here -- GitHub rejects the entire workflow file at
# parse time if a `uses:` job declares one. Consequence: this job also
# cannot see environment-scoped vars, which is why api_base_url comes
Expand Down Expand Up @@ -300,15 +309,27 @@ jobs:
TEST_PASSWORD_2: ${{ secrets.TEST_PASSWORD_2 }}
KEYCLOAK_CLIENT_SECRET: ${{ secrets.KEYCLOAK_CLIENT_SECRET }}

tests-skipped:
name: Tests skipped (SKIP_DEV_TESTS)
needs: deploy
if: github.ref_name != 'main' && vars.SKIP_DEV_TESTS == 'true'
runs-on: ubuntu-latest
steps:
- run: |
echo "::notice::SKIP_DEV_TESTS=true: smoke and functional tests were skipped for this dev deploy."
echo "**SKIP_DEV_TESTS=true**: smoke and functional tests were skipped. Delete the repo variable to turn them back on." >> "$GITHUB_STEP_SUMMARY"

rollback-on-smoke-failure:
name: Rollback (smoke tests failed)
# `deploy` must be in needs: for needs.deploy.result to resolve here.
needs: [deploy, smoke-tests, functional-tests]
# Explicit results rather than failure(), so that a skipped functional stage
# on main never reads as a failure. !cancelled() keeps cancellation a no-op.
# Also the manual rollback button: Run workflow on dev with `rollback` ticked.
if: >-
${{ !cancelled() && needs.deploy.result == 'success' &&
(needs.smoke-tests.result == 'failure' || needs.functional-tests.result == 'failure') }}
${{ !cancelled() && ((inputs.rollback && github.ref_name != 'main') ||
(needs.deploy.result == 'success' &&
(needs.smoke-tests.result == 'failure' || needs.functional-tests.result == 'failure'))) }}
runs-on: ubuntu-latest
environment: ${{ github.ref_name == 'main' && 'production' || 'development' }}
# 50m: must comfortably exceed the Restore previous image step's own
Expand Down Expand Up @@ -347,6 +368,7 @@ jobs:
script: cd "$HOME/${{ env.DEPLOY_PATH }}" && sudo bash scripts/ci-rollback.sh "${{ vars.HEALTH_CHECK_URL || 'http://127.0.0.1:8000/health/' }}" "${{ github.actor }}"

- name: Mark this run as failed
if: ${{ !inputs.rollback }}
# The mitigation succeeded, but the run must still read RED -- a bad
# deploy that silently self-heals is a bad deploy nobody investigates.
run: |
Expand All @@ -357,10 +379,10 @@ jobs:
name: Finalize Deploy
needs: [deploy, smoke-tests, functional-tests]
# Explicit results, not success()/!failure(): on main the functional stage
# is skipped by design.
# is skipped by design, and on dev SKIP_DEV_TESTS skips smoke too.
if: >-
${{ !cancelled() && needs.deploy.result == 'success' &&
needs.smoke-tests.result == 'success' &&
(needs.smoke-tests.result == 'success' || needs.smoke-tests.result == 'skipped') &&
(needs.functional-tests.result == 'success' || needs.functional-tests.result == 'skipped') }}
runs-on: ubuntu-latest
environment: ${{ github.ref_name == 'main' && 'production' || 'development' }}
Expand Down
Loading