<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lucas Reis</title>
    <description>The latest articles on DEV Community by Lucas Reis (@thereis).</description>
    <link>https://dev.to/thereis</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F144407%2Fa6ac8f34-912e-4cc1-afff-f0f591d8f709.jpg</url>
      <title>DEV Community: Lucas Reis</title>
      <link>https://dev.to/thereis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thereis"/>
    <language>en</language>
    <item>
      <title>How to deploy and remove Vercel Preview Deployment from GitHub Actions</title>
      <dc:creator>Lucas Reis</dc:creator>
      <pubDate>Sat, 09 Sep 2023 10:24:28 +0000</pubDate>
      <link>https://dev.to/thereis/how-to-remove-vercel-deployments-from-github-actions-4nfh</link>
      <guid>https://dev.to/thereis/how-to-remove-vercel-deployments-from-github-actions-4nfh</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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 &lt;a href="https://vercel.com" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt; 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. &lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 - Gather the necessary ids
&lt;/h2&gt;

&lt;p&gt;To interact with the &lt;strong&gt;Vercel API&lt;/strong&gt; you need the &lt;code&gt;projectId&lt;/code&gt; and &lt;code&gt;teamId&lt;/code&gt; values. To obtain those values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the Vercel dashboard and select the team&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fofl50td3m474o3vd9ikq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fofl50td3m474o3vd9ikq.png" alt="Dashboard image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on settings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3egqxv1i9b6g9v8dkpvm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3egqxv1i9b6g9v8dkpvm.png" alt="Settings image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copy your team id&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falb9jm63be1mu6d1702v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falb9jm63be1mu6d1702v.png" alt="Team Id image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the project that you're working on by clicking in Overview&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5owhuyuzo2to2naiops.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5owhuyuzo2to2naiops.png" alt="Overview image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click in settings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpm31gwpql6ryd04djs7q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpm31gwpql6ryd04djs7q.png" alt="Settings image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copy your project id&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3cix8uxpb8aeoaw1m89g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3cix8uxpb8aeoaw1m89g.png" alt="Project id image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create an admin token
Create the admin token by visiting &lt;a href="https://vercel.com/account/tokens" rel="noopener noreferrer"&gt;Tokens&lt;/a&gt; page. Don't forget to select &lt;strong&gt;Full Scope&lt;/strong&gt; options. This is important because this token will be responsible to delete the deployments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp066rfzzt94ne5u73qjr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp066rfzzt94ne5u73qjr.png" alt="Admin token"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Summarizing, you'll need 3 tokens from vercel:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Token&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Variable name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;VERCEL_ORG_ID&lt;/td&gt;
&lt;td&gt;It's the team id&lt;/td&gt;
&lt;td&gt;VERCEL_ORG_ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VERCEL_PROJECT_ID&lt;/td&gt;
&lt;td&gt;It's the project id&lt;/td&gt;
&lt;td&gt;VERCEL_PROJECT_ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VERCEL_TOKEN&lt;/td&gt;
&lt;td&gt;It's the API key token&lt;/td&gt;
&lt;td&gt;VERCEL_TOKEN&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Step 1 - Create the environment variables in GitHub Actions
&lt;/h2&gt;

