Recently I have started my journey learning about NextJS and the Vercel platform. As a experienced React Developer, I've developed several frontend applications in past 6 years with this library and it's really nice to see the whole React ecosystem building/following on what a company's says and interacts with the community. The future shines for React and any similarity to PHP is not a coincidence.
So let's get started. As I am building my startup, we decided to create the frontend + backend with NextJS. It's the best thing for our product, having a monolith with the backend and frontend included... and some other benefits like SSR and caching. Since we want to have fast iteration in the product, having a service like Vercel is helping us to build our product without caring about infrastructure (AWS, GCP). The prices are very modest, to be honest I think it's worthy to pay $20 for a full stack infrastructure with a included Postgres instance.
Instead of using their automatic build after pushing a commit to a branch, I've decided to deactivate this feature and trigger the builds from a GitHub Actions.
Step 1 - Gather the necessary ids
To interact with the Vercel API you need the projectId
and teamId
values. To obtain those values:
- Go to the Vercel dashboard and select the team
- Click on settings
- Copy your team id
- Select the project that you're working on by clicking in Overview
- Click in settings
- Copy your project id
- Create an admin token Create the admin token by visiting Tokens page. Don't forget to select Full Scope options. This is important because this token will be responsible to delete the deployments.
Summarizing, you'll need 3 tokens from vercel:
Token | Description | Variable name |
---|---|---|
VERCEL_ORG_ID | It's the team id | VERCEL_ORG_ID |
VERCEL_PROJECT_ID | It's the project id | VERCEL_PROJECT_ID |
VERCEL_TOKEN | It's the API key token | VERCEL_TOKEN |
Step 1 - Create the environment variables in GitHub Actions
Visit the repository settings and create the environment variables there.
Step 2 - Setup the deploy_preview.yml
workflow
- Go into your project, create a new workflow named
deploy_preview.yml
in the.github/workflows
folder. - Paste the following workflow content:
name: Vercel Preview Deployment
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
permissions:
contents: read
statuses: write
pull-requests: write
on:
pull_request:
types:
- opened
- synchronize
jobs:
deploy-preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Extract branch name
shell: bash
run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
id: extract_branch
- name: Hash branch name
uses: pplanel/hash-calculator-action@v1.3.1
id: hash_branch
with:
input: ${{ steps.extract_branch.outputs.branch }}
method: MD5
- name: Install Vercel CLI
run: npm install --global vercel@latest
- name: Cache dependencies
uses: actions/cache@v2
id: cache-npm
with:
path: ~/.npm
key: npm-${{ hashFiles('package-lock.json') }}
restore-keys: npm-
- name: Install dependencies
if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }}
run: npm ci --ignore-scripts
- name: Pull Vercel Environment Information
run: vercel pull --yes --environment=preview --token=$VERCEL_TOKEN
- name: Deploy Project Artifacts to Vercel
id: vercel
env:
META_TAG: ${{ steps.hash_branch.outputs.digest }}-${{ github.run_number }}-${{ github.run_attempt}}
run: |
vercel --version
vercel pull --yes --environment=preview --token=$VERCEL_TOKEN
vercel build --token=$VERCEL_TOKEN
vercel deploy --prebuilt --archive=tgz --token=$VERCEL_TOKEN --meta base_hash=${{ env.META_TAG }}
vercel ls --token=$VERCEL_TOKEN --meta base_hash=${{ env.META_TAG }} &> vercel-output
url=$(cat vercel-output | grep http | awk '{print $2}')
echo "New preview URL: $url"
echo "META_TAG=$META_TAG"
echo "VERCEL_URL=$url" >> "$GITHUB_OUTPUT"
- uses: mshick/add-pr-comment@v2
with:
message: |
Your build has completed!
[Preview deployment](${{ steps.vercel.outputs.VERCEL_URL }})
This workflow is a basic workflow which will be executed whenever a pull request is created or synchronized (receives a new commit). The steps executed are:
- Checkout the PR content into the working directory.
- Get the branch name.
- Create a unique hash for the branch name. This is important because Vercel allow meta tags into builds, this will help us to identify later when we have to remove all preview deployments from a certain branch.
- Install Vercel CLI.
- Check the cache for npm modules (faster builds)
- Install dependencies if needed
- Pull the environment variables defined from Vercel
- Build and deploy artifacts. Pay attention to the
META_TAG
variable. This is important because it will be used a metadata to identify every preview deployment. - Comment the preview URL.
Within this steps, you'll create automatic preview links on every push to your branch.
Step 3 - Setup the remove_deploy_preview.yml
workflow and script
This workflow will be mandatory in the case you want to delete all the previews builds that the project has generated.
Bash script to remove the builds from Vercel
In your project root folder, create the scripts/delete-deployment-preview.sh
file.
#!/bin/bash
# Set the pipefail option.
set -o pipefail
# Get the Vercel API endpoints.
GET_DEPLOYMENTS_ENDPOINT="https://api.vercel.com/v6/deployments"
DELETE_DEPLOYMENTS_ENDPOINT="https://api.vercel.com/v13/deployments"
# Create a list of deployments.
deployments=$(curl -s -X GET "$GET_DEPLOYMENTS_ENDPOINT/?projectId=$VERCEL_PROJECT_ID&teamId=$VERCEL_ORG_ID" -H "Authorization: Bearer $VERCEL_TOKEN ")
# Filter the deployments list by meta.base_hash === meta tag.
filtered_deployments=$(echo $deployments | jq --arg META_TAG "$META_TAG" '[.deployments[] | select(.meta.base_hash | type == "string" and contains($META_TAG)) | .uid] | join(",")')
filtered_deployments="${filtered_deployments//\"/}" # Remove double quotes
# Clears the values from filtered_deployments
IFS=',' read -ra values <<<"$filtered_deployments"
echo "META_TAG ${META_TAG}"
echo "Filtered deployments ${filtered_deployments}"
# Iterate over the filtered deployments list.
for uid in "${values[@]}"; do
echo "Deleting ${uid}"
delete_url=${DELETE_DEPLOYMENTS_ENDPOINT}/${uid}?teamId=${VERCEL_ORG_ID}
echo $delete_url
# Make DELETE a request to the /v13/deployments/{id} endpoint.
curl -X DELETE $delete_url -H "Authorization: Bearer $VERCEL_TOKEN"
echo "Deleted!"
done
Don't forget to run chmod
:
chmod a+x ./scripts/delete-deployment-preview.sh
Deployment workflow
Create the remove_deploy_preview.yml
into the .github/workflows
folder and paste the following content:
name: Remove deploy preview
permissions:
contents: read
statuses: write
pull-requests: write
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
on:
pull_request:
types:
- closed
jobs:
delete-deployments:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Extract branch name
shell: bash
run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
id: extract_branch
- name: Hash branch name
uses: pplanel/hash-calculator-action@v1.3.1
id: hash_branch
with:
input: ${{ steps.extract_branch.outputs.branch }}
method: MD5
- name: Call the delete-deployment-preview.sh script
env:
META_TAG: ${{ steps.hash_branch.outputs.digest }}
run: |
bash ./scripts/delete-deployment-preview.sh
This workflow will run when a existent PR is closed or merged. So be aware that this job will possibly run without deleting any previews.
The workflow steps are the following:
- Checkout the PR contents into the working space.
- Get pull request branch name.
- Create a hash for it.
- Execute the
bash
script that we've created earlier with theMETA_TAG
environment variable.
The script will make a GET request to the https://api.vercel.com/v6/deployments
endpoint and will fetch all the preview deployments that you have. Then, we use jq
to create a list of uid
that matches with the meta.base_hash
that we passed earlier when we created a new preview.
If there's any available deployment, we delete it. If none, it's all good, no need to worry (unless you don't have any at all).
That's all folks, I hope you can sort this out. Leave a comment if you liked and follow me (all about my complains) on Twitter.
Top comments (0)