Next.js, and Gatsby.js (which this blog is built on).
The next section dives deeper into how each of the tools work. Skip to TL;DR for installation instructions.
The first step for automated release notes to use consistent commit message and description formats. This allows the CHANGELOG.md generator to differentiate between commit types, whether a commit is related to an issue, and especially if the commit contains breaking changes.
Three parts make up our commit flow: (1) use Conventional Commit format, (2) enable easy Git hook integration with husky
, and (3) enforce commit message validation based on Conventional Commit rules.
Based on guidelines designed by the Angular team, Conventional Commits is a precise set of rules ensuring commit messages include important context and details easily consumed by others.
Read their documentation to learn about the format’s syntax and requirements, they are required for successful commit message validation.
Before adding custom linting rules for commit messages, let’s install husky
. Described as “Git hooks made easy”, this package allows easier setup of Git hooks through the package.json file, increasing visibility of development tools to outside eyes.
Husky works by automatically adding scripts in the .git folder, which plug into predefined hook functionality in Git. Upon execution of Git a command, Husky’s script will be called, which will in-turn call the scripts specified in the project’s package.json file.
The final step for commit message validation: linting. Using commitlint
in tandem with husky
allows easy integration of pre-made lint rules, specifically following Conventional Commit standards.
Bonus: Especially helpful for onboarding developers unfamiliar with Conventional Commit standards, commitizen
presents a command line wizard for pushing a Conventional-Commits-compatible commit message.
While not required, this helps discovery of more arguments and commits configuration types. It shines when needing to specify breaking changes or other less frequently used commit details.
Now the fun part. You’re following all the commit rules and guidelines established above, and want a CHANGELOG.md that you don’t have to type manually anymore… finally.
The package standard-version
does just that, and a whole lot more. It will:
All of this is done by standard-version
locally, leaving you to push the changes when you are ready. Allowing control over specific processes and verification of its outputs.
Alternative: semantic-release
An alternative to standard-version
is semantic-release
. Which one you choose depends on your development pipeline. If you prefer or need manual control of versioning, release notes, or other pieces then standard-version
is the right solution for you. If instead you have a complete CI/CD pipeline and don’t need granular control over versioning, sematic-release
may fit better.
npm init
npm i -D husky @commitlint/{config-conventional,cli,prompt} commitizen cz-conventional-changelog standard-version
// commitlint.config.js
module.exports = { extends: ["@commitlint/config-conventional"] };
scripts
key of your package.json:// package.json
"commit": "./node_modules/.bin/git-cz",
"release": "standard-version"
// package.json
"husky": {
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
// package.json
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
},
standard-version
config at end of package.json:This controls which headers are visible/hidden from generated CHANGELOG.md
// package.json
"standard-version": {
"types": [
{ "type": "chore", "section": "Others", "hidden": false },
{ "type": "revert", "section": "Reverts", "hidden": false },
{ "type": "fix", "section": "Bug Fixes", "hidden": false },
{ "type": "feat", "section": "Features", "hidden": false },
{ "type": "docs", "section": "Docs", "hidden": false },
{ "type": "style", "section": "Styling", "hidden": false },
{ "type": "refactor", "section": "Code Refactoring", "hidden": false },
{ "type": "perf", "section": "Performance Improvements", "hidden": false },
{ "type": "test", "section": "Tests", "hidden": false },
{ "type": "build", "section": "Build System", "hidden": false },
{ "type": "ci", "section": "CI", "hidden": false }
]
}
Test failed commit message:
First let’s ensure commit linting is functional. Make a change in your code, then commit with a (now invalid) message like: “saving changes”. You should see an error.
Commit proper message with tool:
Now, let’s do a proper commit by using our new command line tool: npm run commit
Commit linting is working and there is a fresh new commit in the repo’s history waiting to be effortlessly printed onto release notes using the new command, npm run release
.
-- --first-release
, so it looks like npm run release -- --first-release
.--dry-run
onto the command, like so: npm run release -- --first-release --dry-run
.standard-version
gives the Git command to copy + paste for pushing the shiny new CHANGELOG.md, bumped version numbers, and tagged release up to your remote repository host. ory host.