If you’ve been following the recent Angular release canidates you can’t help but admire the changelog they are able to produce. Each version published has a nicely formated list of bugs, features, and breaking changes. How they were able to generate this type of changelog really interested me into digging deeper into their process and conventions. It turns out, implementing something like this into your workflow is actually quite simple.

Standarizing Commit Messages

The first step is to start utilizing a convention when commiting changes to your codebase. The easiest way is to use the conventions created by the AngularJS team.

A more readable form of this can be found from Angular Material team’s Code Convention Guidelines. At a minimum, each commit message contains a type, scope and subject. In the following format:

1
<type>(<scope>): <subject>

Add Tooling

Making sure we commit changes using this format can be teadius at first. To make life easier add Commitizen as a development dependency. This provides a command line utlity that will walk you through each portion of the commit message.

Install commitizen

1
yarn add commitizen -D

Add conventional-cz

1
yarn add cz-conventional-changelog -D

Update package.json
First add a new script named commit which executes git-cz (Commitizen)

1
2
3
4
scripts : {
"commit": "git-cz"
...
}

Then add an additional block called config

1
2
3
4
5
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
}

Stage your changes by running git add . followed by npm run commit.

Success!

Preventing Poor Commit Messages

Having this tooling is great, but what about that one developer that just doesn’t seem to get it and is stuck in their ways? Thankfully, preventing commits that do not meet the convention is simple to do by installing a git hook. But to be honest, I’ve never configured a Git hook. Thankfully, Husky makes configuration painless.

First install Husky:

1
yarn add husky -D

Next install validate-commit-msg

1
yarn add validate-commit-msg -D

Update your package.json scripts:

1
2
3
scripts: {
"commitmsg": "validate-commit-msg"
}

Now any commit messages that do not follow the convention will error to the developer.

Generating a Changlog and Versioning

Now that our project is setup lets see the added benefits this provides. To kick off the next step we are going to install standard-version. This plugin not only will generate the proper version for our project, but it will also create a change log with proper commit hashes, and issue numbers.

Install standard-version

1
yarn add standard-version -D

Update your package.json scripts:

1
2
3
scripts: {
"release": "standard-version"
}

Run npm run release. This will examine your Git history and based off your commits generate the proper version and a CHANGELOG.md.


Demoing This Process to Your Team

To help demo how this would work in the real world, I’ve setup a repository with everything configured. First fork this repository.

With the newly forked project lets enable Issue tracking. This will give us a feel for how this would work when we collaborate on a real project.

  • Open the project’s settings in GitHub and enable Features > Issues
  • Create a new issue called feat: Implement Footer
  • Clone your forked repository
  • Verify you’re in the newly created directory and run npm install (or yarn)
  • Create a new branch by running git branch feat/footer
  • Open ./src/index.html and add a footer element
  • Save your changes
  • From the CLI run git add . followed by npm run commit

Follow the prompts adding, using the following information:

1
2
3
4
5
6
type:feature
scope: index
short description: added a footer
long description: <empty>
breaking changes: <empty>
issues closed: <enter your issue number ie. #1>

  • Push your changes to GitHub with git push
  • Next open a pull request and merge your changes in

Notice the CHANGELOG.md and package.json version are unchanged. The reason they haven’t been updated is because we need to first cut a release. Let’s do that now.

  • From your command line switch back to master by running git branch master
  • Pull in your latest changes by running git pull
  • Run npm run release

This runs standard-version which examines your commit history to properly update the CHANGELOG.md, version in package.json, and tags a branch in your repository.
Finally, run git push --follow-tags origin master to push your version changes and tag your repository with this version.

Beyond…

Checkout this great plugin for VSCode. It integrates with commitizen and provides a wizard like experience.

I haven’t actually tried this out yet, but to take things to the next level you could look into semantic-release. It promises fully automated packaging and releasing. Basically, what standard-version does, with the added benefit of integrations with GitHub and Travis CI.