Semantic Versioning
How versioning works
Versioning is automated through semantic-release, a utility that analyzes commit messages during the CI pipeline and determines the next version number based on Semantic Versioning: <major>.<minor>.<patch>.
The plugin @semantic-release/commit-analyzer inspects commit headers to infer the release type. Each commit must include a type prefix (e.g., feat:, fix:) to be correctly interpreted.
Commit types and their impact
Major releases
- Triggered by
BREAKING CHANGE:in the commit body.
Minor releases
- Triggered by
feat:in the commit body.
Patch releases
- Triggered by:
fix:(bug fixes)docs:(documentation changes)refactor:,perf:,test:,ci:,build:(various small improvements and tooling updates)
The @semantic-release/git plugin updates the version field in package.json, commits release assets, and creates a tag for the new version:
{
"version": "<major>.<minor>.<patch>"
}
Handling multiple commits
When multiple commits are present in a release, the highest-impact change determines the release type. Examples:
- If the previous version was 1.2.0 and you commit
feat: new featureandfix: minor bug, the next version will be1.3.0(minor). - If you commit two
fix:changes, it results in a patch bump:1.3.1.
Configuring semantic-release
Semantic-release requires proper setup in your CI pipeline, package.json, and .releaserc.json.
CI configuration
The publish task must run on the default branch, without being tied to a tag (since semantic-release generates the tag itself):
publish:
stage: release
script:
- npm run build
- npm run semantic-release
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
package.json
Ensure the correct scripts and dev dependencies are defined:
{
"scripts": {
"semantic-release": "semantic-release"
},
"devDependencies": {
"@semantic-release/git": "10.0.1",
"semantic-release": "19.0.2"
}
}
.releaserc.json
This file defines plugins and release rules. It tells semantic-release how to interpret commit types and which files to include in the release commit:
{
"branches": ["master"],
"plugins": [
[
"@semantic-release/commit-analyzer",
{
"preset": "angular",
"releaseRules": [
{ "breaking": true, "release": "major" },
{ "type": "feat", "release": "minor" },
{ "type": "fix", "release": "patch" },
{ "type": "docs", "release": "patch" },
{ "type": "refactor", "release": "patch" },
{ "type": "style", "release": "patch" },
{ "type": "build", "release": "patch" },
{ "type": "ci", "release": "patch" },
{ "type": "test", "release": "patch" },
{ "type": "perf", "release": "patch" }
],
"parserOpts": {
"noteKeywords": ["BREAKING CHANGE", "BREAKING CHANGES"]
}
}
],
"@semantic-release/npm",
[
"@semantic-release/git",
{
"assets": ["package.json"],
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
]
]
}
Supporting tools for commits
To simplify writing properly formatted commits, consider using:
commitizer: Interactive CLI for writing commitscommitlint: Lints commit messages based on conventional rules.
These tools help enforce consistency and ensure semantic-release functions as expected.