<?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: Nir Galon</title>
    <description>The latest articles on DEV Community by Nir Galon (@nirgn975).</description>
    <link>https://dev.to/nirgn975</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%2F4545%2FoczRgifS.jpg</url>
      <title>DEV Community: Nir Galon</title>
      <link>https://dev.to/nirgn975</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nirgn975"/>
    <language>en</language>
    <item>
      <title>Releasing Software Is Hard! Is it?</title>
      <dc:creator>Nir Galon</dc:creator>
      <pubDate>Fri, 08 Jan 2021 19:59:50 +0000</pubDate>
      <link>https://dev.to/nirgn975/releasing-software-is-hard-is-it-2ip2</link>
      <guid>https://dev.to/nirgn975/releasing-software-is-hard-is-it-2ip2</guid>
      <description>&lt;p&gt;This article was originally published on &lt;a href="https://lifelongstudent.io/2020/12/releasing-software-is-hard" rel="noopener noreferrer"&gt;https://lifelongstudent.io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One of the things I always got frustrated with is software releases and versioning.&lt;/p&gt;

&lt;p&gt;In the old days, back when I started to work at my first job as a software engineer my team leader was handle all of the project management. It means he knew on what issue you're working at the moment, and when (in what version of the software) it should be merged and be released. To this day I think the versioning was just a random thing there - doesn't mean anything except for all of us to be on the same page when we talked about it or reference it.&lt;/p&gt;

&lt;p&gt;Bugs and features were pushed forward to next versions without any real systematic reasoning about it, and I knew something about it was off. That's when I opened up my browser and just start googling about the topic. I search and read a lot, and finally I ran into &lt;a href="https://semver.org" rel="noopener noreferrer"&gt;Semantic Versioning&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  1. Semantic Versioning
&lt;/h2&gt;

&lt;p&gt;Semantic Versioning (or &lt;a href="https://github.com/semver/semver" rel="noopener noreferrer"&gt;semver&lt;/a&gt;) is basically a simple set of rules and requirements that dictate how version numbers are assigned and incremented. In practice SemVer is probably similar to what you're already doing right now, but similar is worthless. Because without compliance to some sort of formal specification, version numbers are essentially useless for dependency management.&lt;/p&gt;

&lt;p&gt;Semantic Versioning authored back in 2011 and it's already widely used by the open source community. All the major open source projects embraced it, so it's at least worth reading the specification. Once you follow the semver specification your version numbers and the way they change convey meaning about the underlying code and what has been modified from one version to the next.&lt;/p&gt;

&lt;p&gt;If that's not convince you maybe the fact that the Semantic Versioning specification was originally authored by &lt;a href="https://github.com/mojombo" rel="noopener noreferrer"&gt;Tom Preston-Werner&lt;/a&gt; (cofounder of GitHub) will.&lt;/p&gt;

&lt;p&gt;So, if you're still reading this post I assume you're somewhat interested in semver. So go read the specification, it's short, concise, and translated to a lot of languages. I'll just mention the basics: A version format is &lt;code&gt;X.Y.Z&lt;/code&gt; (&lt;code&gt;Major.Minor.Patch&lt;/code&gt; respectively). The &lt;code&gt;Major&lt;/code&gt; is incremented if the API additions/changes are &lt;strong&gt;backwards incompatible&lt;/strong&gt; (i.e. breaking changes). The &lt;code&gt;Minor&lt;/code&gt; is incremented if the API additions/changes are &lt;strong&gt;backwards compatible&lt;/strong&gt;. And the &lt;code&gt;Patch&lt;/code&gt; is incremented if a bug fix &lt;strong&gt;not affecting&lt;/strong&gt; the API 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%2Flifelongstudent.io%2Fposts%2F2020%2Freleasing-software-is-hard%2Fsemver-summary.webp" 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%2Flifelongstudent.io%2Fposts%2F2020%2Freleasing-software-is-hard%2Fsemver-summary.webp" title="Semantic Versioning Summary" alt="Semantic Versioning Summary"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  2. Sounds Great, but..
&lt;/h2&gt;

&lt;p&gt;Semantic Versioning sounds great, but it present a new problem. Every release someone has to sit down, read the issues/pull requests and write a &lt;code&gt;changelog&lt;/code&gt; for that version, from that &lt;code&gt;changelog&lt;/code&gt; he should bump the version of the software accordingly. This sounds like a really tedious manual job. This alone kept me from really using SemVer for a long time.&lt;/p&gt;

&lt;p&gt;Until I found &lt;a href="https://github.com/semantic-release/semantic-release" rel="noopener noreferrer"&gt;semantic-release&lt;/a&gt;! Which is a tool to automates the whole package release workflow (determining the next version number, generating the release notes - &lt;code&gt;changelog&lt;/code&gt;, and publishing the package). This removes the immediate connection between human emotions and version numbers, strictly following the &lt;a href="http://semver.org" rel="noopener noreferrer"&gt;Semantic Versioning&lt;/a&gt; specification.&lt;/p&gt;

