Use "cz-vinyl" package to commit more readable messages with one command
Tags: git, programming, tutorial, productivity
Published: 2023-04-20 12:30:58

Commit messages are very important to understand what work is done on the specific commit, and also for much more important tools.

You can use your commit messages to automate JIRA flows (or other project management framework..), or to automatically upgrade your package version according to the commit message.
For example, you could tag your JIRA ticket ID in your commit message to help others to understand what is the scope of your commit.

You can follow this guide: https://semver.org/ and infer from your commit messages, what should be your next package version. For example, if someone on your team commits some breaking change code, you'll probably want to upgrade your "Major" version (1.0.0 --> 2.0.0).

## How
To start formatting your commit messages, you need to install 2 packages: `npm i -D commitizen cz-vinyl`.
"[Commitizen](https://www.npmjs.com/package/commitizen)" is a tool which allows to get prompted in the command-line-interface to fill some data regarding your commit message, and then get the formatted commit message. "[cz-vinyl](https://www.npmjs.com/package/cz-vinyl)" is an adapter for "Commitizen" which will format your message according to some guidelines.

In your project, create `.cz.json` file with the following content:
```json
{
	"path": "cz-vinyl"
}
```

You can already start using the adapter by running `npx cz`. But we are gonna do it in more elegant way.

We will allow the developers to use the adapter by running `git cmt` (which is more intuitive command to make a commit message). To do so, create `.gitconfig` file with the following content:
```
[alias]
    cmt = "!npx cz"
```

This will create an alias for `git`. Once a developer runs `git cmt`, it will be an alias for running `npx cz`. This won't work out of the box for security aspects, so a developer must run `git config --local include.path ../.gitconfig`. But this makes it cumbersome of course. So we can make it automatically work by adding a "package.json" hook script, which will be running once a developer installs your project: `"prepare": "git config --local include.path ../.gitconfig"`.

You can also configure the adapter, according to your needs with a configuration file, `czvinyl.config.cjs` (or other name according to the documentation):
```js
const czvinylConfig = {
	headerFormat: '{type}: {emoji} {subject}',
	skipTicketId: true,
};

module.exports = czvinylConfig;
```

As a result, you can get a commit message header like: `
chore: [ESS-2234] 🤖 remove Depcheck`.

You can also integrate a GitHub workflow to automatically upgrade your package version according to your commit message:
```yaml
name: Semantic Release

on:
    push:
        branches: [main]

jobs:
    release:
        name: Release version
        permissions:
            contents: write

        runs-on: ubuntu-latest
        steps:
            - name: Setup Node environment
              uses: Exlint/node-environment@v1.2.6
              with:
                  should-cache: false
                  node-version: 18.15.0
                  package-manager: pnpm
                  package-manager-version: 8.3.1

            - name: Setup Node
              uses: actions/setup-node@v3
              with:
                  node-version: 14

            - name: Semantic Release
              uses: cycjimmy/semantic-release-action@v3.4.2
              with:
                  extra_plugins: |
                      @semantic-release/changelog
                      @semantic-release/commit-analyzer
                      @semantic-release/git
                      @semantic-release/npm
              env:
                  GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
```

And a `release.config.cjs` file:
```js
const config = {
	branches: ['main'],
	repositoryUrl: 'git+https://github.com/Exlint/cz-vinyl',
	plugins: [
		[
			'@semantic-release/commit-analyzer',
			{
				preset: 'angular',
				releaseRules: [
					{ type: 'feat', release: 'minor' },
					{ type: 'fix', release: 'patch' },
					{ type: 'perf', release: 'patch' },
					{ type: 'breaking', release: 'major' },
				],
			},
		],
		'@semantic-release/release-notes-generator',
		'@semantic-release/changelog',
		'@semantic-release/npm',
		'@semantic-release/git',
		'@semantic-release/github',
	],
};

module.exports = config;
```