Templates#

The changelog is generated with over-ridable Jinja templates. You don’t have to override all the templates, simply the ones you want to.

You can configure where generate-changelog looks for custom templates.

The core of the changelog is the commit. The rest is just a grouping of the commits in a desired method.

base.md.jinja#

The base template is rendered when generating the changelog from scratch. Incremental generations will only use the heading and versions templates.

{% include "heading.md.jinja" %}

{% include "versions.md.jinja" %}

{% include "footer.md.jinja" %}

heading.md.jinja#

The heading template is rendered for the title of the changelog.

# Changelog

versions.md.jinja#

{% for version in versions -%}
{% include "version_heading.md.jinja" %}

{% for grp_commit in version.grouped_commits -%}
    {% if loop.previtem is defined %}
        {% set heading_level = diff_index(loop.previtem.grouping, grp_commit.grouping) %}
    {% else %}
        {% set heading_level = 0 %}
    {%- endif %}
    {% for level in range(heading_level, group_depth) -%}
        {% include "section_heading.md.jinja" %}
    {% endfor %}

    {% for commit in grp_commit.commits %}
        {% include "commit.md.jinja" %}
    {% endfor %}
{%- endfor %}
{%- endfor %}

To understand how this template works, understanding how the commits are processed and grouped will help.

The commits are enriched with metadata and sorted by the version and grouping values. In this table you can see the commit version and the values of the group_by configuration, sorted.

version

committer, metadata.category

Commit

1.0.1

Alice, Changes

commit8

1.0.1

Alice, New

commit2

1.0.1

Alice, New

commit5

1.0.1

Bob, Changes

commit7

1.0.1

Bob, Fixes

commit10

1.0.1

Bob, New

commit1

1.0.1

Bob, New

commit4

1.0.1

Charly, Changes

commit6

1.0.1

Charly, Fixes

commit9

1.0.1

Charly, New

commit3

This is consolidated into the context that looks something like this (See the VersionContext for better information):

simplified_version_context = {
    "label": "1.0.1",
    "grouped_commits": {
        ("Alice", "Changes"): ["commit8"],
        ("Alice", "New"): ["commit2", "commit5"],
        ("Bob", "Changes"): ["commit7"],
        ("Bob", "Fixes"): ["commit10"],
        ("Bob", "New"): ["commit1", "commit4"],
        ("Charly", "Changes"): ["commit6"],
        ("Charly", "Fixes"): ["commit9"],
        ("Charly", "New"): ["commit3"],
    }
}

The template looks for changes in the grouping values and renders section headings for the new value. The result is somthing like:

## 1.0.1 (2022-01-01)

### Alice

#### Changes

- commit8

#### New

- commit2

- commit5

...

version_heading.md.jinja#

The version heading template is rendered for the title of each tagged version.

## {{ version.label }} ({{ version.date_time.strftime("%Y-%m-%d") }})

section_heading.md.jinja#

The section heading template is rendered for the value changes in the grouping. The heading level is adjusted based on the level parameter set in the version_heading.md.jinja template.

###{{ "#" * level }} {{ grp_commit.grouping[level] or "Other" }}

commit.md.jinja#

This template is rendered for each commit.

- {{ commit.summary }}
  {{ commit.body|indent(2, first=True) }}
  {% for key, val in commit.metadata["trailers"].items() %}
  {% if key not in valid_author_tokens %}
  **{{ key }}:** {{ val|join(", ") }}

  {% endif %}
{% endfor %}