Home DevOps Semantic Release — The Version Bump That Skipped From v1.2.3 to v2.0.0
Advanced 3 min · July 07, 2026
Semantic Release: Automated Versioning and Changelogs

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.

N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.

Follow
Production
production tested
July 07, 2026
last updated
214
articles · all by Naren
Before you start⏱ 20 min
  • Deep devops experience in a production environment
  • Familiarity with debugging, profiling, and performance analysis
  • Understanding of distributed systems and failure modes
 ● Production Incident
Quick Answer

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.

✦ Definition~90s read
What is Semantic Release?

semantic-release is an automated tool that determines the next version number, generates changelogs, and publishes releases based on conventional commit messages. feat → minor, fix → patch, BREAKING CHANGE → major.

Imagine a robot that reads every commit message since the last release.
Plain-English First

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.

01_semantic_release_setup.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# Install semantic-release
npm install -g semantic-release

# Create config file
cat > .releaserc << 'EOF'
{
  "branches": ["main"],
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    "@semantic-release/npm",
    "@semantic-release/github"
  ]
}
EOF

# Dry run to preview
npx semantic-release --dry-run

# Run in CI (example: GitHub Actions step)
# - run: npx semantic-release
#   env:
#     GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
#     NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

# Verify the release version
npx semantic-release --dry-run 2>&1 | grep 'next version'
Output
# semantic-release dry run
# Found 12 commits since last release v1.2.3
# Analyzing commits:
# feat: add payment module → minor
# fix: fix tax calculation → patch
# fix: correct typo → patch
# feat!: redesign API → major
# Next version: v2.0.0
# Publish to npm: v1.2.4
# Create GitHub release: v1.2.4
semantic-release Requires Permission to Push
semantic-release creates git tags and commits changelog files. It needs write access to your repository. Use a dedicated GITHUB_TOKEN (not your personal token) with contents: write and pull-requests: write permissions. For npm publishing, configure NPM_TOKEN as a repository secret.
Production Insight
Use semantic-release with @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.
Key Takeaway
semantic-release automates versioning based on conventional commits: fix → patch, feat → minor, BREAKING → major. Commit message format determines the version. Use dry-run to preview releases. Enforce conventional commits with commitlint in CI.
● Production incidentPOST-MORTEMseverity: high

The 'Fix' Commit That Would Have Bumped v1.2.3 to v2.0.0

Symptom
A developer included a breaking API change in a commit with type 'fix:'. semantic-release correctly parsed the commit message, found no 'BREAKING CHANGE:' footer, and would have bumped the patch version (v1.2.4). The breaking change would have been released as a patch, silently breaking all downstream consumers. The code reviewer caught the mistake and updated the commit to 'feat:' with a 'BREAKING CHANGE:' footer before merge.
Assumption
The developer assumed the commit type ('fix:') was just a label and wouldn't affect versioning. They didn't realize semantic-release uses the type to determine the version bump.
Root cause
1. Developer made a breaking API change (renamed a function, removed a parameter). 2. They committed with 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.
Fix
1. Changed the commit message to 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.
Key lesson
  • Commit type determines version bump: fix → patch, feat → minor, BREAKING → major.
  • Use ! or BREAKING 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.
Production debug guideUse this when production is on fire3 entries
Symptom · 01
I want to automate version bumps and releases
Fix
Set up semantic-release in CI with conventional commits
Symptom · 02
I need to prevent accidental major version bumps
Fix
Use commitlint to enforce conventional commit format, and add BREAKING CHANGE detection in CI
Symptom · 03
I want to see what version the next release will be
Fix
Run npx semantic-release --dry-run to preview the version bump and changelog

Key takeaways

1
semantic-release automates version bumps from commit messages
2
fix → patch, feat → minor, BREAKING CHANGE → major
3
Use ! or BREAKING CHANGE: footer to mark breaking changes
4
Always dry-run before actual release to verify the version bump
N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.

Follow
Verified
production tested
July 07, 2026
last updated
214
articles · all by Naren
🔥

That's Git. Mark it forged?

3 min read · try the examples if you haven't

Previous
Trunk-Based Development: Merge to Main Multiple Times Daily
39 / 47 · Git
Next
Branch Protection Rules: Secure Your Git Workflow