&lt;p&gt;Visit the repository settings and create the environment variables there.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa5f748dsn1oxx29jh8b1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa5f748dsn1oxx29jh8b1.png" alt="GitHub Actions secrets"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 - Setup the &lt;code&gt;deploy_preview.yml&lt;/code&gt; workflow
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go into your project, create a new workflow named &lt;code&gt;deploy_preview.yml&lt;/code&gt; in the &lt;code&gt;.github/workflows&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;Paste the following workflow content:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Vercel Preview Deployment&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;VERCEL_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.VERCEL_TOKEN }}&lt;/span&gt;
  &lt;span class="na"&gt;VERCEL_ORG_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.VERCEL_ORG_ID }}&lt;/span&gt;
  &lt;span class="na"&gt;VERCEL_PROJECT_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.VERCEL_PROJECT_ID }}&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;
  &lt;span class="na"&gt;statuses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
  &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;opened&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;synchronize&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deploy-preview&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Extract branch name&lt;/span&gt;
        &lt;span class="na"&gt;shell&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bash&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" &amp;gt;&amp;gt; $GITHUB_OUTPUT&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;extract_branch&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Hash branch name&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pplanel/hash-calculator-action@v1.3.1&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hash_branch&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.extract_branch.outputs.branch }}&lt;/span&gt;
          &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MD5&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Vercel CLI&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install --global vercel@latest&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cache dependencies&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/cache@v2&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cache-npm&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;~/.npm&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm-${{ hashFiles('package-lock.json') }}&lt;/span&gt;
          &lt;span class="na"&gt;restore-keys&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm-&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.cache-npm.outputs.cache-hit != 'true' }}&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm ci --ignore-scripts&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pull Vercel Environment Information&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vercel pull --yes --environment=preview --token=$VERCEL_TOKEN&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy Project Artifacts to Vercel&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vercel&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;META_TAG&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.hash_branch.outputs.digest }}-${{ github.run_number }}-${{ github.run_attempt}}&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;vercel --version&lt;/span&gt;
          &lt;span class="s"&gt;vercel pull --yes --environment=preview --token=$VERCEL_TOKEN&lt;/span&gt;
          &lt;span class="s"&gt;vercel build --token=$VERCEL_TOKEN&lt;/span&gt;
          &lt;span class="s"&gt;vercel deploy --prebuilt --archive=tgz --token=$VERCEL_TOKEN --meta base_hash=${{ env.META_TAG }}&lt;/span&gt;

          &lt;span class="s"&gt;vercel ls --token=$VERCEL_TOKEN --meta base_hash=${{ env.META_TAG }} &amp;amp;&amp;gt; vercel-output&lt;/span&gt;
          &lt;span class="s"&gt;url=$(cat vercel-output | grep http | awk '{print $2}')&lt;/span&gt;
          &lt;span class="s"&gt;echo "New preview URL: $url"&lt;/span&gt;
          &lt;span class="s"&gt;echo "META_TAG=$META_TAG"&lt;/span&gt;
          &lt;span class="s"&gt;echo "VERCEL_URL=$url" &amp;gt;&amp;gt; "$GITHUB_OUTPUT"&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mshick/add-pr-comment@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;Your build has completed!&lt;/span&gt;

            &lt;span class="s"&gt;[Preview deployment](${{ steps.vercel.outputs.VERCEL_URL }})&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Checkout the PR content into the working directory.&lt;/li&gt;
&lt;li&gt;Get the branch name.&lt;/li&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;li&gt;Install Vercel CLI.&lt;/li&gt;
&lt;li&gt;Check the cache for npm modules (faster builds)&lt;/li&gt;
&lt;li&gt;Install dependencies if needed&lt;/li&gt;
&lt;li&gt;Pull the environment variables defined from Vercel&lt;/li&gt;
&lt;li&gt;Build and deploy artifacts. Pay attention to the &lt;code&gt;META_TAG&lt;/code&gt; variable. This is important because it will be used a metadata to identify every preview deployment.&lt;/li&gt;
&lt;li&gt;Comment the preview URL.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Within this steps, you'll create automatic preview links on every push to your branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 - Setup the &lt;code&gt;remove_deploy_preview.yml&lt;/code&gt; workflow and script
&lt;/h2&gt;

&lt;p&gt;This workflow will be mandatory in the case you want to delete all the previews builds that the project has generated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bash script to remove the builds from Vercel
&lt;/h3&gt;

&lt;p&gt;In your project root folder, create the &lt;code&gt;scripts/delete-deployment-preview.sh&lt;/code&gt; file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# Set the pipefail option.&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; pipefail

&lt;span class="c"&gt;# Get the Vercel API endpoints.&lt;/span&gt;
&lt;span class="nv"&gt;GET_DEPLOYMENTS_ENDPOINT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://api.vercel.com/v6/deployments"&lt;/span&gt;
&lt;span class="nv"&gt;DELETE_DEPLOYMENTS_ENDPOINT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://api.vercel.com/v13/deployments"&lt;/span&gt;

&lt;span class="c"&gt;# Create a list of deployments.&lt;/span&gt;
&lt;span class="nv"&gt;deployments&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; GET &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$GET_DEPLOYMENTS_ENDPOINT&lt;/span&gt;&lt;span class="s2"&gt;/?projectId=&lt;/span&gt;&lt;span class="nv"&gt;$VERCEL_PROJECT_ID&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;teamId=&lt;/span&gt;&lt;span class="nv"&gt;$VERCEL_ORG_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$VERCEL_TOKEN&lt;/span&gt;&lt;span class="s2"&gt; "&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Filter the deployments list by meta.base_hash === meta tag.&lt;/span&gt;
&lt;span class="nv"&gt;filtered_deployments&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$deployments&lt;/span&gt; | jq &lt;span class="nt"&gt;--arg&lt;/span&gt; META_TAG &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$META_TAG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'[.deployments[] | select(.meta.base_hash | type == "string" and contains($META_TAG)) | .uid] | join(",")'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;filtered_deployments&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;filtered_deployments&lt;/span&gt;&lt;span class="p"&gt;//\&lt;/span&gt;&lt;span class="s2"&gt;"/}"&lt;/span&gt;&lt;span class="p"&gt; # Remove double quotes

