i have multiple apps in my turborepo and each app has a separate project created in vercel.
Each of the apps uses the same Database, where we are using Neon as the database provider and Prisma to manage migrations.
Here’s our current CI/CD pipeline
name: Deploy Preview
on: [pull_request]
env:
NEON_API_KEY: ${{ secrets.NEON_API_KEY }}
NEON_MAIN_BRANCH_NAME: ${{ secrets.NEON_MAIN_BRANCH_NAME }}
NEON_PROJECT_ID: ${{ secrets.NEON_PROJECT_ID }}
PG_DATABASE: ${{ secrets.PG_DATABASE }}
PG_USERNAME: ${{ secrets.PG_USERNAME }}
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_TEAM_ID: ${{ secrets.VERCEL_TEAM_ID }}
jobs:
deploy-preview:
permissions: write-all
runs-on: ubuntu-latest
strategy:
matrix:
app: [web,admin]
outputs:
web_preview_url: ${{ steps.deploy.outputs.web_preview_url }}
admin_preview_url: ${{ steps.deploy.outputs.admin_preview_url }}
neon_branch_id: ${{ steps.create-branch.outputs.branch_id }}
steps:
- name: Get branch name
id: branch-name
uses: tj-actions/branch-names@v8
- uses: actions/checkout@v4
with:
ref: ${{ steps.branch-name.outputs.current_branch }}
- name: Create Neon Branch
id: create-branch
uses: neondatabase/create-branch-action@v5
with:
project_id: ${{ env.NEON_PROJECT_ID }}
# parent: dev # optional (defaults to your primary branch)
branch_name: preview/pr-${{ github.event.number }}-${{ steps.branch-name.outputs.current_branch }}
username: ${{ env.PG_USERNAME }}
api_key: ${{ env.NEON_API_KEY }}
- name: Update environment variables
run: |
touch .env
echo DATABASE_URL=${{ steps.create-branch.outputs.db_url_with_pooler }} >> .env
- name: Install Vercel
run: npm install --global vercel@34.2.5
- name: Link Vercel to GitHub Repository
run: vercel link --repo --yes --scope=${{ env.VERCEL_TEAM_ID}} --token=${{ env.VERCEL_TOKEN }}
- name: Pull Vercel Environment Information
run: |
if [ "${{ matrix.app }}" == "web" ]; then
vercel pull --yes --scope=${{ env.VERCEL_TEAM_ID}} --environment=preview --token=${{ env.VERCEL_TOKEN }} --cwd apps/web
elif [ "${{ matrix.app }}" == "admin" ]; then
vercel pull --yes --scope=${{ env.VERCEL_TEAM_ID}} --environment=preview --token=${{ env.VERCEL_TOKEN }} --cwd apps/admin
fi
- name: Build Project Artifacts
run: |
if [ "${{ matrix.app }}" == "web" ]; then
vercel build --scope=${{ env.VERCEL_TEAM_ID}} --token=${{ env.VERCEL_TOKEN }} --cwd apps/web
elif [ "${{ matrix.app }}" == "admin" ]; then
vercel build --scope=${{ env.VERCEL_TEAM_ID}} --token=${{ env.VERCEL_TOKEN }} --cwd apps/admin
fi
- name: Deploy Preview to Vercel
id: deploy
run: |
if [ "${{ matrix.app }}" == "web" ]; then
echo web_preview_url=$(vercel deploy --prebuilt --env DATABASE_URL=${{ steps.create-branch.outputs.db_url_with_pooler }} --scope=${{ env.VERCEL_TEAM_ID}} --token=${{ env.VERCEL_TOKEN }} --cwd apps/web) >> $GITHUB_OUTPUT
elif [ "${{ matrix.app }}" == "admin" ]; then
echo admin_preview_url=$(vercel deploy --prebuilt --env DATABASE_URL=${{ steps.create-branch.outputs.db_url_with_pooler }} --scope=${{ env.VERCEL_TEAM_ID}} --token=${{ env.VERCEL_TOKEN }} --cwd apps/admin) >> $GITHUB_OUTPUT
fi
comment-preview:
runs-on: ubuntu-latest
needs: deploy-preview
steps:
- name: Comment on Pull Request
uses: thollander/actions-comment-pull-request@v2
with:
# GITHUB_TOKEN: ${{ env.GH_TOKEN }}
message: |
VERCEL Web Preview URL :rocket: : ${{ needs.deploy-preview.outputs.web_preview_url }}
VERCEL Admin Preview URL :rocket: : ${{ needs.deploy-preview.outputs.admin_preview_url }}
Neon branch :elephant: : https://console.neon.tech/app/projects/${{ env.NEON_PROJECT_ID }}/branches/${{ needs.deploy-preview.outputs.neon_branch_id }}
2 things to note from the snippet above
- We are updating the DATABASE_URL env value generated from neon database
- After deployment is completed we are commenting on the PR with deployment url
The problem with the current approach
- We are building common packages twice (defeats the purpose of using turborepo)
- Prisma migrations must be ran on both the apps in parallel (Although, I would be somehow be able to avoid it in and run it only once ). Sometimes the builds fails because of this
I cannot use turbo build
command since I wouldn’t be able to dynamically update env variable, access deployment url etc which the vercel cli provides with.
It would be good to have more options in the vercel cli to support this, similar to the --repo flag that was introduced some time back.
References: