Manually writing release notes is the kind of work that nobody enjoys and everybody underestimates. The result is usually one of two failure modes: nobody writes them at all, or someone spends three hours every Friday assembling them from git log and ticket scraps. Automation is the obvious answer, and the tooling is mature enough in 2026 that there is no excuse to keep doing it by hand.
This post is the patterns that produce real, customer-facing release notes from your existing commits and PRs — and how to avoid the failure modes that make the output worse than nothing.
Three Audiences, Three Outputs
A "release notes" pipeline usually has to serve three different readers:
Engineers. Need the full changelog: commits, PRs, breaking changes. Verbose, technical, comprehensive.
Customers. Need user-facing changes: new features, fixed bugs, deprecations. Selective, plain-language, marketing-aware.
Internal stakeholders (sales, support, leadership). Need the same as customers, plus context about what is coming next.
The trap is producing one document for all three. The engineering changelog confuses customers; the customer-facing notes miss the technical detail engineers need.
The right pattern: generate the engineering changelog automatically, then derive the customer-facing notes from it (with human curation).
Conventional Commits as the Foundation
The cleanest automation starts at commit time. Conventional Commits enforces a structured format:
feat: add export to CSV button on dashboard
fix: prevent duplicate notifications on rapid clicks
docs: clarify webhook signature header
chore: bump prettier to 3.2
Tools parse these to determine version bumps and changelog entries automatically. The format is enforced in CI:
# .github/workflows/commits.yml
- uses: wagoid/commitlint-github-action@v5
Teams that adopt Conventional Commits get release automation almost for free. Teams that do not have to either retrofit the format on PR titles or rely on labels/metadata.
Semantic Release
semantic-release is the most-deployed automation in this space. It reads commits, decides the version bump, generates the changelog, tags the release, and publishes — all in CI.
{
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/github",
"@semantic-release/git"
]
}
On every merge to main:
- Commit history since last tag is analyzed
- Version is bumped (
feat= minor,fix= patch,feat!orBREAKING CHANGE= major) - CHANGELOG.md is updated with the new entries
- A git tag and GitHub release are created
For libraries published to a registry (npm, Packagist, PyPI), this also publishes the package. Fully automated release cycle.
PR-Label-Based Automation
If Conventional Commits is too disruptive to adopt, PR labels are an alternative. Tools like release-drafter work from labels.
# .github/release-drafter.yml
categories:
- title: '🚀 Features'
labels: ['feature', 'enhancement']
- title: '🐛 Bug Fixes'
labels: ['fix', 'bugfix']
- title: '🧰 Maintenance'
labels: ['chore', 'dependencies']
PRs are labeled at merge time; release-drafter assembles them into a draft GitHub release. Less rigorous than Conventional Commits but easier to retrofit.
Customer-Facing Notes
The engineering changelog is rarely the customer release notes. A chore commit ("bump prettier") and a feat commit ("add CSV export") are equally visible in the engineering changelog; only one matters to customers.
Two patterns for customer-facing notes:
Curated digest. A human picks the customer-relevant items from the engineering changelog, rewords them, and publishes. Lower automation, higher quality.
Tag-based filtering. PRs marked customer-visible (or similar) automatically appear in the customer notes. The author decides at merge time. Automated but requires discipline.
Most companies find a hybrid works best: tag-based filtering for the draft, human review for the polish.
What to Include and What to Skip
Customer-facing notes are an editing problem, not a writing problem.
Include:
- New features, especially user-visible ones
- Bug fixes that customers will have noticed
- Breaking changes (always, with migration instructions)
- Deprecations with sunset dates
- Performance improvements customers will feel
- Security fixes (in coordination with the security team)
Skip:
- Internal refactoring
- Test changes
- CI/CD updates
- Documentation tweaks
- Routine dependency bumps
The goal is "what the customer cares about," not "everything we did."
Versioning
For products with a public API, semantic versioning provides the framework.
- Major (X.0.0): Breaking changes
- Minor (X.Y.0): New features, backward-compatible
- Patch (X.Y.Z): Bug fixes
Conventional Commits + semantic-release maps commits to bumps automatically:
BREAKING CHANGE→ majorfeat→ minorfix→ patch
For internal applications without semantic versioning, date-based versioning (2026.05.12) is fine. The point is having a unique identifier per release; the format matters less.
Publishing
Where the release notes actually go:
- GitHub Releases. The default for OSS. Automatically generated from tags.
- Public changelog page. For SaaS products. Often
/changelogon the marketing site. - In-app notifications. "What's new" modal for active users.
- Email digest. Monthly or quarterly summary to all customers.
- Slack / Discord communities. Drop the notes where the community lives.
Most products end up using more than one. The same content, formatted for each surface, beats different content per surface.
The Slack-Notification-Only Anti-Pattern
A common mistake: piping release notes to Slack and nowhere else. Slack has no permanence. Three months later, the only record of a feature shipping is gone.
Slack notifications are a complement, not a replacement. The canonical record lives in a changelog (GitHub Releases, a markdown file, a database table).
Customer-Visible Examples
For inspiration, three companies do this well:
- Stripe — their changelog is comprehensive, dated, categorized, and links to documentation.
- Linear — they publish a "Changelog" page that reads like editorial content with screenshots.
- GitHub — "Changelog" with categorized announcements and clear deprecation notices.
The common pattern: customer-visible notes are not just bullet lists. They have voice, examples, and a clear value proposition for the reader.
A Practical Pipeline
For a typical Laravel + Node SaaS:
- Commits use Conventional Commits, enforced by commitlint in CI.
- PRs are labeled with
customer-visiblewhen relevant. semantic-releaseruns on merge to main, bumping the version and updating CHANGELOG.md.- A separate workflow filters customer-visible PRs and posts them to the
/changelogpage (via a CMS or markdown file). - A weekly digest is auto-drafted by collecting the week's customer-visible items; product manager edits for tone and publishes.
The total automation work is one to two weeks. The maintenance is minimal.
What Not to Automate
A few things benefit from human touch:
- Marketing copy for major launches. Generated bullets are not a launch announcement.
- Migration guides for breaking changes. The "before/after" needs explanation.
- Apology language after incidents. "We had an outage" deserves more than auto-generated text.
- Strategic context. "This sets us up for what we are doing next" is editorial, not generated.
Automate the boring part; preserve the human voice where it matters.
When Less Is More
For a tiny team shipping a few times per month, full automation is overkill. A markdown file updated by whoever ships, plus a Slack post, is enough. Reach for the heavier automation when the cadence outpaces the manual process.
The honest test: if release notes are not getting written, automate. If they are getting written but in three different formats, standardize. If they are getting written, in one format, and the team can keep up — leave it alone.
Looking at a release process that has gotten faster than the documentation around it can keep up with? We help teams set up release-note automation that improves customer communication without adding ceremony. scopeforged.com