Stage 5 · Platform
Build, Version & Release
Semantic Versioning
Applying SemVer, conventional commits, changelog generation, and release-please automation.
SemVer Basics
Semantic Versioning (SemVer) uses a three-part version number: MAJOR.MINOR.PATCH. MAJOR increments for breaking changes, MINOR for new features, and PATCH for bug fixes. This communicates the impact of changes to consumers without reading the changelog.
| Version | Change Type | Example |
|---|---|---|
| MAJOR (X.0.0) | Breaking API changes | v1.0.0 -> v2.0.0 |
| MINOR (0.X.0) | New features, backward compatible | v1.0.0 -> v1.1.0 |
| PATCH (0.0.X) | Bug fixes, backward compatible | v1.0.0 -> v1.0.1 |
Conventional Commits
Conventional Commits is a specification for commit messages that makes version automation possible. The format is type(scope): description, where type determines the version bump.
feat: add user authentication endpoint
feat(auth): implement OAuth2 flow
fix: resolve race condition in payment processing
fix(api): handle null response from upstream
docs: update API reference
chore: upgrade dependencies to latest versions
refactor: extract validation into separate module
test: add integration tests for user service
breaking-change: remove deprecated v1 API endpointsfeat triggers a MINOR bump, fix triggers a PATCH bump, and breaking-change (or a ! suffix) triggers a MAJOR bump. The scope in parentheses is optional but helps categorize changes.
Changelog Generation
name: Release
on:
push:
branches: [main]
permissions:
contents: write
pull-requests: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate changelog
uses: conventional-changelog/standard-version@v9
with:
release-as: patch
header: "## Changelog\n"
commit-url-format: "https://github.com/myorg/myrepo/commit/{{hash}}"
compare-url-format: "https://github.com/myorg/myrepo/compare/{{previousTag}}...{{currentTag}}"
skip.bump: false
skip.changelog: false
- name: Push release
run: |
git push --follow-tagsstandard-version reads conventional commits to determine the version bump, generates a changelog, creates a git tag, and pushes everything. The commit-url and compare-url formats create clickable links in the changelog.
Release-Plese Automation
name: Release
on:
push:
branches: [main]
permissions:
contents: write
pull-requests: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: googleapis/release-please-action@v4
id: release
with:
release-type: node
changelog-types: >
[
{"type":"feat","section":"Features","hidden":false},
{"type":"fix","section":"Bug Fixes","hidden":false},
{"type":"perf","section":"Performance","hidden":false},
{"type":"breaking-change","section":"Breaking Changes","hidden":false}
]
- name: Publish to npm
if: ${{ steps.release.outputs.release_created }}
run: |
npm ci
npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}Release-Plese creates a release PR that accumulates changes. When merged, it creates a GitHub release and tag. The release_created output lets you chain additional steps like publishing to npm.
Version Bumping Strategies
- Manual bumping — developer updates version in package.json before merge. Simple but error-prone.
- Conventional commits — automated tooling reads commit messages and bumps the version. Reliable and auditable.
- Commit count — every merge to main increments the version. Simple but ignores change significance.
- Merge-based — squash merge count determines the version. Works with GitHub's squash-and-merge.
Pre-release Versions
# Alpha releases (internal testing)
v1.2.0-alpha.1
v1.2.0-alpha.2
# Beta releases (wider testing)
v1.2.0-beta.1
v1.2.0-beta.2
# Release candidates (final testing)
v1.2.0-rc.1
v1.2.0-rc.2
# Nightly builds
v1.2.0-nightly.20240115Pre-release versions use a hyphen suffix. They are lower precedence than the release version — v1.2.0-alpha.1 < v1.2.0. Package managers treat pre-releases as unstable by default.
Release-Plese supports monorepos with independent versioning per package. Configure it with a release-please-config.json to manage multiple packages in a single repository with coordinated releases.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.