Reusable GitHub Actions workflow that enriches GitHub release notes with the matching section from
CHANGELOG.md.
Many "publish library" workflows (e.g. mbl-actionhub/publish-kmp-library) create GitHub releases with only a ## Published Modules artifact-list block. This workflow runs on release:created/published/edited events, extracts the matching ## [<version>] (or ## [Unreleased] fallback) section from your CHANGELOG.md, and prepends it as ## What's changed above the artifact list.
Before (auto-created release body):
## Published Modules
- io.github.mobilebytelabs:cmp-clipboard:3.4.0
- io.github.mobilebytelabs:cmp-share:3.4.0
- ...After (enriched by this workflow):
## What's changed
### Added — Inter-App Comms v0.4
- Phase 0 spikes: ...
- Phases 2-5: ADR-09 closures
- Phase 13: SystemIntents lifecycle-free entry points
- ...
---
## Published Modules
- io.github.mobilebytelabs:cmp-clipboard:3.4.0
- ...Add this to your library repo as .github/workflows/release-notes.yml:
name: Release Notes
on:
release:
types: [created, published, edited]
workflow_dispatch:
inputs:
tag:
description: 'Release tag to enrich (e.g. v3.4.0)'
required: true
type: string
jobs:
enrich:
uses: MobileByteLabs/mbl-release-notes-action/.github/workflows/release-notes-from-changelog.yml@v1.0.0
permissions:
contents: write
with:
tag: ${{ github.event.release.tag_name || inputs.tag }}
secrets: inheritThat's it. The next release you publish gets auto-enriched.
| Input | Default | Description |
|---|---|---|
tag |
(required) | Release tag to enrich (e.g. v3.4.0) |
changelog-path |
CHANGELOG.md |
Path to changelog relative to repo root |
heading-label |
What's changed |
Heading text for the prepended block (no leading ##) |
separator |
--- |
Markdown separator between changelog block + existing body |
fail-when-missing |
false |
Fail the job if no CHANGELOG section is found (default: no-op exits 0) |
| Priority | Pattern | Notes |
|---|---|---|
| 1 | ## [<version>] |
Preferred — for projects that move [Unreleased] to [X.Y.Z] on each release |
| 2 | ## [Unreleased] |
Fallback — for projects that keep all unreleased work under [Unreleased] |
Tag prefix v is stripped (v3.4.0 → matches [3.4.0]).
The workflow checks out at the release tag commit, not the default branch HEAD. This avoids reading a CHANGELOG that's already had a "bump-after-release" commit applied to it.
If the release body already starts with ## <heading-label> (default: ## What's changed), the workflow exits 0 without editing. Safe to re-run via workflow_dispatch for backfilling old releases without double-prepending.
If CHANGELOG.md doesn't exist or has no matching section, the workflow emits a warning and exits 0. Set fail-when-missing: true to make it a hard failure instead.
The reusable workflow declares contents: write (needed to edit release notes). The calling workflow must propagate it via permissions: on the job:
jobs:
enrich:
uses: MobileByteLabs/mbl-release-notes-action/.github/workflows/release-notes-from-changelog.yml@v1.0.0
permissions:
contents: write # required — propagates to the reusable workflowsecrets: inherit (the workflow uses secrets.GITHUB_TOKEN, which is auto-provided by GitHub Actions — no manual setup).
Pin to a tag for reproducibility:
uses: MobileByteLabs/mbl-release-notes-action/.github/workflows/release-notes-from-changelog.yml@v1.0.0| Tag | Notes |
|---|---|
v1.0.0 |
Initial release |
with:
tag: ${{ github.event.release.tag_name }}
changelog-path: docs/CHANGELOG.mdwith:
tag: ${{ github.event.release.tag_name }}
heading-label: 'Release notes' # renders as `## Release notes`with:
tag: ${{ github.event.release.tag_name }}
fail-when-missing: truegh workflow run release-notes.yml --ref main -f tag=v3.4.0mbl-actionhub— sibling repo with KMP-library-specific reusable workflows (CI, publish, PR-check)- Keep a Changelog — the CHANGELOG format this workflow expects
Apache 2.0 — see LICENSE