Metadata-Version: 2.4
Name: changelog-fragment-cli
Version: 0.1.1
Summary: Generate release changelogs from directories of changelog fragments
License-Expression: GPL-3.0-or-later
License-File: LICENSE
Keywords: cli,semver,changelog
Author: Gregor Vollmer
Author-email: git@dynamic-noise.net
Requires-Python: >=3.11
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Dist: pyyaml (>=6.0.3,<7.0.0)
Project-URL: Homepage, https://github.com/gregorv/changelog-fragment-cli
Project-URL: Repository, https://github.com/gregorv/changelog-fragment-cli
Description-Content-Type: text/markdown

# changelog-fragment-cli
Generate release changelogs from directories of changelog fragments,
obeying the laws from [Keep-a-Changelog](https://keepachangelog.com/)
and [Semantic Versioning](https://semver.org/).

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.md` when several branches ship
  changes concurrently.
- Tags each change with a `severity` so 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.

```yaml
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.
- `severity` is required and must be `patch`, `minor`, `major`, or `release`.
- 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](https://semver.org/) 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.

