Semantic Release — The Version Bump That Skipped From v1.2.3 to v2.0.0
A 'fix:' commit that contained a breaking change bumped the major version.
20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.
- ✓Deep devops experience in a production environment
- ✓Familiarity with debugging, profiling, and performance analysis
- ✓Understanding of distributed systems and failure modes
Set up semantic-release in CI: npm install -g semantic-release. Configure with .releaserc file. Push conventional commits. semantic-release: 1) analyzes commits since last release, 2) determines version bump, 3) generates changelog, 4) creates git tag, 5) publishes to npm/PyPI/etc.
Imagine a robot that reads every commit message since the last release. If it finds 'feat: add payment module', it knows the version needs a minor bump (v1.2.3 → v1.3.0). If it finds 'fix: correct tax calculation', it's a patch (v1.2.3 → v1.2.4). If it finds 'BREAKING CHANGE:', it's a major version (v1.2.3 → v2.0.0). The robot creates a changelog, tags the release, and publishes — all without human intervention.
Semantic versioning (semver) is the convention: MAJOR.MINOR.PATCH. semantic-release automates the versioning decision based on commit messages. This eliminates human error in version bumps, ensures every merge to main can produce a release, and generates changelogs automatically. The key requirement: your team must use conventional commits. This guide covers setup, the incident where a mislabeled commit would have caused a silent major version bump, and how to configure semantic-release for your project.
Setting Up semantic-release
Install: npm install -g semantic-release or npm install --save-dev semantic-release.
Configure: create .releaserc (JSON or YAML) with branches, plugins, and publish options.
Plugins: @semantic-release/commit-analyzer (analyzes commits for version), @semantic-release/release-notes-generator (generates changelog), @semantic-release/npm (publishes to npm), @semantic-release/github (creates GitHub release), @semantic-release/git (commits changelog to repo).
CI setup: Add a semantic-release step to your CI pipeline that runs after tests pass on main. Use npx semantic-release with a GITHUB_TOKEN environment variable.
Dry run: npx semantic-release --dry-run shows the next version number and changelog without publishing.
GITHUB_TOKEN (not your personal token) with contents: write and pull-requests: write permissions. For npm publishing, configure NPM_TOKEN as a repository secret.@semantic-release/git plugin to commit the updated changelog and package.json version back to main. This keeps the repository in sync with published versions. For monorepos, use @semantic-release/monorepo or tools like changesets that handle multi-package versioning. The commit message linting should be a CI gate that runs on every PR — reject messages that don't follow conventional commits format.The 'Fix' Commit That Would Have Bumped v1.2.3 to v2.0.0
fix: rename processPayment to executePayment. 3. The commit message had no 'BREAKING CHANGE:' footer. 4. semantic-release would parse this as a patch (fix = patch). 5. The breaking API change would ship as v1.2.4. 6. All downstream packages depending on v1.2.3+ would break at next npm install. 7. The code reviewer noticed the breaking change and flagged it.feat!: rename processPayment to executePayment (the ! marks breaking change). 2. semantic-release correctly parsed this as a major version bump. 3. Added commitlint to CI to enforce conventional commit format. 4. Added a CI check: npx semantic-release --dry-run runs on every PR and shows the would-be version bump. 5. Educated the team: commit type determines version bump. Breaking changes MUST use ! or BREAKING CHANGE footer.- Commit type determines version bump: fix → patch, feat → minor, BREAKING → major.
- Use
!orBREAKING CHANGE:footer for breaking changes. - Add a CI check that shows the would-be version bump on every PR.
- Enforce conventional commit format with commitlint.
BREAKING CHANGE detection in CInpx semantic-release --dry-run to preview the version bump and changelogKey takeaways
! or BREAKING CHANGE: footer to mark breaking changes20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.
That's Git. Mark it forged?
3 min read · try the examples if you haven't