When doing continuous delivery, it makes sense to automate the release reporting process by automatically generate a changelog. The purpose of a changelog is to document all changes in an app using proper versioning. I have been working with firms where this release reporting process has been such a manual and tedious process that it has created too much overhead to make continuous delivery possible. For this reason, having a way to automatically document changes in your app can be a complete game-changer for your team – and maybe even your company.
When versioning apps a version number is constructed of a major, minor and patch part as:
A major version release is a breaking change in a library, meaning the clients will need to adapt to use this version. In an user-facing application, the definition of a major release is vague, because there are no technical clients to the app, only users. So a breaking change would be a radical change to the user experience, not just a change in the public API.
A minor version release is a non-breaking feature update to the system, such as adding a new feature.
A patch version release is a bugfix that is not adding any new features to the code, just fixing existing.
Angular Git Conventions
If you take a look at how the Angular team has created their changelog, you will see that this is generated using the following Git conventions:
A feature is the introduction of new behavior in the system, which should increase the version with a minor release (if it is non-breaking).
A feature should follow the following Git commit message:
feat(scope): *Commit message*
The definition of a breaking change is not crystal clear but I express it as:
A breaking change is a backward incompatible change that either alters the user experience drastically (for user-facing software) or changes the public API in a way that clients will need to adapt.
If the feature is a breaking change, it should increase the major version number. As default, when you do a npm install, it will automatically update the minor version, so if you are not increasing the major version on non-backward compatible changes, the clients of a library will break.
A note here is that, if some software is in alpha (not complete), then there are low expectations of the backward compatibility, as there tend to be huge backward incompatible changes at this stage in the development process.
For breaking changes the commit message should start with BREAKING CHANGE, so it follows the Git commit message:
feat(scope): *Commit message* BREAKING CHANGE: *Description of breaking change*
A fix is a correction of a defect for making the program work according to the acceptance criteria. A fix shouldn’t alter any existing behavior but only make the program work as intended.
A bugfix should follow the following Git commit message:
fix(scope): *Commit message*
A chore is some task that is neither a feature or bugfix but is simply cleaning up the code.
A chore should follow the following Git commit message:
chore(scope): *Commit message*
Always rebase and squash commits when doing pull requests
As a general rule, a pull request should only contain one commit. For this reason, all commits in a pull request should be squashed to one when merging. The exception here is if you pull request contains multiple features/fixes (ideally it should be split up in multiple PRs).
So if your pull request contains multiple commits first squash them into one by doing:
git rebase origin master -i
Here you choose squash for all commits except the one at the top. You can also rename the commit message if you need to.
Tools for Generating Changelog
Both of the frameworks are based on the same Git conventions for updating version and generate the changelog. The difference is that semantic-release will publish your changelog automatically to the remote Git repository where standard-version will stage the change locally in the Git repository and the version update will need to be pushed manually.
Both frameworks can make sense, standard-version can be beneficial if you want to review and correct the versioning before it is published.
Generate CHANGELOG using standard-version
First, you need to install standard version with:
npm i -g standard-version
Version number and changelog will automatically be generated from Git commit messages with:
This will update the version in package.json and generate CHANGELOG.md as well as creating a tag for the version number on the Git commit.
The version update, changelog and the Git version tag can be pushed to the remote using:
git push --follow-tags
Where does this fit in the development workflow?
The generation of the changelog should happen automatically as the branch is merged into the master. The CI server should automatically create the changelog, commit it and push it to the remote git repository. This way the team doesn’t have to manage the versioning manually, except when a release should be marked as a major release. When doing this you simply specify the major number in package.json’s version property.
We discussed why versioning software and keeping a changelog is important, not just for libraries but also for applications. We had a look at the semantic versioning conventions and the Angular Git conventions for automatically enforcing semantic versioning using a versioning tool. We looked at the tool standard-version and saw how to version and generate a changelog. Lastly, this versioning process should be automated as part of the CI pipeline, when new code is committed to the master branch, for ensuring all this is enforced by only following correct Git conventions.