<?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: Stijn Van Asschodt</title>
    <description>The latest articles on DEV Community by Stijn Van Asschodt (@stijnva).</description>
    <link>https://dev.to/stijnva</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%2F336530%2Fe74ea2f8-e56c-48cf-b190-e4503b1e25c0.jpg</url>
      <title>DEV Community: Stijn Van Asschodt</title>
      <link>https://dev.to/stijnva</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stijnva"/>
    <language>en</language>
    <item>
      <title>Semantic versioning in JavaScript projects made easy</title>
      <dc:creator>Stijn Van Asschodt</dc:creator>
      <pubDate>Sat, 23 May 2020 16:16:58 +0000</pubDate>
      <link>https://dev.to/stijnva/semantic-versioning-in-javascript-projects-made-easy-3h63</link>
      <guid>https://dev.to/stijnva/semantic-versioning-in-javascript-projects-made-easy-3h63</guid>
      <description>&lt;p&gt;If you've used a package manager like npm or yarn before, you're probably familiar with a versioning format like X.Y.Z, where X, Y, and Z each represent a number, separated by dots. But what do those numbers mean?&lt;/p&gt;

&lt;p&gt;This versioning format is called &lt;a href="https://semver.org/" rel="noopener noreferrer"&gt;Semantic Versioning&lt;/a&gt; (or SemVer for short). Those three numbers correspond to: &lt;code&gt;&amp;lt;MAJOR&amp;gt;.&amp;lt;MINOR&amp;gt;.&amp;lt;PATCH&amp;gt;&lt;/code&gt;. Updating the major version means introducing a breaking change, the minor version is incremented when adding a new feature and the patch version is increased when including backward-compatible bug fixes. Increasing the version number (often called "bumping") also requires an update of the project's changelog. However, managing this manually for every release seems like a tedious task. After all, a developer most likely prefers writing code over documentation. Luckily, there are some tools to help automate this!&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠 Tools
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/conventional-changelog/standard-version" rel="noopener noreferrer"&gt;Standard version&lt;/a&gt; is a utility that takes care of all these versioning steps. It bumps the version, writes the changes to the changelog, and creates a git tag with the new version. It requires &lt;a href="https://www.conventionalcommits.org/en/v1.0.0/" rel="noopener noreferrer"&gt;conventional commit&lt;/a&gt; messages when committing, meaning all commit messages should follow a specific pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;type&amp;gt;[optional scope]: &amp;lt;description&amp;gt;

[optional body]

[optional footer]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;fix:&lt;/code&gt; and &lt;code&gt;feat:&lt;/code&gt; types correlate to the &lt;code&gt;PATCH&lt;/code&gt; and &lt;code&gt;MINOR&lt;/code&gt; version respectively. Adding a &lt;code&gt;BREAKING CHANGE:&lt;/code&gt; prefix to the body or footer of the commit message indicates a bump of the &lt;code&gt;MAJOR&lt;/code&gt; version.&lt;/p&gt;

&lt;p&gt;But how can you make sure contributors stick to this format, to prevent standard version from breaking?&lt;br&gt;
Similar to how a linter like &lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;eslint&lt;/a&gt; can be used to analyze your code, a tool like &lt;a href="https://github.com/conventional-changelog/commitlint" rel="noopener noreferrer"&gt;commitlint&lt;/a&gt; can be used to analyze your commit messages. By adding commitlint as a commit-msg git hook, all commit messages can be evaluated against a predefined config, ahead of the actual commit. So if the linter throws an error, the commit fails. An easy way to create those git hooks, is by using a helper like &lt;a href="https://github.com/typicode/husky" rel="noopener noreferrer"&gt;husky&lt;/a&gt;, which allows you to define your hooks directly inside the &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Additionally, using an interactive CLI like &lt;a href="https://github.com/commitizen/cz-cli" rel="noopener noreferrer"&gt;commitizen&lt;/a&gt;, simplifies writing the commit messages in the conventional commit format by asking questions about your changes and using your answers to structure the message.&lt;/p&gt;
&lt;h2&gt;
  
  
  💿 Setup
&lt;/h2&gt;

&lt;p&gt;Install all the necessary tools.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; standard-version commitizen @commitlint/&lt;span class="o"&gt;{&lt;/span&gt;cli,config-conventional&lt;span class="o"&gt;}&lt;/span&gt; husky
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;commitlint.config.js&lt;/code&gt; file in the root of the project. This file defines the rules that all commit messages should follow. By extending the conventional commit config, created by the commitlint team, all conventional commit rules will be added to the config.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@commitlint/config-conventional&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure the hook in the &lt;code&gt;package.json&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"husky"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"commit-msg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"commitlint -E HUSKY_GIT_PARAMS"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A commit not following the conventional commit pattern, will now fail and give appropriate feedback regarding what caused the error:&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;$git&lt;/span&gt; commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"non-conventional commit"&lt;/span&gt;
husky &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; commit-msg &lt;span class="o"&gt;(&lt;/span&gt;node v10.15.3&lt;span class="o"&gt;)&lt;/span&gt;
⧗   input: non-conventional commit
✖   subject may not be empty &lt;span class="o"&gt;[&lt;/span&gt;subject-empty]
✖   &lt;span class="nb"&gt;type &lt;/span&gt;may not be empty &lt;span class="o"&gt;[&lt;/span&gt;type-empty]

✖   found 2 problems, 0 warnings
ⓘ   Get &lt;span class="nb"&gt;help&lt;/span&gt;: https://github.com/conventional-changelog/commitlint/#what-is-commitlint

husky &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; commit-msg hook failed &lt;span class="o"&gt;(&lt;/span&gt;add &lt;span class="nt"&gt;--no-verify&lt;/span&gt; to bypass&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, initialize the conventional changelog adapter to make the repo commitizen-friendly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx 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;Add 2 scripts to the &lt;code&gt;package.json&lt;/code&gt;: one to run the commitizen cli and one for standard-version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git-cz"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"release"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"standard-version"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  💻 Usage
&lt;/h2&gt;

&lt;p&gt;Now, when using &lt;code&gt;npm run cm&lt;/code&gt; to commit, commitizen's cli will be shown.  It asks a series of questions about the changes you're committing and builds the message based on the provided answers. For example, committing a new feature looks like this:&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%2Fi%2Fphgbekfey5wft5m2r9jq.gif" 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%2Fi%2Fphgbekfey5wft5m2r9jq.gif" alt="commitizen cli example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When everything is ready for a new release, use standard-version to update the version number, changelog and create the git tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Standard version's output shows the bumping of the minor version to 1.1.0, as expected when committing a feature, and that a correct git tag was created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;✔ bumping version &lt;span class="k"&gt;in &lt;/span&gt;package.json from 1.0.0 to 1.1.0
✔ outputting changes to CHANGELOG.md
✔ committing package.json and CHANGELOG.md
husky &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; commit-msg &lt;span class="o"&gt;(&lt;/span&gt;node v10.15.3&lt;span class="o"&gt;)&lt;/span&gt;

✔ tagging release v1.1.0
ℹ Run &lt;span class="sb"&gt;`&lt;/span&gt;git push &lt;span class="nt"&gt;--follow-tags&lt;/span&gt; origin master &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm publish&lt;span class="sb"&gt;`&lt;/span&gt; to publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The outputted changes to the &lt;code&gt;CHANGELOG.md&lt;/code&gt; look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Changelog&lt;/span&gt;

All notable changes to this project will be documented in this file. See &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;standard-version&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://github.com/conventional-changelog/standard-version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; for commit guidelines.

&lt;span class="gu"&gt;## 1.1.0 (2020-04-13)&lt;/span&gt;&lt;span class="sb"&gt;


&lt;/span&gt;&lt;span class="gu"&gt;### Features&lt;/span&gt;
&lt;span class="p"&gt;
*&lt;/span&gt; short desc, added to changelog (&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;cd9dbc9&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://github.com/Hzunax/semantic-versioning-example/commit/cd9dbc9627b7fc64ba0490e495fd71686a604e57&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each &lt;code&gt;fix&lt;/code&gt;, &lt;code&gt;feat&lt;/code&gt;, or &lt;code&gt;BREAKING CHANGE&lt;/code&gt; commit will show up in the changelog with its short description and a link to the commit on the remote.&lt;/p&gt;

&lt;p&gt;Standard version also takes care of committing these changes (with a conventional commit message), so all that's left to do is push the changes to the remote and we're done!&lt;/p&gt;

&lt;h2&gt;
  
  
  📖 Further reading
&lt;/h2&gt;

&lt;p&gt;I made an &lt;a href="https://github.com/Hzunax/semantic-versioning-example" rel="noopener noreferrer"&gt;example setup&lt;/a&gt; where I use the tools described in this post. Feel free to check out the commit messages and how they are represented in the changelog.&lt;/p&gt;

&lt;p&gt;For more complex configurations and more detailed information on the tools and concepts used in this post, check out the links below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.conventionalcommits.org/en/v1.0.0/" rel="noopener noreferrer"&gt;Conventional commits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://semver.org/" rel="noopener noreferrer"&gt;SemVer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/commitizen/cz-cli" rel="noopener noreferrer"&gt;Commitizen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/conventional-changelog/standard-version" rel="noopener noreferrer"&gt;Standard version&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://commitlint.js.org/#/" rel="noopener noreferrer"&gt;Commitlint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/typicode/husky" rel="noopener noreferrer"&gt;Husky&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>productivity</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
