name: Deploy production # Two environments only: local dev (see README "Development") and prod. # A push/merge to main builds and tests the image, backs up prod (pg_dump via # postgres:17-alpine), runs Drizzle migrations, then switches the container. # Pushes to any other branch (e.g. db-schemas) do not match and run nothing. on: push: branches: [main] workflow_dispatch: inputs: rollback_tag: description: 'Roll back: redeploy this earlier image SHA (skips migrations/seeds)' required: true concurrency: group: deploy-production cancel-in-progress: false jobs: deploy: # Belt and braces: a manual dispatch from another branch does nothing either. if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Configure deployment SSH key env: DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }} run: | set -euo pipefail install -d -m 700 ~/.ssh printf '%s\n' "$DEPLOY_KEY" > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 ssh-keyscan -H 172.17.0.1 >> ~/.ssh/known_hosts # The Dockerfile runs bun install --frozen-lockfile, unit tests and the build, # so a failing test never produces a deployable image. - if: github.event_name == 'push' uses: docker/build-push-action@v5 with: context: . push: false load: true tags: git.stanrunge.dev/stan/website:${{ github.sha }} build-args: | GIT_SHA=${{ github.sha }} - name: Transfer image if: github.event_name == 'push' run: | set -euo pipefail image="git.stanrunge.dev/stan/website:${{ github.sha }}" docker save "$image" | ssh -o BatchMode=yes deploy@172.17.0.1 'sudo docker load' - name: Back up, migrate and deploy if: github.event_name == 'push' run: | set -euo pipefail ssh -o BatchMode=yes deploy@172.17.0.1 \ "bash -s -- '${{ github.sha }}' deploy" < scripts/deploy-remote.sh - name: Roll back to an earlier image if: github.event_name == 'workflow_dispatch' env: TAG: ${{ inputs.rollback_tag }} run: | set -euo pipefail case "$TAG" in *[!0-9a-f]*|'') echo 'Invalid image tag' >&2; exit 2 ;; esac ssh -o BatchMode=yes deploy@172.17.0.1 "bash -s -- '$TAG' rollback" < scripts/deploy-remote.sh