Skip to content

Changelog Framework

The tenzir-changelog harness curates changelog entries, ships release notes, and assembles the public changelog across Tenzir repositories. Use this page as a reference for concepts, configuration, and CLI details. For step-by-step walkthroughs, see the guide for maintaining a changelog.

tenzir-changelog ships as a Python package that requires Python 3.12 or later. Install it with uv (or pip) and verify the console script:

Terminal window
uv add tenzir-changelog
uvx tenzir-changelog --help
  • Project – Identifies which documentation stream the changelog belongs to. Every entry and release references the same project string.
  • Entry – A changelog consists of entries. Each entry uses one of four hard-coded types: breaking, feature, bugfix, or change.
  • Unreleased bucket – Pending entries live in unreleased/ until you move them to a release.
  • Release – Versioned milestone under releases/<version>/ containing manifest.yaml, notes.md, and archived entry files in entries/.
  • Configuration file – Settings live in config.yaml by default, or you can store them in package.yaml alongside the changelog/ directory. config.yaml takes precedence when both exist.
  • Export style – Controls whether release notes use a detailed card layout or a compact bullet-list layout. Set export_style: compact in configuration to prefer the bullet-list format without passing --compact each time.
  • Components – You may constrain the optional component field on entries by listing allowed labels in configuration. Component filters apply to the CLI table, exports, and validation.

A typical project layout looks like this:

  • Directoryproject-root/
    • Directorychangelog/
      • config.yaml
      • Directoryunreleased/
        • 01-add-feature.md
        • 02-fix-bug.md
      • Directoryreleases/
        • Directoryv1.0.0/
          • manifest.yaml
          • notes.md
          • Directoryentries/
            • 01-add-feature.md
            • 02-fix-bug.md

For a package layout (with package.yaml), the structure may look like:

  • Directorymy-package/
    • package.yaml
    • Directorychangelog/
      • Directoryunreleased/
      • Directoryreleases/

Run changelog commands from the project root or the changelog/ directory:

Terminal window
uvx tenzir-changelog [command] [options]

All commands accept --config to point at an explicit configuration file (YAML format, defaulting to config.yaml) and --root to operate on another repository. When you omit both options, the CLI looks for config.yaml inside the changelog root or, failing that, for a package.yaml one directory above the changelog folder. This package mode lets you run commands from either the package root or the changelog/ directory without repeating --root.

Display changelog entries in multiple views.

tenzir-changelog show [identifiers...] [options]
OptionDescription
identifiersRow numbers, entry IDs, release versions, or - (optional)
-c/--cardShow detailed cards for matching entries
-m/--markdownExport as Markdown
-j/--jsonExport as JSON
--compactUse compact bullet-list layout
--no-compactUse detailed card layout
--no-emojiRemove type emoji from output
--project <id>Filter to specific project
--component <label>Filter to specific component
--banner <text>Add banner text to table output

The table view (default) lists entries with ID, title, type, project, PRs, and authors. Row numbers count backward from the newest entry, so #1 always targets the latest change.

Create a new changelog entry in unreleased/.

tenzir-changelog add [options]
OptionDescription
--title <text>Entry title
--type <type>breaking, feature, bugfix, or change
--description <text>Entry body
--author <name>Contributor name (repeatable)
--pr <number>Pull request number (repeatable)
--component <label>Component label (must match configuration)
--webOpen prefilled GitHub file creation URL

The command prompts for any information you do not pass explicitly. The first invocation scaffolds config.yaml, unreleased/, and releases/ automatically. The CLI assigns globally sequential filenames with numeric prefixes (e.g., 01-feature-name.md).

Stage a release under releases/<version>/.

tenzir-changelog release create [version] [options]
OptionDescription
versionRelease version (e.g., v1.0.0)
--patchBump patch version from latest release
--minorBump minor version from latest release
--majorBump major version from latest release
--yesCommit changes (default is dry run)
--intro <text>Inline intro text (mutually exclusive with --intro-file)
--intro-file <path>Path to intro file (mutually exclusive with --intro)
--compactUse bullet-list layout for notes.md
--date <YYYY-MM-DD>Override release date

The command renders notes.md, updates manifest.yaml, and moves entry files into entries/. It performs a dry run by default. When the release already exists, the CLI appends additional unreleased entries.

Re-export release notes without modifying files.

