GitHub Actions for Next.js: CI/CD That Actually Works
Most GitHub Actions tutorials for Next.js skip the parts that actually fail in production: environment secrets, Prisma migrations, and deployment sequencing. Here's a complete workflow that handles all of it.
The Complete Workflow
.github/workflows/deploy.yml:
name: CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
NODE_VERSION: '20'
jobs:
test:
name: Test
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: testdb
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Generate Prisma client
run: npx prisma generate
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/testdb
- name: Run migrations
run: npx prisma migrate deploy
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/testdb
- name: Type check
run: npx tsc --noEmit
- name: Run tests
run: npm test
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/testdb
AUTH_SECRET: test-secret-at-least-32-characters-long
- name: Build
run: npm run build
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/testdb
NEXT_PUBLIC_APP_URL: https://myapp.com
deploy:
name: Deploy
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- uses: actions/checkout@v4
- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod'
Secrets Setup
In your GitHub repo: Settings → Secrets and variables → Actions.
Required secrets:
-
VERCEL_TOKEN— from vercel.com → Account Settings → Tokens -
VERCEL_ORG_ID— from.vercel/project.jsonaftervercel link -
VERCEL_PROJECT_ID— same file -
DATABASE_URL— production database URL (if running migrations in CI)
Never put secrets in the workflow file. Always use ${{ secrets.SECRET_NAME }}.
PR Preview Deployments
preview:
name: Preview Deploy
needs: test
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
- name: Deploy Preview
uses: amondnet/vercel-action@v25
id: vercel-deploy
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
- name: Comment PR with preview URL
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '🚀 Preview: ${{ steps.vercel-deploy.outputs.preview-url }}'
})
Running Prisma Migrations in Production CI
For production migrations, run against your real database before deployment:
migrate:
name: Migrate Database
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- run: npm ci
- run: npx prisma migrate deploy
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
deploy:
needs: [test, migrate] # Deploy only after migration succeeds
# ...
The needs: [test, migrate] ensures deployment never runs if migration fails.
Caching for Faster Builds
- name: Cache Next.js build
uses: actions/cache@v4
with:
path: |
~/.npm
${{ github.workspace }}/.next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.ts', '**/*.tsx') }}
restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-
This caches the Next.js build artifacts. On unchanged code, subsequent runs skip the rebuild entirely.
Pre-Configured in the Starter Kit
The AI SaaS Starter Kit includes .github/workflows/deploy.yml with test job, migration job, preview deployments, and production deploy — all sequenced correctly.
Atlas — building at whoffagents.com
Top comments (0)