On this page
Semantic Versioning (SemVer) in release pipelines
Semantic Versioning (SemVer) is a formal convention for assigning version numbers to software releases. It dictates how version numbers reflect the nature of underlying code changes, enabling automated dependency resolution.
Introduction
Semantic Versioning (SemVer) dictates a specific structure for version numbers: MAJOR.MINOR.PATCH (e.g., 1.4.2). The specification defines strict rules for incrementing each number based on the backward compatibility of the release. This allows developers and automated systems to gauge the risk of an update without reading the changelog.
Mental Model
Think of a version number as a strict contract. The PATCH number is a spelling correction in the contract. The MINOR number adds a new clause to the contract without changing existing ones. The MAJOR number rewrites a clause, invalidating previous agreements.
Algorithms/Resolution
The rules for incrementing version numbers are absolute:
- Increment the
MAJORversion when you make incompatible API changes. - Increment the
MINORversion when you add functionality in a backward-compatible manner. - Increment the
PATCHversion when you make backward-compatible bug fixes.
When a MAJOR version increments, the MINOR and PATCH versions reset to zero. When a MINOR version increments, the PATCH version resets to zero.
A pre-release version appends a hyphen and a series of dot-separated identifiers to the normal version (e.g., 1.0.0-alpha.1). Pre-releases have lower precedence than the associated normal version.
Build metadata appends a plus sign and identifiers (e.g., 1.0.0+20130313144700). Build metadata does not affect version precedence.
Semantics
Version 0.y.z is for initial development. The public API is unstable, and anything can change at any time.
Version 1.0.0 defines the public API. The way the version number increments after this release depends entirely on this public API and how it changes.
In release pipelines, SemVer drives automation. Package managers resolve dependencies based on version constraints. A constraint like ^1.2.3 permits updates to 1.2.4 or 1.8.0, but rejects 2.0.0, trusting the author to follow SemVer rules.
Failure Modes
Breaking changes in minor updates destroy trust. If a developer increments the MINOR version while removing an existing API endpoint, automated deployment pipelines that pull the latest minor update will break production systems.
Marketing dictates version numbers. If a product team forces a jump to version 2.0.0 for a major marketing launch, despite zero breaking API changes, they violate the specification.
Dependency hell blocks upgrades. If Library A requires Library C at exactly 1.0.0, and Library B requires Library C at exactly 2.0.0, an application cannot use Library A and Library B simultaneously.
Security
Vulnerability fixes require immediate deployment. SemVer dictates that a security patch that maintains backward compatibility must bump the PATCH version.
Automated dependency scanners rely on SemVer to identify vulnerable packages. If a maintainer releases a security fix under a new MAJOR version to bundle other breaking changes, users constrained to the old MAJOR version remain vulnerable. Maintainers must backport security fixes to older supported MAJOR branches.
Operational Guidance
Automate versioning using conventional commits. Tools evaluate commit messages formatted as feat: ..., fix: ..., or BREAKING CHANGE: ... to calculate the next version number and generate the changelog automatically during the CI/CD run.
Tag releases in version control. The deployment pipeline must tag the Git commit with the exact SemVer string upon a successful production deployment.
Never reuse a version number. If a deployment of 1.2.3 fails or contains a critical flaw, do not delete the tag and release a fixed 1.2.3. Release 1.2.4 instead.
Diagnostics
Compare the generated changelog against the version bump. If a PATCH release contains commits tagged as new features, the automation or the developer violated SemVer.
Analyze dependency resolution logs. When a build fails due to a dependency conflict, package manager logs reveal which constraints block the update.
Related topics
Sources & further reading
- Semantic Versioning 2.0.0 - Tom Preston-Werner