tenzir-changelog release notes <identifier> [options]
OptionDescription
identifierRelease version or - for unreleased
-mExport as Markdown (default)
-jExport as JSON
--compactUse bullet-list layout
--no-emojiDrop type icons

Publish a release to GitHub via gh.

tenzir-changelog release publish <version> [options]
OptionDescription
versionRelease version
--yesSkip confirmation prompts
--draftMark as draft
--prereleaseMark as prerelease
--tagCreate and push annotated Git tag

The command reads project metadata from config.yaml or package.yaml for the repository slug and uses notes.md as the release body.

Run structural checks across entry files, release manifests, and exported documentation.

tenzir-changelog validate

The validator reports missing metadata, unused entries, duplicate entry IDs, and configuration drift across repositories.

Configuration settings live in config.yaml by default, or you can store them in package.yaml alongside the changelog/ directory. config.yaml takes precedence when both exist.

Configuration fields:

FieldDescription
idCanonical project slug written into entry frontmatter (required)
nameHuman-friendly label surfaced in release titles and CLI output
descriptionOptional project description included in release manifests
repositoryOptional GitHub slug (e.g., owner/repo) used by release publish
export_styleDefault layout: compact (bullet-list) or omit for detailed cards
componentsOptional list of component labels that entries must satisfy

Example:

id: tenzir-core
name: Tenzir Core
description: Core pipeline engine
repository: tenzir/tenzir
export_style: compact
components:
- cli
- engine
- operators

The first invocation of tenzir-changelog add scaffolds config.yaml automatically, inferring defaults from the directory name. Projects with package.yaml next to changelog/ reuse the package id and name automatically.

Entry files live in unreleased/ or releases/<version>/entries/ as Markdown files with YAML frontmatter. The CLI assigns sequential numeric prefixes (e.g., 01-feature-name.md, 02-bugfix.md).

Example entry:

---
title: Add pipeline builder
type: feature
authors:
- alice
created: 2025-10-16
prs:
- 101
component: cli
---
Introduces the new pipeline builder UI with drag-and-drop support.

Frontmatter fields:

FieldTypeRequiredDescription
titlestringyesEntry title
typestringyesbreaking, feature, bugfix, or change
authorslist[string]noContributor names
createdstringyesCreation date in YYYY-MM-DD format
prslist[int]noPull request numbers
componentstringnoLabel matching configured components

Release manifests live at releases/<version>/manifest.yaml and record metadata about a release.

Example manifest:

created: 2025-10-18
intro: |
Welcome to version 1.0.0!
This release includes significant performance improvements.

Manifest fields:

FieldTypeRequiredDescription
createdstringyesRelease date in YYYY-MM-DD format
introstringnoIntroductory content (supports Markdown)

The CLI generates notes.md by stitching together the intro and grouped entry sections. Intro content comes from either --intro (inline text) or --intro-file (file path) when creating a release.

The CLI recognizes these environment variables:

VariableDescription
GITHUB_TOKENGitHub token with repo scope for private repos

For managing multiple related projects, tenzir-changelog supports coordinated changelog operations across multiple project roots using the --root flag repeatedly.

When you specify multiple --root flags, the CLI enters multi-project mode:

  • The show command displays entries from all projects in a unified table with a Project column, sorting entries by project order (as specified by --root flags) and then by date within each project.
  • Markdown and JSON exports group entries by project using a hierarchical format: version → project → entry type → entries.
  • The release create command performs atomic coordinated releases across all projects. If any project fails validation (e.g., the version already exists), the CLI makes no changes to any project.

Use --project <id> to filter output to specific projects. Entry identifiers may repeat across projects, and the CLI keeps them correctly scoped to their origin project when rendering tables or exports.

Multi-project markdown exports follow this hierarchical structure:

# v5.0.0
## Tenzir Core
### Features
- **Add pipeline builder**: Introduces the new pipeline builder UI.
## Tenzir Cloud
### Features
- **Add SSO support**: Integrates enterprise SSO for authentication.
  • Validation errors – Run tenzir-changelog validate to identify missing metadata, unused entries, or duplicate IDs.
  • Component mismatch – When components is configured, ensure every entry either omits component or uses an allowed label.
  • Configuration not found – Ensure config.yaml exists in the changelog root or package.yaml sits next to the changelog/ directory. Run tenzir-changelog add once to scaffold the configuration.
  • Version bump fails – Bump flags read the latest release manifest on disk. Create an initial release with an explicit version before using --patch/--minor/--major.

Last updated: