Commit Standard and Semantic Versioning for any project
Tags: node, javascript, git, github
Published: 2020-08-04 11:33:43

One of the biggest problems working with any project is handling commit messages and determinate the next version number of our releases.

We'll add to our project a tool that provides an easy set of rules for creating different commit messages like features, fixes, and breaking changes.

```bash
refactor!: drop support for Node 6
docs: correct spelling of CHANGELOG
feat(lang): add polish language
fix: correct minor typos in code
```

We'll use these commit messages to determine the next version number, generating the release notes, and publishing the packages. As a BONUS, we'll execute this process using Github Actions.

This removes the immediate connection between human emotions and version numbers, strictly following the Semantic Versioning specification.

## Prerequisites

```bash
Node 10+
```

## Tools

### [Sematic Versioning 2.0.0](https://semver.org/)

Given a version number MAJOR.MINOR.PATCH, increment the:
MAJOR version when you make incompatible API changes,
MINOR version when you add functionality in a backward-compatible manner, and
PATCH version when you make backward-compatible bug fixes.

### [Commitizen](https://github.com/commitizen/cz-cli)

Fill the required commit field at commit time.

![Commit fields](https://dev-to-uploads.s3.amazonaws.com/i/7mlok3v8wclpx28zu0od.png)

### [Conventional changelog](https://github.com/conventional-changelog/conventional-changelog)

Generate changelogs and release notes from a project's commit messages and metadata.

### [Husky](https://www.npmjs.com/package/husky)

To check bad commits.

### [Commitlint](https://commitlint.js.org/#/)

It helps your team adhering to a commit convention. By supporting npm-installed configurations, it makes sharing of commit conventions easy.

### [Commitlint - Config conventional](https://www.npmjs.com/package/@commitlint/config-conventional)

Configuration for Commitlint to enforce conventional commits.

![Check ugly commits](https://dev-to-uploads.s3.amazonaws.com/i/f4g7bgte9ql81ejd0ucf.png)

### [Sematic Release](https://github.com/semantic-release/semantic-release)

Automates the whole package release workflow, including determining the next version number, generating the release notes, and publishing the package.

## Dependencies

Install global dependencies

```bash
npm i -g commitizen
npm i -D husky @commitlint/cli @commitlint/config-conventional @semantic-release/git @semantic-release/changelog @semantic-release/commit-analyzer @semantic-release/release-notes-generator @semantic-release/npm
```

## Steps

- Execute **commitizen init cz-conventional-changelog -D -E** this will add the dependencies of cz-conventional-changelog and update our package with the configuration:

```bash
"config": {
  "commitizen": {
    "path": "./node_modules/cz-conventional-changelog"
  }
}
```

- Update *package.json* to Husky check if the commits follow the conventional standard using commitlint

```bash
"husky": {
  "hooks": {
    "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
  }
},
"commitlint": {
  "extends": [
    "@commitlint/config-conventional"
  ]
}
```

Now you can check using **git cz** to commit instead of *git commit -m "uggly message"*

## Sematic versioning with Github Action

- Create a Personal Access Token with "Repo" permissions
```bash
In Github → Settings → Developer settings → Personal access tokens → Generate new token
```
- Create a new key GH_TOKEN and the value of the new generated token
```bash
In your Repository → Settings → Secrets → New secret
```
- Update the *package.json* with this code

```bash
"plugins": [
  "@semantic-release/commit-analyzer",
  "@semantic-release/release-notes-generator",
  "@semantic-release/changelog",
  "@semantic-release/github",
  "@semantic-release/npm",
  "@semantic-release/git"
],
"release": {
  "prepare": [
    "@semantic-release/changelog",
    "@semantic-release/npm",
    {
      "path": "@semantic-release/git",
      "assets": [
        "package.json",
        "package-lock.json",
        "CHANGELOG.md"
      ],
      "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
    }
  ]
},
```

- Create a folder in the root of your project .github/workflows with this code.

```bash
name: Semantic release

on:
  push:
    branches:
      - master
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Setup Node.js
        uses: actions/setup-node@v1
        with:
          node-version: 12
      - name: Install dependencies
        run: npm install
      - name: Semantic release
        env:
          GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
        run: npx semantic-release
```

- Now, push your changes to your repo and see in actions.

The command **npx semantic-release** will analize our commits, generate release notes, update our changelog and generate the release in Github with the information in commits and finally update the version in our *package.json*.

Feel free to ask any questions you had.

Bye!