&lt;p&gt;To make our life even more simple we can use the &lt;a href="https://github.com/marketplace/actions/release-me#create-a-release" rel="noopener noreferrer"&gt;Release me!&lt;/a&gt; GitHub action which use &lt;a href="https://github.com/semantic-release/semantic-release" rel="noopener noreferrer"&gt;semantic-release&lt;/a&gt; under the hood.&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%2Flifelongstudent.io%2Fposts%2F2020%2Freleasing-software-is-hard%2Fautomate-all-the-things.webp" 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%2Flifelongstudent.io%2Fposts%2F2020%2Freleasing-software-is-hard%2Fautomate-all-the-things.webp" title="Automate All The Things" alt="Automate All The Things"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But how semantic-release knows what part of the version it should bump? It uses the commit messages to determine the type of changes in the codebase. So that means we need to adhere to a specific commit message format. By default the semantic-release follows the &lt;a href="https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines" rel="noopener noreferrer"&gt;Angular Commit Message Conventions&lt;/a&gt;, but you can change it with a &lt;code&gt;config&lt;/code&gt; file. We'll not change it for this post because this format is widely used by the open source community.&lt;/p&gt;

&lt;p&gt;I starting to get a feeling here we just kicking the ball to different places and not really have a solution to the problem. Because now we need to learn and manually write our commit messages in a specific format.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  3. Let's solve this once and for all
&lt;/h2&gt;

&lt;p&gt;You're sort of right. Our problem is still present, but those other problems were still present before we talked about them, we just didn't mention them. But fear not, &lt;a href="https://www.conventionalcommits.org" rel="noopener noreferrer"&gt;Conventional Commits&lt;/a&gt; to the rescue. The Conventional Commits specification is a convention on top of commit messages that provides a set of rules for creating an explicit commit history. And I know what you're thinking to yourself right now "another specification?!".&lt;/p&gt;

&lt;p&gt;Again, fear not my young padawan. &lt;a href="https://github.com/commitizen/cz-cli" rel="noopener noreferrer"&gt;commitizen&lt;/a&gt; - a command line utility will help us &lt;code&gt;commit&lt;/code&gt; and will guide us through every commit.&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%2Flifelongstudent.io%2Fposts%2F2020%2Freleasing-software-is-hard%2Fcommitizen-in-action.webp" 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%2Flifelongstudent.io%2Fposts%2F2020%2Freleasing-software-is-hard%2Fcommitizen-in-action.webp" title="Commitizen In Action" alt="Commitizen In Action"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, let's recap all the tools so far. If we'll use &lt;a href="https://github.com/commitizen/cz-cli" rel="noopener noreferrer"&gt;commitizen&lt;/a&gt; for &lt;code&gt;commit&lt;/code&gt;s, our commits messages will be in a format compatible with &lt;a href="https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines" rel="noopener noreferrer"&gt;Angular Commit Message Conventions&lt;/a&gt; and &lt;a href="https://www.conventionalcommits.org" rel="noopener noreferrer"&gt;Conventional Commits&lt;/a&gt;. If our commits are compatible with those formats &lt;a href="https://github.com/semantic-release/semantic-release" rel="noopener noreferrer"&gt;semantic-release&lt;/a&gt; will determining the next version number, generating the release notes, and publishing the package by the &lt;a href="https://semver.org" rel="noopener noreferrer"&gt;Semantic Versioning&lt;/a&gt; specification. Perfect!&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  4. Time to get our hands dirty
&lt;/h2&gt;

&lt;p&gt;Let's start by creating a simple &lt;code&gt;package.json&lt;/code&gt; file with npm in our project directory (let's call it &lt;code&gt;deweb&lt;/code&gt; because that's what the &lt;a href="https://namelix.com" rel="noopener noreferrer"&gt;namelix&lt;/a&gt; generator generate for us).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;deweb
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;deweb
&lt;span class="nv"&gt;$ &lt;/span&gt;git init
&lt;span class="nv"&gt;$ &lt;/span&gt;npm init
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;node_modules &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .gitignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are my configurations.&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%2Flifelongstudent.io%2Fposts%2F2020%2Freleasing-software-is-hard%2Finit-the-project.webp" 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%2Flifelongstudent.io%2Fposts%2F2020%2Freleasing-software-is-hard%2Finit-the-project.webp" title="Init The Project" alt="Init The Project"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we need to install &lt;a href="https://github.com/commitizen/cz-cli" rel="noopener noreferrer"&gt;commitizen&lt;/a&gt; and make our repo &lt;strong&gt;commitizen friendly&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;commitizen &lt;span class="nt"&gt;-g&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;commitizen init cz-conventional-changelog &lt;span class="nt"&gt;--save-dev&lt;/span&gt; &lt;span class="nt"&gt;--save-exact&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This just tells commitizen which adapter we actually want our contributors to use when they try to commit to this repo. And now you can use &lt;code&gt;git cz&lt;/code&gt; command instead of &lt;code&gt;git commit&lt;/code&gt; and the commitizen prompt will guide your through the commit message and &lt;code&gt;commit&lt;/code&gt; all the files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git cz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Flifelongstudent.io%2Fposts%2F2020%2Freleasing-software-is-hard%2Fcommit-with-commitizen.webp" 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%2Flifelongstudent.io%2Fposts%2F2020%2Freleasing-software-is-hard%2Fcommit-with-commitizen.webp" title="Commit With Commitizen" alt="Commit With Commitizen"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  5. Release the damn thing
&lt;/h2&gt;

