|
| 1 | +name: Chaos Migration Drill |
| 2 | + |
| 3 | +# Nightly chaos drill: starts a migration, kills Postgres mid-flight, |
| 4 | +# restarts it, and verifies the runner recovers cleanly. |
| 5 | +# |
| 6 | +# SAFETY: runs only on ephemeral containers — never against a shared DB. |
| 7 | +# The workflow does NOT require DATABASE_URL from secrets; it spins up |
| 8 | +# a throwaway Postgres container on the runner itself. |
| 9 | + |
| 10 | +on: |
| 11 | + schedule: |
| 12 | + # Nightly at 02:00 UTC (low-traffic window) |
| 13 | + - cron: '0 2 * * *' |
| 14 | + workflow_dispatch: |
| 15 | + inputs: |
| 16 | + kill_delay_min: |
| 17 | + description: 'Min seconds before kill (float)' |
| 18 | + default: '0.05' |
| 19 | + required: false |
| 20 | + kill_delay_max: |
| 21 | + description: 'Max seconds before kill (float)' |
| 22 | + default: '2.0' |
| 23 | + required: false |
| 24 | + pull_request: |
| 25 | + branches: [main, master, develop] |
| 26 | + paths: |
| 27 | + - 'internal/migrations/**' |
| 28 | + - 'scripts/drills/kill_pg_migration.sh' |
| 29 | + - '.github/workflows/chaos-migration-drill.yml' |
| 30 | + - 'migrations/**' |
| 31 | + |
| 32 | +concurrency: |
| 33 | + group: chaos-drill-${{ github.ref }} |
| 34 | + cancel-in-progress: true |
| 35 | + |
| 36 | +jobs: |
| 37 | + chaos-migration-drill: |
| 38 | + name: Kill-During-Migration Drill |
| 39 | + runs-on: ubuntu-latest |
| 40 | + # Hard timeout: the drill should complete well within 10 minutes. |
| 41 | + timeout-minutes: 10 |
| 42 | + |
| 43 | + steps: |
| 44 | + - name: Checkout |
| 45 | + uses: actions/checkout@v4 |
| 46 | + |
| 47 | + - name: Set up Go |
| 48 | + uses: actions/setup-go@v5 |
| 49 | + with: |
| 50 | + go-version-file: go.mod |
| 51 | + cache: true |
| 52 | + |
| 53 | + - name: Run chaos migration drill |
| 54 | + env: |
| 55 | + POSTGRES_IMAGE: postgres:17-alpine |
| 56 | + POSTGRES_CONTAINER: stellabill-chaos-pg |
| 57 | + POSTGRES_USER: drill |
| 58 | + POSTGRES_PASSWORD: drill |
| 59 | + POSTGRES_DB: drill |
| 60 | + POSTGRES_PORT: '15432' |
| 61 | + KILL_DELAY_MIN: ${{ github.event.inputs.kill_delay_min || '0.05' }} |
| 62 | + KILL_DELAY_MAX: ${{ github.event.inputs.kill_delay_max || '2.0' }} |
| 63 | + RESULTS_CSV: drill-results.csv |
| 64 | + SLACK_WEBHOOK_URL: ${{ secrets.CHAOS_DRILL_SLACK_WEBHOOK }} |
| 65 | + run: bash scripts/drills/kill_pg_migration.sh |
| 66 | + |
| 67 | + - name: Upload drill results artifact |
| 68 | + if: always() |
| 69 | + uses: actions/upload-artifact@v4 |
| 70 | + with: |
| 71 | + name: chaos-drill-results-${{ github.run_id }} |
| 72 | + path: | |
| 73 | + drill-results.csv |
| 74 | + /tmp/drill-migrate-pre.log |
| 75 | + /tmp/drill-migrate-post.log |
| 76 | + retention-days: 30 |
| 77 | + |
| 78 | + - name: Summarise result |
| 79 | + if: always() |
| 80 | + run: | |
| 81 | + echo "## Chaos Migration Drill Results" >> "$GITHUB_STEP_SUMMARY" |
| 82 | + echo '```' >> "$GITHUB_STEP_SUMMARY" |
| 83 | + cat drill-results.csv 2>/dev/null || echo "(no results file)" |
| 84 | + echo '```' >> "$GITHUB_STEP_SUMMARY" |
| 85 | +
|
| 86 | + - name: Notify on failure (no Slack webhook configured) |
| 87 | + if: failure() && env.SLACK_WEBHOOK_URL == '' |
| 88 | + run: | |
| 89 | + echo "::warning::Chaos drill failed. Configure CHAOS_DRILL_SLACK_WEBHOOK secret for Slack notifications." |
| 90 | + env: |
| 91 | + SLACK_WEBHOOK_URL: ${{ secrets.CHAOS_DRILL_SLACK_WEBHOOK }} |
0 commit comments