CI/CD with GitHub Actions
CI/CD with GitHub Actions
The Workflow That Protects Main
Every push or PR to main runs: typecheck → tests → build. Only if all pass does Vercel deploy. This means broken code never reaches production.
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npx tsc --noEmit
test:
runs-on: ubuntu-latest
needs: typecheck # only run if typecheck passes
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm test
build:
runs-on: ubuntu-latest
needs: [typecheck, test]
env:
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL }}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run build---
Adding Secrets to GitHub
Repository → Settings → Secrets and Variables → Actions → New repository secret.
Add the same variables Vercel needs:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEY- Any other build-time environment variables
---
Deploying to Vercel via GitHub Actions
Vercel automatically deploys when you push to GitHub (via the Git integration). The GitHub Actions workflow above just gates that deployment — if CI fails, Vercel still deploys (it doesn't know about your workflow by default).
To make Vercel wait for CI:
Option A: Use Vercel's Deployment Protection (requires Vercel Pro).
Option B: Deploy manually from GitHub Actions using the Vercel CLI:
deploy:
needs: [typecheck, test, build]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20, cache: npm }
- run: npm ci
- run: npm install -g vercel
- run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
- run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
- run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}Add to GitHub Secrets: VERCEL_TOKEN (from vercel.com/account/tokens), VERCEL_ORG_ID, VERCEL_PROJECT_ID (from .vercel/project.json after running vercel link).
---
Caching for Speed
Without caching, npm ci downloads all packages on every run. With caching, the second run takes seconds:
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm # caches node_modules based on package-lock.json hash---
Viewing Workflow Results
GitHub → your repo → Actions tab. Click a workflow run to see each job's logs. Red X = failure, green checkmark = success. Click any step to expand the logs.
Debugging failed workflows:
- Look at the step that failed
- Read the full error message (usually at the bottom of that step's output)
- Reproduce locally: run the exact same command from the workflow