# Clears the values from filtered_deployments
IFS=&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="p"&gt; read -ra values &amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$filtered_deployments&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;

echo &lt;/span&gt;&lt;span class="s2"&gt;"META_TAG &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;META_TAG&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;
echo &lt;/span&gt;&lt;span class="s2"&gt;"Filtered deployments &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;filtered_deployments&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;

# Iterate over the filtered deployments list.
for uid in &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;; do
    echo &lt;/span&gt;&lt;span class="s2"&gt;"Deleting &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;uid&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;

    delete_url=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DELETE_DEPLOYMENTS_ENDPOINT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;uid&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="p"&gt;?teamId=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VERCEL_ORG_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="p"&gt;
    echo &lt;/span&gt;&lt;span class="nv"&gt;$delete_url&lt;/span&gt;&lt;span class="p"&gt;

    # Make DELETE a request to the /v13/deployments/{id&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; endpoint.
    curl -X DELETE &lt;/span&gt;&lt;span class="nv"&gt;$delete_url&lt;/span&gt;&lt;span class="s2"&gt; -H "&lt;/span&gt;Authorization: Bearer &lt;span class="nv"&gt;$VERCEL_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"

    echo "&lt;/span&gt;Deleted!&lt;span class="s2"&gt;"
done



&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Don't forget to run &lt;code&gt;chmod&lt;/code&gt;:&lt;br&gt;
&lt;code&gt;chmod a+x ./scripts/delete-deployment-preview.sh&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment workflow
&lt;/h3&gt;

&lt;p&gt;Create the &lt;code&gt;remove_deploy_preview.yml&lt;/code&gt; into the &lt;code&gt;.github/workflows&lt;/code&gt; folder and paste the following content:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;


&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Remove deploy preview&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;
  &lt;span class="na"&gt;statuses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
  &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;VERCEL_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.VERCEL_TOKEN }}&lt;/span&gt;
  &lt;span class="na"&gt;VERCEL_ORG_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.VERCEL_ORG_ID }}&lt;/span&gt;
  &lt;span class="na"&gt;VERCEL_PROJECT_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.VERCEL_PROJECT_ID }}&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;closed&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;delete-deployments&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Extract branch name&lt;/span&gt;
        &lt;span class="na"&gt;shell&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bash&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" &amp;gt;&amp;gt; $GITHUB_OUTPUT&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;extract_branch&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Hash branch name&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pplanel/hash-calculator-action@v1.3.1&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hash_branch&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.extract_branch.outputs.branch }}&lt;/span&gt;
          &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MD5&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Call the delete-deployment-preview.sh script&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;META_TAG&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.hash_branch.outputs.digest }}&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;bash ./scripts/delete-deployment-preview.sh&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The workflow steps are the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Checkout the PR contents into the working space.&lt;/li&gt;
&lt;li&gt;Get pull request branch name.&lt;/li&gt;
&lt;li&gt;Create a hash for it.&lt;/li&gt;
&lt;li&gt;Execute the &lt;code&gt;bash&lt;/code&gt; script that we've created earlier with the &lt;code&gt;META_TAG&lt;/code&gt; environment variable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The script will make a GET request to the &lt;code&gt;https://api.vercel.com/v6/deployments&lt;/code&gt; endpoint and will fetch all the preview deployments that you have. Then, we use &lt;code&gt;jq&lt;/code&gt; to create a list of &lt;code&gt;uid&lt;/code&gt; that matches with the &lt;code&gt;meta.base_hash&lt;/code&gt; that we passed earlier when we created a new preview.&lt;/p&gt;

&lt;p&gt;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).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzb5fgmr5dudotwl8q740.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzb5fgmr5dudotwl8q740.png" alt="Delete deployment preview"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/dev_reis" rel="noopener noreferrer"&gt;dev_reis on Twitter&lt;/a&gt;&lt;br&gt;
&lt;a href="https://instagram.com/dev_reis" rel="noopener noreferrer"&gt;dev_reis on Instagram&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>vercel</category>
      <category>preview</category>
      <category>github</category>
    </item>
  </channel>
</rss>