&lt;p&gt;Now, we can use &lt;a href="https://github.com/semantic-release/semantic-release" rel="noopener noreferrer"&gt;semantic-release&lt;/a&gt; manually to automatically generate the release (I mean to write the command by hands every time we want to create a new release). But we can do it even better! We not do it automagically in GitHub actions? and even tie it up to GitHub milestones.&lt;/p&gt;

&lt;p&gt;So, let's create a GitHub action that uses the &lt;a href="https://github.com/marketplace/actions/release-me#create-a-release" rel="noopener noreferrer"&gt;Release me!&lt;/a&gt; action and run every time there is a milestones event on GitHub.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; .github/workflows
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; .github/workflows/cd.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this file you should copy the default template of a &lt;a href="https://docs.github.com/en/free-pro-team@latest/actions" rel="noopener noreferrer"&gt;GitHub action&lt;/a&gt;, and use the &lt;a href="https://github.com/marketplace/actions/release-me#create-a-release" rel="noopener noreferrer"&gt;release-me-action&lt;/a&gt;. Then you need to change the &lt;code&gt;on&lt;/code&gt; key on the top of the file &lt;code&gt;milestone&lt;/code&gt; and just when a milestone closed.&lt;br&gt;
&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;Continuous Deployment&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;milestone&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="nv"&gt;closed&lt;/span&gt;&lt;span class="pi"&gt;]&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&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;Create Release 🚀&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;ridedott/release-me-action@master&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;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&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;release-branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;["main"]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's commit the new file and push it to GitHub.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git cz
&lt;span class="nv"&gt;$ &lt;/span&gt;git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last thing we need to do is to create a milestone in GitHub, then look at the &lt;strong&gt;Actions&lt;/strong&gt; section and see our workflow, but we notice it doesn't run yet.&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%2Flifelongstudent.io%2Fposts%2F2020%2Freleasing-software-is-hard%2Fgithub-actions-when-milestone-is-open.webp" 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%2Flifelongstudent.io%2Fposts%2F2020%2Freleasing-software-is-hard%2Fgithub-actions-when-milestone-is-open.webp" title="GitHub Actions When Milestone Is Open" alt="GitHub Actions When Milestone Is Open"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then let's close the milestone (just hit the &lt;code&gt;close&lt;/code&gt; button), and refresh the &lt;strong&gt;Action&lt;/strong&gt; tab.&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%2Flifelongstudent.io%2Fposts%2F2020%2Freleasing-software-is-hard%2Fgithub-actions-after-milestone-closed.webp" 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%2Flifelongstudent.io%2Fposts%2F2020%2Freleasing-software-is-hard%2Fgithub-actions-after-milestone-closed.webp" title="GitHub Actions After Milestone Closed" alt="GitHub Actions After Milestone Closed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And when the workflow finish to run, let's open the releases page and see our new release (you can notice the action also created a &lt;code&gt;changelog.md&lt;/code&gt; file with all the changes, and it'll update this file with every release).&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%2Flifelongstudent.io%2Fposts%2F2020%2Freleasing-software-is-hard%2Fgithub-releases-after-action-completed.webp" 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%2Flifelongstudent.io%2Fposts%2F2020%2Freleasing-software-is-hard%2Fgithub-releases-after-action-completed.webp" title="GitHub Releases After Action Completed" alt="GitHub Releases After Action Completed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  6. Summary
&lt;/h2&gt;

&lt;p&gt;To recap, we now release our software automatically without any human intervention except to &lt;code&gt;close&lt;/code&gt; the milestone (we can easily change it on the GitHub workflow). Our commit messages are nicely organized with &lt;a href="https://github.com/commitizen/cz-cli" rel="noopener noreferrer"&gt;commitizen&lt;/a&gt; by the &lt;a href="https://www.conventionalcommits.org" rel="noopener noreferrer"&gt;Conventional Commits&lt;/a&gt; specification. Our release happen automatically with GitHub actions. And the release itself is generated with &lt;a href="https://github.com/semantic-release/semantic-release" rel="noopener noreferrer"&gt;semantic-release&lt;/a&gt; -the next version number, the release notes and the publishing itself to GitHub releases.&lt;/p&gt;

&lt;p&gt;If you want to see it all happen or maybe got stuck a long the way, just go over to the &lt;a href="https://github.com/nirgn975/deweb" rel="noopener noreferrer"&gt;deweb&lt;/a&gt; repo on GitHub and check out the code.&lt;/p&gt;

</description>
      <category>semver</category>
      <category>conventionalcommits</category>
      <category>commitizen</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
