Changelogs automatisés avec Git-Cliff
Vous avez soigneusement rédigé vos messages de commit en suivant la norme Conventional Commits. Et maintenant ? Vous copiez-collez ça à la main dans un CHANGELOG.md comme au Moyen Âge ?
Bien sûr que non. On automatise.
Générer un changelog automatiquement, c’est le meilleur retour sur investissement d’un historique de commits discipliné. Ça transforme votre log Git en un document clair et lisible qui raconte l’évolution du projet.
Pourquoi automatiser votre changelog ?
« Je peux l’écrire moi-même, ça prend cinq minutes. »
Bien sûr, et vous pouvez aussi baratter votre propre beurre. La question n’est pas le temps : c’est la cohérence, l’exactitude et le professionnalisme.
- Toujours à jour : généré depuis la source de vérité, votre historique Git.
- Professionnel : un format propre qui rassure utilisateurs et parties prenantes.
- Sans effort : une fois en place, vos commits deviennent vos notes de version.
Présentation de git-cliff
Il existe plusieurs outils, mais git-cliff fait très bien le job. C’est rapide, très personnalisable, et écrit en Rust (évidemment).
Il parcourt votre historique, filtre selon nos types de commits conventionnels (feat, fix, etc.) et génère un joli Markdown.
Installation
Vous pouvez installer git-cliff de plusieurs façons. Choisissez votre camp.
apk add git-cliffpacman -S git-cliff# Installation via un wrapper npm
npm install -g git-cliff-npm# Pour les utilisateurs Windows
winget install orhun.git-cliff# Sur macOS ou Linux
brew install git-cliff# Si vous avez la toolchain Rust
cargo install git-cliffUtilisation en CI/CD avec Docker
Le moyen le plus simple et le plus portable d’exécuter git-cliff en CI/CD est d’utiliser son image Docker officielle. Pas d’installation sur les runners, version maîtrisée et reproductible.
Voici un exemple de job GitLab CI qui génère le changelog et le publie en artefact. Le même principe s’applique à GitHub Actions, Jenkins, etc.
# .gitlab-ci.yml
stages:
- release
create_changelog:
stage: release
image: orhunp/git-cliff:latest
script:
# Récupérer tout l’historique et les tags
- git fetch --all --tags
# Générer le changelog
- git-cliff --output CHANGELOG.md --tag ${CI_COMMIT_TAG}
artifacts:
paths:
- CHANGELOG.md
rules:
# Ne s’exécute que lors d’un push de tag
- if: $CI_COMMIT_TAGCe job va automatiquement :
- Ne s’exécuter que quand vous poussez un nouveau tag Git.
- Utiliser l’image Docker
git-cliff. - Récupérer tout l’historique Git.
- Générer un
CHANGELOG.mdpour le tag en cours. - Publier
CHANGELOG.mden artefact.
Maintenant, votre processus de release est non seulement automatisé, mais aussi documenté. Du travail propre.
Utilisation de base
Pour générer un changelog pour toutes les versions :
git-cliff --output CHANGELOG.mdPour générer les notes d’une version à venir (ex. v1.1.0) :
git-cliff --tag v1.1.0 > new_release_notes.mdConfiguration
La vraie puissance de git-cliff vient de son fichier de configuration cliff.toml. Vous pouvez générer une base par défaut :
git-cliff --initÇa donne un point de départ correct.
Pour un changelog propre et professionnel, adapté à notre workflow Conventional Commits, utilisez plutôt ce cliff.toml. Minimal, mais efficace.
[changelog]
# template pour l’en‑tête du changelog
header = """
"""
# template pour le corps du changelog (Tera templates)
body = """
{% if version %}\
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%d-%b-%Y") }}
{% else %}\
## [unreleased]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | striptags | trim | upper_first }}
{% for commit in commits %}
- {% if commit.scope %}*({{ commit.scope }})* {% endif %}\
{% if commit.breaking %}[**breaking**] {% endif %}\
{{ commit.message | upper_first }}\
{% endfor %}
{% endfor %}\n
Full changelog available at [{{ previous.version }}...{{ version }}]({{ get_env(name="CI_PROJECT_URL") }}/-/compare/{{ previous.version }}...{{ version }})
"""
# template pour le pied de page
footer = """
"""
trim = true
[git]
conventional_commits = true
filter_unconventional = true
split_commits = false
commit_preprocessors = []
commit_parsers = [
{ message = "^feat", group = "<!-- 0 -->🚀 Features" },
{ message = "^fix", group = "<!-- 1 -->🐛 Bug Fixes" },
{ message = "^doc", group = "<!-- 3 -->📚 Documentation" },
{ message = "^perf", group = "<!-- 4 -->⚡ Performance" },
{ message = "^refactor", group = "<!-- 2 -->🚜 Refactor" },
{ message = "^style", group = "<!-- 5 -->🎨 Styling" },
{ message = "^test", group = "<!-- 6 -->🧪 Testing" },
{ message = "^chore\\(release\\): prepare for", skip = true },
{ message = "^chore\\(deps.*\\)", skip = true },
{ message = "^chore\\(pr\\)", skip = true },
{ message = "^chore\\(pull\\)", skip = true },
{ message = "^chore|^ci", group = "<!-- 7 -->⚙️ Miscellaneous Tasks" },
{ body = ".*security", group = "<!-- 8 -->🛡️ Security" },
{ message = "^revert", group = "<!-- 9 -->◀️ Revert" },
]
protect_breaking_commits = false
filter_commits = false
topo_order = false
sort_commits = "oldest"Ce fichier fait exactement ce qu’il faut :
- Regroupe les commits par sections logiques (
Features,Bug Fixes, etc.). - Affiche la portée (scope) et met en évidence les breaking changes.
- Filtre le bruit pour ne garder que l’utile.
- Fournit un lien vers le diff complet entre deux versions. Le template utilise une URL spécifique à GitLab; adaptez‑la dans la section
bodypour d’autres plateformes.
Vous pourrez toujours peaufiner ensuite avec la documentation officielle.