github-actions
GitHub Actions Deploy to Vercel
GitHub Actions workflow to deploy a frontend application to Vercel with preview deployments on PRs and production on merge.
Overview
A GitHub Actions workflow that deploys your application to Vercel. Creates preview deployments for pull requests and promotes to production when code is merged to the main branch. Uses the Vercel CLI for full control over the deployment process.
Configuration
# .github/workflows/deploy-vercel.yml
name: Deploy to Vercel
on:
push:
branches: [main] # Production deploy on merge to main
pull_request:
branches: [main] # Preview deploy on PRs
# Cancel in-progress deployments for the same ref
concurrency:
group: deploy-${{ github.ref }}
cancel-in-progress: true
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: ${{ github.event_name == 'push' && 'production' || 'preview' }}
url: ${{ steps.deploy.outputs.url }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm # Cache npm dependencies
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test -- --ci
- name: Install Vercel CLI
run: npm install -g vercel
# Pull Vercel project settings
- name: Pull Vercel environment
run: vercel pull --yes --environment=${{ github.event_name == 'push' && 'production' || 'preview' }} --token=${{ secrets.VERCEL_TOKEN }}
# Build the project using Vercel's build system
- name: Build project
run: vercel build ${{ github.event_name == 'push' && '--prod' || '' }} --token=${{ secrets.VERCEL_TOKEN }}
# Deploy to Vercel
- name: Deploy to Vercel
id: deploy
run: |
URL=$(vercel deploy --prebuilt ${{ github.event_name == 'push' && '--prod' || '' }} --token=${{ secrets.VERCEL_TOKEN }})
echo "url=$URL" >> "$GITHUB_OUTPUT"
# Comment preview URL on pull request
- name: Comment PR with preview URL
if: github.event_name == 'pull_request'
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 deployment ready: ${{ steps.deploy.outputs.url }}`
})
Key Options Explained
concurrency— Cancels any in-progress deployment for the same branch when a new commit is pushed, preventing wasted resources on stale deploys.environment— Creates GitHub environment deployments with tracked URLs. Shows deployment status directly on PRs and the repository homepage.vercel pull— Downloads project configuration and environment variables from Vercel. The--environmentflag selects the right variable set.vercel build --prebuilt— Builds locally in CI, then deploys the pre-built output. Gives you full control over the build environment.--prodflag — Only used on pushes to main. Without it, Vercel creates a preview deployment with a unique URL.
Common Modifications
- Skip deploy on docs changes: Add
paths-ignore: ['**.md', 'docs/**']to thepushtrigger to avoid deploying on documentation-only changes. - Environment variables: Add
vercel env pull .env.local --token=${{ secrets.VERCEL_TOKEN }}to pull env vars before building. - Monorepo: Add
--cwd packages/frontendto Vercel commands to target a specific workspace package. - Protected production: Use GitHub environment protection rules to require approval before production deployments.
- Alias domains: Add
vercel alias $URL my-app-pr-${{ github.event.number }}.vercel.app --token=${{ secrets.VERCEL_TOKEN }}for readable preview URLs.