Generate release changelogs from directories of changelog fragments
Project description
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file changelog_fragment_cli-0.1.1.tar.gz.
File metadata
- Download URL: changelog_fragment_cli-0.1.1.tar.gz
- Upload date:
- Size: 23.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
64869e934bb913e693887143a1c81721e4eb23b0af44ed1fd24d3e702a9fdb87
|
|
| MD5 |
c2f4d4fe84987a45e0bcaa1e67ab6d41
|
|
| BLAKE2b-256 |
4b9d986844567f75b671a7d51591a9f7f08e28daf7eb0855bcbffb30ed9eb9d4
|
Provenance
The following attestation bundles were made for changelog_fragment_cli-0.1.1.tar.gz:
Publisher:
publish.yml on gregorv/changelog-fragment-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
changelog_fragment_cli-0.1.1.tar.gz -
Subject digest:
64869e934bb913e693887143a1c81721e4eb23b0af44ed1fd24d3e702a9fdb87 - Sigstore transparency entry: 2090805654
- Sigstore integration time:
-
Permalink:
gregorv/changelog-fragment-cli@6de66fd0da9257d7eda2900d9cffc601ef9708e8 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/gregorv
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6de66fd0da9257d7eda2900d9cffc601ef9708e8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file changelog_fragment_cli-0.1.1-py3-none-any.whl.
File metadata
- Download URL: changelog_fragment_cli-0.1.1-py3-none-any.whl
- Upload date:
- Size: 26.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0bf9477107a9904a1dc3912874102115ae6656ebd0754a1892fa386511ebcf81
|
|
| MD5 |
56b68369bc1fa0fecccb718867038f4c
|
|
| BLAKE2b-256 |
cec67f62db1f8cdb46b7ef8699363fabd0ccc21becbbfdaa029fd1b8608b1915
|
Provenance
The following attestation bundles were made for changelog_fragment_cli-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on gregorv/changelog-fragment-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
changelog_fragment_cli-0.1.1-py3-none-any.whl -
Subject digest:
0bf9477107a9904a1dc3912874102115ae6656ebd0754a1892fa386511ebcf81 - Sigstore transparency entry: 2090805823
- Sigstore integration time:
-
Permalink:
gregorv/changelog-fragment-cli@6de66fd0da9257d7eda2900d9cffc601ef9708e8 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/gregorv
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6de66fd0da9257d7eda2900d9cffc601ef9708e8 -
Trigger Event:
push
-
Statement type: