<?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: Damian Świstowski</title>
    <description>The latest articles on DEV Community by Damian Świstowski (@journeyman).</description>
    <link>https://dev.to/journeyman</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%2F920848%2F9dcf2c66-0932-439d-b221-a45596b1c16c.png</url>
      <title>DEV Community: Damian Świstowski</title>
      <link>https://dev.to/journeyman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/journeyman"/>
    <language>en</language>
    <item>
      <title>Release by tagging on Vercel</title>
      <dc:creator>Damian Świstowski</dc:creator>
      <pubDate>Mon, 05 Sep 2022 01:25:55 +0000</pubDate>
      <link>https://dev.to/journeyman/release-by-tagging-on-vercel-4o1m</link>
      <guid>https://dev.to/journeyman/release-by-tagging-on-vercel-4o1m</guid>
      <description>&lt;h2&gt;
  
  
  Where is the problem?
&lt;/h2&gt;

&lt;p&gt;I like to have my project configured to have a staging build on which I run all my acceptance tests, close to production configuration, just before the production release. &lt;/p&gt;

&lt;p&gt;To achieve it, my staging build represents the current &lt;code&gt;HEAD&lt;/code&gt; of the project's &lt;code&gt;main&lt;/code&gt; branch. After running, the acceptance tests branch is tagged and released to production.&lt;/p&gt;

&lt;p&gt;The default configuration for the project on &lt;a href="https://vercel.com" rel="noopener noreferrer"&gt;vercel.com&lt;/a&gt; releases the main branch to production with every commit. It is easy to configure the second branch for staging build, by adding &lt;code&gt;staging&lt;/code&gt; branch and domain configuration for it: &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%2Fa3sxg9i0zit5hzgbjc4t.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%2Fa3sxg9i0zit5hzgbjc4t.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this configuration, the head of the &lt;code&gt;main&lt;/code&gt; branch will be released to &lt;a href="https://vercel-release-by-tag.vercel.app/" rel="noopener noreferrer"&gt;https://vercel-release-by-tag.vercel.app/&lt;/a&gt;, and the changes of the &lt;code&gt;staging&lt;/code&gt; branch will be released to &lt;code&gt;https://staging-vercel-release-by-tag.vercel.app/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In order to release to production, one needs to merge the &lt;code&gt;staging&lt;/code&gt; branch to &lt;code&gt;main&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is an acceptable workflow, but you are not using the GitHub release page to keep track of changes between different production releases. Additionally, developers need to manage two branches, which is not optimal.&lt;/p&gt;

&lt;h2&gt;
  
  
  First try
&lt;/h2&gt;

&lt;p&gt;My first approach to solving problem with tagged releases was to use &lt;a href="https://vercel.com/guides/can-you-deploy-based-on-tags-releases-on-vercel" rel="noopener noreferrer"&gt;can you deploy based on tags releases on vercel&lt;/a&gt; guide. The proposed solution - is to create an unused branch and &lt;a href="https://vercel.com/docs/concepts/git/deploy-hooks" rel="noopener noreferrer"&gt;deploy hook&lt;/a&gt; to release this tag, which did not work for me. The deploy hooks are linked to the branch:&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%2Fonyo18r4dvoylc2br6da.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%2Fonyo18r4dvoylc2br6da.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And because of that link, they can release only code which is on a specific branch. Configuring a webhook to release the &lt;code&gt;staging&lt;/code&gt; branch will release that branch to the staging environment, I didn't find a way to change that behaviour.&lt;/p&gt;

&lt;h2&gt;
  
  
  Second try
&lt;/h2&gt;

&lt;p&gt;My second try to solve it was to move release to GitHub actions with &lt;a href="https://vercel.com/guides/how-can-i-use-github-actions-with-vercel" rel="noopener noreferrer"&gt;how can I use GitHub Actions with Vercel?&lt;/a&gt; guide.&lt;/p&gt;

&lt;p&gt;As a result i created &lt;code&gt;.github/workflows/deploy-prod.yml&lt;/code&gt; file with content:&lt;/p&gt;

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

name: Deploy to production
env:
  VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
  VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
on:
  push:
    tags:
      - 'v*'

