changelog-fragment-cli
Generate release changelogs from directories of changelog fragments, obeying the laws from Keep-a-Changelog and Semantic Versioning.
Each user-visible change gets its own YAML fragment in a project subdirectory.
As an example, per Merge Request / Pull Request a new fragment is placed in the
changes.d subdirectory.
When building a release, a CI workflow then collects every fragment, merges them
into a new ## [X.Y.Z] - YYYY-MM-DD section at the top of the existing CHANGELOG.md
and deletes the consumed files. Additional meta information can be placed in various
temporary files, e.g. the calculated version number of the new release or the list of
removed files.
Why fragments
- Avoids merge conflicts on
CHANGELOG.mdwhen several branches ship changes concurrently. - Tags each change with a
severityso the release workflow can pick the correct semver bump automatically (patch<minor<major).
Format
File name: anything ending in .yaml or .yml. Suggested form:
<short-slug>.yaml, e.g. signed-urls.yaml or fix-cors.yaml.
Prefix with an issue or story identifier when one exists
(STORY-005-signoff.yaml) so PRs self-document.
severity: minor # one of: patch | minor | major
added: # any subset of Keep a Changelog sections:
- First bullet. # added | changed | deprecated | removed | fixed | security
fixed:
- Second bullet, possibly multi-line:
- |-
Use a `|-` block scalar to preserve line breaks inside a bullet
verbatim. Continuation lines indent by two spaces relative to the
scalar's first line.
Rules enforced by poetry run python scripts/changelog.py validate:
- Top level must be a mapping.
severityis required and must bepatch,minor,major, orrelease.- At least one section with at least one non-empty string entry.
- Unknown top-level keys are rejected (prevents silent typos).
Severity — how to pick
The severity decides which place of the version number is incremented. Please refer to the official Semantic Versioning documentation for detailed information.
| Severity | Use when |
|---|---|
patch |
Bug fix, internal change, or docs change with no user-visible behavior change. |
minor |
New feature or user-visible improvement that is backwards-compatible. |
major |
Breaking change for users (data loss, schema drops, removed endpoints, required re-login). |
release |
The 0.x → 1.0.0 cutover. Only valid while the current version is 0.y.z. |
The highest severity present across all fragments decides which place in the version number will be incremented.
Pre-1.0 bump rule
While the project is on 0.y.z, the major digit stays pinned at 0 and
the bumps map down one level:
major(breaking) → bumps the minor digit (e.g.0.3.0→0.4.0).minor/patch→ bumps the patch digit (e.g.0.3.0→0.3.1).
The 0 → 1 transition is gated behind the explicit release severity
so it never happens by accident. Once the current version is 1.0.0 or
higher the standard SemVer mapping applies (major/minor/patch bump
the matching digit) and release is rejected.
Starting a new project
A fresh project has no CHANGELOG.md yet. Scaffold one, plus the fragments
directory, with:
changelog-fragment-cli init CHANGELOG.md changes.d
This writes an empty Keep-a-Changelog file (no version entries yet) and a
changes.d/ directory containing a .gitkeep placeholder so the empty
directory survives in git. An existing CHANGELOG.md is never overwritten
unless you pass --force.
Because the scaffolded changelog declares no released version, it parses as
0.0.0 ("nothing released yet"), so the first release is always 0.1.0
regardless of the fragments' severity — the one exception being a release
fragment, which cuts straight to 1.0.0.
Creating a fragment
Scaffold a new fragment with a chosen severity and empty placeholders for every Keep-a-Changelog section:
changelog-fragment-cli create --minor changes.d/signed-urls.yml
Exactly one of --patch, --minor, --major, or --release is required.
The file is written with the selected severity plus an empty list for each
section (added, changed, deprecated, removed, fixed, security) —
fill in the ones that apply and delete the rest. Missing parent directories
are created; an existing file is never overwritten unless you pass --force.
Validating locally
changelog-fragment-cli validate --fragments-dir changes.d
Exit 0 means the fragments are release-ready; exit 2 prints every offending file to stderr.
Previewing the next release
changelog-fragment-cli preflight \
--fragments-dir changes.d \
--changelog CHANGELOG.md \
--run-number 1 \
--out-changelog /tmp/CHANGELOG.md.new \
--out-notes /tmp/release-notes.md \
--out-consumed /tmp/consumed.txt \
--out-summary /tmp/summary.md
This writes version=... / build_number=... to the file passed via
--github-output and writes the prospective new CHANGELOG.md and
per-release notes to the paths above.
Metadata
Release files for changelog-fragment-cli 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| changelog_fragment_cli-0.1.1.tar.gz | 23.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| changelog_fragment_cli-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 50.4 kB
Release files / changelog_fragment_cli-0.1.1.tar.gz
| Download URL | changelog_fragment_cli-0.1.1.tar.gz |
|---|---|
| Size | 23.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
64869e934bb913e693887143a1c81721e4eb23b0af44ed1fd24d3e702a9fdb87
|
|
BLAKE2b-256 checksum How to use checksums |
4b9d986844567f75b671a7d51591a9f7f08e28daf7eb0855bcbffb30ed9eb9d4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 6, 2026.
Transparency logRelease files / changelog_fragment_cli-0.1.1-py3-none-any.whl
| Download URL | changelog_fragment_cli-0.1.1-py3-none-any.whl |
|---|---|
| Size | 26.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0bf9477107a9904a1dc3912874102115ae6656ebd0754a1892fa386511ebcf81
|
|
BLAKE2b-256 checksum How to use checksums |
cec67f62db1f8cdb46b7ef8699363fabd0ccc21becbbfdaa029fd1b8608b1915
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 6, 2026.
Transparency log