rlsbl v0.92.0 /rlsbl.changelog.generate
On this page

Generate a Markdown CHANGELOG.md from structured JSONL changelog entries, grouping them by version with configurable formatting.

#rlsbl.changelog.generate

#rlsbl.changelog.generate

Generate a Markdown CHANGELOG.md from structured JSONL changelog entries, grouping them by version with configurable formatting.

#_base_version

python
def _base_version(version: str) -> str

Strip the pre-release suffix from a version string.

"0.43.0-alpha.0" -> "0.43.0" "1.0.0" -> "1.0.0"

#_is_prerelease

python
def _is_prerelease(version: str) -> bool

Return True if the version has a pre-release suffix.

#_read_release_metadata

python
def _read_release_metadata(project_path: str, version: str) -> tuple[str, str]

Read description and context from an archived release toml file.

Looks for .rlsbl/releases/v{version}.toml and extracts the description and context fields. Returns ("", "") if the file doesn't exist or can't be parsed.

#_read_release_metadata_full

python
def _read_release_metadata_full(project_path: str, version: str) -> tuple[str, str, str]

Read description, context, and bump type from an archived release toml file.

Looks for .rlsbl/releases/v{version}.toml and extracts the description, context, and bump fields. Returns ("", "", "") if the file doesn't exist or can't be parsed.

#generate_version_section

python
def generate_version_section(version: str, entries: list[ChangelogEntry], *, description: str='', context: str='', bump_type: str | None=None) -> str

Generate markdown for one version section.

Only includes entries where user_facing=True. Groups by type under sub-headers (Breaking, Features, Fixes, Other). Empty groups are omitted. If no user-facing entries exist, emits a single "No user-facing changes." bullet.

If all entries share a release_type (e.g., "ota" or "build"), a marker is appended to the version heading.

When description is provided, it is added as a paragraph after the version heading and before the first type group. When context is provided, it is rendered as a collapsible

block after the description.

#generate_version_file

python
def generate_version_file(changes_dir: str, version: str, write_to_disk: bool=True, *, description: str='', context: str='', bump_type: str | None=None) -> str

Read the JSONL file for a version, generate markdown, optionally write .md alongside it.

Returns the generated markdown text. When write_to_disk is False, computes the markdown without touching the filesystem (used to preview content before pre-checks).

When description and context are provided, they are passed through to generate_version_section() so release metadata appears in the output.

#_deduplicate_entries

python
def _deduplicate_entries(entries: list[ChangelogEntry]) -> list[ChangelogEntry]

Remove duplicate entries based on commit hash sets.

Two entries are duplicates when they have the same set of commits. The first occurrence wins (preserves order).

#_generate_consolidated_section

python
def _generate_consolidated_section(stable_version: str, all_entries: list[ChangelogEntry], prerelease_versions: list[str], prerelease_entries_by_version: dict[str, list[ChangelogEntry]], *, description: str='', context: str='', bump_type: str | None=None) -> str

Generate a consolidated section for a stable version with pre-release predecessors.

Produces:

  1. The stable heading (## 0.43.0) with ALL entries deduplicated
  2. A note listing the pre-release cycle
  3. Individual pre-release headings (### 0.43.0-alpha.0) with their entries

#_read_changelog_format

python
def _read_changelog_format(project_path: str) -> str

Read changelog_format from project config, defaulting to 'grouped'.

#generate_changelog

python
def generate_changelog(project_path: str, *, write_to_disk: bool=True, version_override: str | None=None, description: str='', context: str='', changes_dir_override: str | None=None, changelog_output_path: str | None=None, bump_type: str | None=None) -> str

Generate the complete CHANGELOG.md from .rlsbl/changes/ JSONL files.

  1. Reads changelog_format from config (only "grouped" supported).
  2. Reads unreleased.jsonl (if non-empty) for an Unreleased section.
  3. Reads all versioned JSONL files sorted newest-first.
  4. Generates per-version .md files alongside the JSONL files (when write_to_disk).
  5. Writes CHANGELOG.md at project root (when write_to_disk).
  6. Returns the generated content.

When write_to_disk is False, computes and returns the markdown content without modifying the filesystem. This lets callers preview the changelog before pre-release checks run, so an aborted release leaves a clean working tree.

When version_override is provided AND unreleased entries exist, the section heading is "## {version_override}" instead of "## Unreleased". Versioned sections (from existing JSONL files) are unaffected. Default None preserves the original behaviour exactly.

description and context are applied to the unreleased section only (the current release being prepared). Previously released version sections read their description and context from archived release files at .rlsbl/releases/v{version}.toml.

changes_dir_override overrides the default .rlsbl/changes/ path. Used in explicit releasable mode where the changes dir lives under the releasable directory.

changelog_output_path overrides the default CHANGELOG.md output location. Used in explicit releasable mode to write CHANGELOG.md into the releasable directory instead of the project root.

bump_type is passed through to generate_version_section() for the unreleased section. For versioned sections, the bump type is read from the archived release file.