Release Notes
Automated release notes turn the changelog from a Friday-afternoon chore into a side effect of merging PRs. The pattern: enforce a conventional commit/PR shape, let a generator (release-please, changesets, semantic-release) compute the next version, write CHANGELOG.md, and open the release PR. Reviewers approve a diff instead of curating bullets by hand.
release-please workflow with versioning + notes
EXAMPLE
# .github/workflows/release-please.yml
# Runs on every push to main. Opens a PR with version bump + CHANGELOG diff.
# When the PR is merged, the tag is created and your release pipeline runs.
name: release-please
on:
push:
branches: [main]
permissions:
contents: write
pull-requests: write
issues: write
jobs:
release-please:
runs-on: ubuntu-latest
steps:
- uses: googleapis/release-please-action@v4
with:
release-type: node # or php, go, python, rust, generic
token: ${{ secrets.GITHUB_TOKEN }}
# .release-please-config.json — optional, finer control
{
"packages": {
".": {
"package-name": "shop",
"release-type": "node",
"changelog-sections": [
{ "type": "feat", "section": "Features" },
{ "type": "fix", "section": "Bug Fixes" },
{ "type": "perf", "section": "Performance" },
{ "type": "docs", "section": "Documentation" },
{ "type": "refactor", "section": "Internal" }
]
}
}
}
# .release-please-manifest.json — track the current version
{ ".": "1.4.0" }
# ===== Conventional commits =====
# release-please reads commit messages to decide the version bump.
# feat: minor bump -> 1.4.0 -> 1.5.0
# fix: patch bump -> 1.4.0 -> 1.4.1
# feat!: major bump -> 1.4.0 -> 2.0.0
# chore: no version change
# Anything that does not match is ignored.
# Examples
# feat(orders): support partial refunds
# fix(checkout): handle empty postal code on shipping form
# feat!: drop Node 18 support (BREAKING CHANGE: requires Node 20+)
# ===== Enforce on PRs =====
# .github/workflows/pr-title.yml
# name: PR title format
# on: [pull_request]
# jobs:
# lint:
# runs-on: ubuntu-latest
# steps:
# - uses: amannn/action-semantic-pull-request@v5
# env: { GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} }
# with:
# types: |
# feat
# fix
# perf
# docs
# refactor
# test
# chore
# ===== When the release PR merges =====
# 1) release-please tags the commit (v1.5.0)
# 2) Your release pipeline (see cicd/tags lesson) runs:
# - build + push container image tagged v1.5.0
# - publish to npm / pypi / crates as needed
# - create a GitHub Release with the CHANGELOG section as body
# - deploy to production (or staged rollout)
# 3) Devs read the release notes in #releases on Slack, in a feed,
# or in the App Store / Play release notes you copy from the same source.
# ===== Alternatives =====
# - changesets (better for monorepos with multiple packages)
# - semantic-release (no PR — auto-releases on every merge)
# - autorelease (small projects)
# Pick by team size + monorepo shape; the goal is the same.
# ===== Why this matters =====
# - Stop forgetting the changelog
# - Stop debating versions
# - Stop writing release notes from git log on Friday at 5pm
# - Customers, partners, and security teams get a stable, machine-readable
# timeline of what changed
# - Auditors love it
# ===== Common pitfalls =====
# - Mixing release-please with manual tag pushes -> race conditions
# - Inconsistent commit/PR titles -> release notes look noisy
# - Squash merging without an aggregate commit message
# (configure GitHub: 'Default to PR title and description for squash')
Why it matters
Once release-please owns the version + the CHANGELOG, the release PR becomes the canonical artifact: review the version bump, review the diff, merge. Hand-writing release notes turns into a one-time setup cost — and the moment a deploy goes wrong, you have a precise git-tagged, machine-readable changelog to bisect against.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
# Generated from PR labels or conventional commits. # release-please opens a release PR that bumps version + changelog.Try it Yourself »
Discussion
Loading…