How to deploy safely with Vercel
Learn how to run end-to-end tests for your pull requests previews and before you deploy your main branch to production with Vercel.

Vercel and Github configuration
After you have created your Vercel project from your Github repository, there are a few small steps to take:
- In the project Settings > Environments > Production, disable
Auto-assign Custom Production Domains
. This is important otherwise every pull requests merged into your main branch will trigger an update to your production site.

- In the project Settings > Deployment Protection > Protection Bypass for Automation, click “Add Secret” to generate a new environment variable called
VERCEL_AUTOMATION_BYPASS_SECRET
. Paste this value in your Github actions repository secrets with the same name:VERCEL_AUTOMATION_BYPASS_SECRET
. This is important so that Vercel lets you run the end-to-end tests on the protected preview environment.

-
In Account Settings > Tokens, create a new token for the organization your project belongs to. This will be used by Github Actions to deploy your application to production. Paste this value in your Github repository actions secrets with the name:
VERCEL_TOKEN
. -
While you are inside the Github repository secrets, add one more secret with the name:
VERCEL_TEAM_SCOPE
which is the slug of the organization your project belongs to as invercel.com/your-organization-slug/
Run end-to-end tests for your pull requests integration
I recommend to use Playwright as end-to-end tests solution as it is reliable and efficient. Vercel already deploys your pull requests branches to a preview environment, so we can easily setup a github action to run our end-to-end tests after the deployments as shown below:

Here I will assume you already have a Playwright test suite or equivalent that you want to run. If not, you can follow this guide to setup one. What is important here is that you can configure a dynamic BASE_URL
environment variable to indicate where the tests should run.
Now all you need is a github action workflow that will run your end-to-end tests after the deployment to the preview environment, here is an example below using pnpm:
name: End to End Tests
on: deployment_status:
jobs: e2e: if: github.event_name == 'deployment_status' && github.event.deployment_status.state == 'success' && github.event.deployment.environment == 'Preview' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: ref: ${{ github.event.deployment.sha }} - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v4 with: node-version: lts/* cache: "pnpm" - name: Install dependencies run: pnpm install
- name: Install Playwright Browsers run: pnpm exec playwright install --with-deps chromium - name: Run Playwright tests run: pnpm run e2e env: BASE_URL: ${{ github.event.deployment_status.environment_url }} VERCEL_AUTOMATION_BYPASS_SECRET: ${{ secrets.VERCEL_AUTOMATION_BYPASS_SECRET }}
It is fairly straightforward: Vercel will build and deploy your pull request branch to a dedicated preview URL, and then the github action will run your end-to-end tests on it thanks to the BASE_URL
environment variable which is set to the deployment_status
URL.
You can also see that we are using the VERCEL_AUTOMATION_BYPASS_SECRET
secret to bypass the deployment protection for automation as configured above.
That’s it! Now every pull request will run your end-to-end tests and report its status check in the Github UI.
You can also mark this status check as required in your github repository settings to ensure that your pull requests are not merged until the end-to-end tests pass.
Run end-to-end tests for your continuous deployment
While you are already well covered with end-to-end tests running before your pull requests are merged, you should also run those end-to-end tests on your main branch before going live. The reason is simple: your main branch is the real deal and I have seen too many incidents where things went wrong in production because the release deployed was never tested in its final state in a production-like environment.
If you disabled the Auto-assign Custom Production Domains
in the Vercel project settings, you should now see your latest main branch commit as as Production: Staged
deployment in the Vercel deployments UI:

To promote the depoyment, we will use a very similar recipe as the one we just setup for pull requests, except this time we will use the repository_dispatch
event instead of deployment_status
as recommended by Vercel:

Here is an example of a github action workflow that will run your end-to-end tests on your main branch before going live and then promote the deployment to production:
name: Deploy Production Vercel
on: repository_dispatch: types: - "vercel.deployment.success"
jobs: deploy-production-vercel: if: github.event.client_payload.environment == 'production' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: ref: ${{ github.event.client_payload.git.sha }} - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v4 with: node-version: lts/* cache: pnpm - name: Install dependencies run: pnpm install
- name: Install Playwright Browsers run: pnpm exec playwright install --with-deps chromium - name: Run Playwright tests run: pnpm run e2e env: BASE_URL: ${{ github.event.client_payload.url }} PUBLIC_ENV: production VERCEL_AUTOMATION_BYPASS_SECRET: ${{ secrets.VERCEL_AUTOMATION_BYPASS_SECRET }}
# Promote deployment to production - run: npx vercel promote ${{ github.event.client_payload.url }} --scope=${{ secrets.VERCEL_TEAM_SCOPE }} --token=${{ secrets.VERCEL_TOKEN }}
Now we have an extra step in our delivery pipeline to promote the preview deployment to production.
Also note the if:
conditions we have in our workflows to ensure we are not running them on the wrong environments.
Now your deployments UI should look like this with the latest main branch commit marked as Production: Current
deployment in the Vercel deployments UI:

And that’s all there is to it! This is thanks to Vercel being well integrated with Github and already triggering all the events we need to run our end-to-end tests and promote our main branch deployment to production.
If it seems a little intimidating to setup, don’t worry, I have created an example repository that you can use as a starting point: Safe Continuous Deployments.