DEV Community

Ariff
Ariff

Posted on

Fixing Vercel + Supabase env issues in GitHub Actions

TL;DR

  • Preview deploys were failing due to missing env and token scopes
  • I consolidated env management using GitHub Environments + encrypted secrets
  • Added a preflight step to validate required vars before deploy ## Context I've been wiring a Next.js dashboard with Supabase and Vercel. My CI/CD started flaking — preview builds failed while local dev worked fine. The culprit: environment variables and token scopes not flowing correctly in Actions. ## Solution ### 1) Centralize env and secrets
  • Use GitHub Environments (Preview/Production) for context-aware values
  • Store only what's needed: VERCEL_TOKEN, VERCEL_ORG_ID, VERCEL_PROJECT_ID, SUPABASE_URL, SUPABASE_ANON_KEY, NEXT_PUBLIC_* ### 2) Preflight validation step Fail fast if any required env is missing. ### 3) Deploy with scoped token Ensure VERCEL_TOKEN has the minimal project scope. ### 4) Example workflow
name: Deploy Preview
on:
  pull_request:
    branches: [ main ]
jobs:
  preview:
    runs-on: ubuntu-latest
    environment: preview
    permissions:
      contents: read
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 20
      - name: Preflight env check
        run: |
          required=(VERCEL_TOKEN VERCEL_ORG_ID VERCEL_PROJECT_ID SUPABASE_URL SUPABASE_ANON_KEY)
          for k in "${required[@]}"; do
            if [ -z "${!k}" ]; then
              echo "::error::Missing $k"; exit 1
            fi
          done
        env:
          VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
          VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
          VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
          SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
          SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }}
      - name: Install
        run: npm ci
      - name: Build
        run: npm run build
        env:
          NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
          NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }}
      - name: Vercel deploy (Preview)
        run: |
          npx vercel pull --yes --environment=preview --token=$VERCEL_TOKEN
          npx vercel build --token=$VERCEL_TOKEN
          npx vercel deploy --prebuilt --token=$VERCEL_TOKEN
        env:
          VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
Enter fullscreen mode Exit fullscreen mode

Gotchas

  • Avoid mixing NEXT_PUBLIC_* and server-only keys
  • Don't store Supabase service_role in GitHub — keep it out of CI unless absolutely necessary
  • Vercel envs must be created in the correct environment (Preview/Prod) or pull will fetch empty values ## Ask How are you validating env drift between Vercel and GitHub? Any lightweight secret scanning step you recommend pre-merge?

Top comments (0)