feat(changelog): add 'template' option to supply a custom changelog template
Description
This PR adds an option --template to the changelog command to be able to supply a custom template (see #132).
Checklist
- [x] Add test cases to all the changes you introduce
- [x] Run
./script/formatand./script/testlocally to ensure this change passes linter check and test - [x] Test the changes on the local machine manually
- [x] Update the documentation for the changes
Expected behavior
When the user calls cz changelog --template=CHANGELOG.md.j2 and supplies a custom Jinja template, then the custom template is used to render the final changelog instead of the built-in template.
Steps to Test This Pull Request
- Create a custom template using the built-in template as reference
- Run changelog command:
cz changelog --template=CHANGELOG.md.j2 - Enjoy the custom changelog
Additional context
Closes #132
Thanks, looks interesting. This adds some extra maintainability on our side, with people reporting templates not working, I'm not sure if it makes sense to us. I think the documentation should also explain how to use it, which variables are available to us inside your template.
If you don't mind @aisbergg I'd like to know where the current changelog implementation was not flexible enough? Thanks
What do you think @Lee-W ?
Hi @Woile,
I just recently discoverd conventional commits and I am quite intrigued by the idea of creating the changelogs from examining the Git history. Then I stumbled upon this project. Combining the creation of changelogs with version bumps is a really good idea. Though, I am not yet using commitizen, because I see following issues for myself:
Custom Changelog Template
I like the idea of customizing my changelogs by adding a custom header with a description of the file. Also I might be interested in different formats, one for storing in the repository and a second for displaying on a website. For example the project git-chglog asks first which template format shall be used. It stores it in the repository, where it then can be customized further.
I just created the --template option to see, if it works alright. There are some difficulties:
- Custom templates with file headers and other stuff don't go well together with the "incremental" function. The incremental function would find the last tag and insert the new rendered template and therefore duplicating the file header. Turning the option off helps.
- The
releases(formertree) object is in form of a generator. In order to loop it multiple times in the template, it must be first turned into a list. - Built-in Jinja filters are somewhat lacking in some cases. For example I implemented a table of contents in my changelog. In order to do so, I needed a filter to create a slug representation for the links. It is likely, that users request more filters, especially if the users have an Ansible background (like me), where they have a ton of special Jinja filters.
So it definitely adds complexity and might come with some more overhead. I wouldn't mind, if you decide against adding this feature.
Sign Tags When Using Bump
(not related to the changelog thing, but I mention it anyway)
I use bump2version for bumping the version. It offers the option to sign Git tags, which is missing in commitizen. Enforcing annotated commits to sign does not work either, because commitizen uses the -a option in Git, which creates always unsigned tags.
cz changelog --incremental is usually smart enough to include a header in your changelog.
You can create something like:
Try this CHANGELOG.md:
# CHANGELOG
This is the changelog for some app
## This is a subtitle
some exta content
and cz changelog --incremental will keep it.
The signed commits and tags are planned at some point I guess, we have already many requests, so maybe it's time to add them.
Could you show an example of the CHANGELOG with table of contents?
I'm a bit reluctant to expose the template, because that was never the idea. The moment we expose that template, we cannot move away from jinja, and we cannot make internal refactors without breaking our users, and it's an extra thing for us to maintain. What do you think @Lee-W ?
My template lookled like this:
(Click to expand)
{% set releases = releases | list %}{# turn the generator into a list #}
{% macro create_release_title(release) %}
{%- set version = release.version[1:] if release.version.startswith('v') else release.version -%}
{{- version ~ ' (' ~ release.date ~ ')' if release.date else version -}}
{% endmacro %}
# Changelog
All notable changes to this project will be documented in this file.
{% for release in releases %}
- [{{ create_release_title(release) }}](#{{ create_release_title(release) | slugify }})
{% endfor %}
---
{% for release in releases %}
## {{ create_release_title(release) }}
{% for change_key, changes in release.changes.items() %}
{% if change_key %}
### {{ change_key }}
{% endif %}
{% for change in changes %}
{% if change.scope %}
- **{{ change.scope }}**: {{ change.message }}
{% elif change.message %}
- {{ change.message }}
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
It would turn the changelog of commitizen into:
(Click to expand)
# Changelog
All notable changes to this project will be documented in this file.
- [Unreleased](#unreleased)
- [2.17.4 (2021-04-22)](#2174-2021-04-22)
- [2.17.3 (2021-04-19)](#2173-2021-04-19)
- [2.17.2 (2021-04-10)](#2172-2021-04-10)
---
## Unreleased
### Feat
- **bump**: allow annotated tags to be signed
- **changelog**: add slugify filter for usage in a custom template
- **changelog**: add 'template' option to supply a custom changelog template
### Fix
- **bump**: use configured changelog_incremental value when calling `cz bump --changelog`
## 2.17.4 (2021-04-22)
### Fix
- version update in a docker-compose.yaml file
## 2.17.3 (2021-04-19)
### Fix
- fix multiple versions bumps when version changes the string size
## 2.17.2 (2021-04-10)
### Fix
- **bump**: replace all occurances that match regex
- **wip**: add test for current breaking change
@Woile I actually like this idea, but also know your concern about maintaining it. As we're already using jinja2 in the bump message, I doubt jija2 will be a huge concern to us. If my understanding is right, what we need to do is create a jinja2 template that consists of our current one, and then tell our users what variables they can use. Do you think of other case we'll need to concern/maintain?