jobs:
  Deploy-Production:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Install Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 16

      - name: install and release
        run: | 
          npm install --global vercel@latest
          vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
          vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
          vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}


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

&lt;/div&gt;

&lt;p&gt;This approach was not acceptable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build was done once in GitHub Action worker and build artefact need to be uploaded to Vercel, and this process was slower than building directly there.&lt;/li&gt;
&lt;li&gt;Prisma client was not generated correctly without additional configuration, because the build environment was different than the runtime.
The pros of this approach were it doesn't require creating an artificial branch. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final approach
&lt;/h2&gt;

&lt;p&gt;For the final solution, I decided to configure Vercel to build directly from the branch, but add workflow to make sure all the changes on the production branch are done automatically after applying the tag. &lt;/p&gt;

&lt;p&gt;To achieve it I created &lt;a href="https://github.com/dswistowski/vercel-release-by-tag/tree/production" rel="noopener noreferrer"&gt;production&lt;/a&gt; branch in my git repo and created for both &lt;code&gt;main&lt;/code&gt; and &lt;code&gt;production&lt;/code&gt; protection rules:&lt;br&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%2Fjcypdd4191tgdrfmpibx.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%2Fjcypdd4191tgdrfmpibx.png" alt="Image description"&gt;&lt;/a&gt;.&lt;br&gt;
Protection makes sure the &lt;code&gt;production&lt;/code&gt; branch will be not deleted by accident after merging it to a different branch.&lt;/p&gt;

&lt;p&gt;After that, I configured Vercel to release production code from the &lt;code&gt;production&lt;/code&gt; branch (settings -&amp;gt; git)&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%2Fwybknmcfuoumfbh6fcud.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%2Fwybknmcfuoumfbh6fcud.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And to release &lt;code&gt;main&lt;/code&gt; branch to &lt;code&gt;staging&lt;/code&gt; domain (settings-&amp;gt;domain):&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%2Fev58dmun5w2stigcu92l.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%2Fev58dmun5w2stigcu92l.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the final piece is to update &lt;code&gt;production&lt;/code&gt; branch on tag creation. The easies way is to create GitHub Action:&lt;/p&gt;

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

name: Deploy to production
on:
  push:
    tags:
      - 'v*'

jobs:
  Deploy-Production:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Release to production
        run: |
          git push origin HEAD:production -f


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;git push origin HEAD:production -f&lt;/code&gt; command will force an update current &lt;code&gt;production&lt;/code&gt; branch with the currently tagged commit (because the action is executed only on tags starting with &lt;code&gt;v&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Created process:
&lt;/h3&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%2Ft0pz7oaajitjzaub2v9f.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%2Ft0pz7oaajitjzaub2v9f.png" alt="workflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;This solution assumes workflow when the team works on the &lt;code&gt;main&lt;/code&gt; branch and the &lt;code&gt;production&lt;/code&gt; is updated only by action after tagging. It's possible to lock the ability to update the &lt;code&gt;production&lt;/code&gt; branch by accident by adding a pull request requirement to the branch protection rule, creating a bot account with &lt;code&gt;bypass branch protections&lt;/code&gt; right for this branch and using the token of that account in GitHub action to authorise git access. &lt;/p&gt;

&lt;p&gt;The second way of defence against accidental release of production is to configure &lt;a href="https://vercel.com/docs/concepts/projects/overview#ignored-build-step" rel="noopener noreferrer"&gt;ignored build step&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Script similar to:&lt;/p&gt;

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

#!/bin/bash

echo "VERCEL_GIT_COMMIT_REF: $VERCEL_GIT_COMMIT_REF"

if [[ "$VERCEL_GIT_COMMIT_REF" == "main" ]]; then
  echo "✅ - Staging build can proceed"
  exit 1;
elif [[ "$VERCEL_GIT_COMMIT_REF" == "production" &amp;amp;&amp;amp; $(git name-rev --name-only --tags HEAD) != "undefined"  ]]; then
  echo "✅ - Production build can proceed"
  exit 1;
else
  # Don't build
  echo "🛑 - Build cancelled"
  exit 0;
fi


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

&lt;/div&gt;

</description>
      <category>vercel</category>
      <category>github</category>
      <category>cicd</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
