Write-at-source vs post-hoc pipelines, ownership, audience split, and what evidence justifies automating now.

Release-notes automation fails for a boring reason: teams automate the wrong moment in the workflow. The useful split is not “AI vs human.” It is whether the words for readers get written when someone makes the change, or afterward, by a tool reading what version control happened to record.
A pipeline that produces a serviceable changelog for engineers upgrading a library will produce noise for a CSM preparing a renewal—and no model upgrade fixes that, because the problem sits in inputs and ownership. Everything below follows from that split. For craft once you have a draft, see how to write.
| Pipeline | When words are written | Strength | Failure mode |
|---|---|---|---|
| Write-at-source | With the change (PR template, ticket field, “customer impact” checkbox) | Context is fresh; intent is captured | Dies if the field is optional and ignored |
| Post-hoc generation | After merge, from commits/tickets/diffs | Low ceremony; catches volume | Reconstructs intent poorly; ticket jargon leaks |
Most mature teams run a hybrid: write-at-source for Tier-1 and breaking changes, post-hoc drafts for Tier-3 volume, then an editorial pass into a template.
Generators only sound smart when the source already encodes reader-relevant facts:
If your tickets say “fix NPE in billing worker,” automation will announce an NPE in a billing worker. That is not a model problem.
Running on Jira? The step-by-step version, with the automation rule you can copy, lives in Jira release notes.
1. Add a customer-impact field to your pull request template. This is the cheapest write-at-source step. A minimal version in .github/pull_request_template.md:
## Customer impact
<!-- One sentence a customer would understand, or "None" -->
- [ ] User-facing change
- [ ] Breaking change or deprecation (needs a notice)
- [ ] Internal only (no release note)Make the field required for user-facing work, for example through review rules, so it doesn't die the way optional fields do.
2. Let labels sort the draft. GitHub can generate release notes automatically from merged pull requests. A .github/release.yml file groups them by label and excludes noise:
changelog:
exclude:
labels: [internal, dependencies]
categories:
- title: Breaking changes
labels: [breaking-change]
- title: New
labels: [feature]
- title: Fixed
labels: [bug]
- title: Other changes
labels: ["*"]
The output is a draft for developers. It uses pull request titles, so it's only as readable as those titles.
3. Use a commit convention if you generate from commits.Conventional Commits prefixes (feat:, fix:, and a BREAKING CHANGE: footer) let tools sort changes and flag breaking ones, and they map onto semantic versioning.
4. Or write a note file with each change. Tools like Changesets (JavaScript) and towncrier (Python) ask contributors to add a short note file alongside their change, then compile those files into the changelog at release time. That's write-at-source with tooling doing the assembly.
5. In Jira or similar, use a dedicated release-note field. Add a "Release note" text field (plus a "customer-facing?" flag) that's filled in while the ticket is open, then export the tickets in a release version as the starting draft. Filling it in only at release time defeats the point.
Whichever setup you use, the output is a draft. The editorial steps below still apply before anything reaches customers.
Automation is usually tuned for the people closest to the repo. Customer-facing notes need a different noun set, a different level of detail, and often a different channel. Route by audience before you scale generation—see audiences and channels.
Don't make one generated document serve everyone. Customers end up wading through migration steps for APIs they never call, while the engineer planning an upgrade hunts through feature copy for the one line that decides whether the deploy is risky. Route anything tagged as breaking to its own output (a "Breaking changes" section at the top of the changelog, a dedicated upgrade guide, or a migration notice) with a named owner and its own timeline. For API consumers, the HTTP Deprecation and Sunset response headers can carry the same signal in-band. Full playbook → breaking changes.
Decide who is accountable for the customer sentence before you buy a generator:
RACI detail lives on who writes release notes. Timing: generate drafts continuously; publish on the cadence your program already chose (best practices).
| Do now | Wait until… | Reconsider if… |
|---|---|---|
| Required customer-impact field on PRs for user-facing work | You have a human editorial owner for digests | Your only “notes” audience is internal engineering |
| Post-hoc drafts for high-volume Tier-3 | Ticket hygiene is good enough to quote | You ship mostly infra with no external readers |
| Separate templates for deprecation / follow-up | Breaking-change calendar exists | You try to fully auto-publish Tier-1 without review |
Automation amplifies the writing system you already have. Research on release notes in practice found significant disagreement between stakeholder groups on how release notes should be written and used (Bi et al., IEEE Transactions on Software Engineering, 2022). A generator can't settle that disagreement for you, so decide who each output is for, and fix the inputs first.
It can draft. End-to-end publish without an owner who understands the customer usually produces a prettier changelog, not better communication.
Automate gathering inputs; keep humans on narrative, timing, and channel plan. Tier-1 is a communication event, not only a commit batch.
Start with a mandatory customer-impact field on user-facing PRs. Add post-hoc generation once that field is trusted, so the generator has something true to say.
Tag breaking changes explicitly in the source system and route them through the warn → remind → cutover path—never through an unreviewed digest.
If drafts are fine but getting the same note into email, in-app, and a public page is the grind, a dedicated release-notes workspace can help. The pipeline design above still comes first.