brackt/.github/workflows/deploy.yml
Chris Parsons adde69a922 Run database migrations on deploy before starting container
Migrations were never being run against production on deploy, causing
schema mismatches when new columns are added. This adds a migration
step using the PROD_DATABASE_URL secret before bringing up the new
container, with set -e to abort the deploy if migrations fail.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 02:48:44 +00:00

161 lines
5.1 KiB
YAML

name: 🚀 Deploy
on:
push:
branches:
- main
pull_request: {}
permissions:
actions: write
contents: read
jobs:
cancel:
name: 🛑 Cancel Previous Runs
runs-on: ubuntu-latest
steps:
- uses: styfle/cancel-workflow-action@0.12.1
test:
name: 🧪 Test
needs: [cancel]
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: brackt_test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v4
- name: ⎔ Setup node
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'npm'
- name: 📥 Install dependencies
run: npm ci
- name: 🧪 Run unit tests
run: npm run test:run
env:
DATABASE_URL: postgresql://test:test@localhost:5432/brackt_test
NODE_OPTIONS: --max-old-space-size=4096
typecheck:
name: ʦ TypeScript
needs: [cancel]
runs-on: ubuntu-latest
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v4
- name: ⎔ Setup node
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'npm'
- name: 📥 Install dependencies
run: npm ci
- name: 🔎 Type check
run: npm run typecheck
lint:
name: 🔍 Lint
needs: [cancel]
runs-on: ubuntu-latest
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v4
- name: ⎔ Setup node
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'npm'
- name: 📥 Install dependencies
run: npm ci
- name: 🔍 Lint (oxlint)
run: npm run lint
build:
name: 🐳 Build
needs: [test, typecheck, lint]
# only build/deploy main branch on pushes
if: ${{ github.ref == 'refs/heads/main' && github.event_name == 'push' }}
runs-on: ubuntu-latest
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v4
- name: 🐳 Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: 🔓 Login to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ vars.CONTAINER_REGISTRY }}
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: 🗄️ Build and Push to Container Registry
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ vars.CONTAINER_REGISTRY }}/brackt:latest
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
name: 🚀 Deploy
runs-on: ubuntu-latest
needs: [build]
# only deploy main branch on pushes
if: ${{ github.ref == 'refs/heads/main' && github.event_name == 'push' }}
steps:
- name: 🚀 Deploy app to server
uses: appleboy/ssh-action@v1.0.3
env:
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
CONTAINER_REGISTRY: ${{ vars.CONTAINER_REGISTRY }}
PROD_DATABASE_URL: ${{ secrets.PROD_DATABASE_URL }}
with:
host: ${{ secrets.DEPLOY_HOST }}
port: ${{ secrets.DEPLOY_PORT }}
username: ${{ secrets.DEPLOY_USER }}
key: ${{ secrets.DEPLOY_KEY }}
envs: REGISTRY_USERNAME,REGISTRY_PASSWORD,CONTAINER_REGISTRY,PROD_DATABASE_URL
script: |
set -e
IMAGE="$CONTAINER_REGISTRY/brackt:latest"
docker login $CONTAINER_REGISTRY -u $REGISTRY_USERNAME -p $REGISTRY_PASSWORD
cd brackt
docker compose pull
docker run --rm -e DATABASE_URL="$PROD_DATABASE_URL" "$IMAGE" npx drizzle-kit migrate
docker compose up -d
sleep 10
if docker compose ps | grep -qE "Exit|exited"; then
echo "One or more containers failed to start:"
docker compose logs --tail=50
exit 1
fi