Ingénierie

Des conventional commits à un changelog

6 min de lecture mis à jour le

Les conventional commits offrent gratuitement trois choses à un changelog : le type de chaque changement, la partie du système touchée, et si ça casse quelque chose. Ils n’offrent rien d’autre. La formulation, le regroupement et la sélection, qui sont le changelog, restent entièrement ouverts, et un pipeline qui prétend le contraire livre un git log formaté.

feat(exports): add CSV column selection
fix(auth): reject expired refresh tokens
chore(deps): bump node-pg to 8.11

Trois commits au format Conventional Commits. À partir de ceux-ci, une machine peut vous dire qu’un est une fonctionnalité, un est une correction, un est du ménage, et quelle partie du système chacun a touché. C’est vraiment utile, et c’est toute la promesse de la convention : un historique de commits lisible par autre chose qu’une personne. L’erreur est de penser que ça vous donne un changelog. Ça vous donne la matière première.

Que spécifie la convention ?

Un type, un scope optionnel, et une description : type(scope): description. Les types sont conventionnellement feat, fix, chore, docs, refactor, test, perf, build, ci. Deux choses marquent un changement cassant : un ! avant les deux-points, ou un footer BREAKING CHANGE:. Les outils se basent sur feat et fix pour les bumps de version mineure et patch, et sur le marqueur breaking pour une majeure.

Le commit vous donneLe changelog a besoin deQui comble l’écart
feat / fix / choreAdded / Fixed / interneUn mapping, automatique
(scope)Un regroupement que le lecteur reconnaîtUne personne, une fois par scope
! ou BREAKING CHANGE:Qui casse, pour quand, et quoi faireUne personne, à chaque fois
La description, écrite pour une revieweuseLe résultat, écrit pour une clienteUne personne, chaque entrée
Un commitUn changement, qui peut être plusieurs commitsRègles de squash, ou une personne

Le marqueur le dit à l’outil ; il ne le dit pas à l’appelant, ce qui est le sujet de comment déprécier une API et qu’est-ce qu’un changement cassant. C’est une petite spec et ça vaut la peine de la suivre même si vous n’en générez jamais rien, parce qu’elle force une décision par commit : est-ce un changement que les utilisateurs voient, ou non.

Où s’arrêtent les conventional commits ?

Ils s’arrêtent à la phrase. Tout ce que la convention capture, ce sont des métadonnées sur un changement ; le changement lui-même est toujours décrit dans le vocabulaire d’une revieweuse.

Les messages de commit sont écrits pour des revieweuses. fix(auth): reject expired refresh tokens est correct et ne dit rien à une cliente. La lectrice d’un changelog veut “vous serez déconnecté quand une session a vraiment expiré, au lieu de voir des 401 intermittents”.

Les scopes sont internes. exports, auth, ingest sont des noms de modules. Ils sont stables, ce qui les rend bons pour regrouper, et sans signification pour quiconque en dehors de la codebase.

Un changement, c’est souvent plusieurs commits. Une fonctionnalité mergée sur onze commits produit onze entrées, dix desquelles du bruit, et les écraser pour cacher ça perd l’historique de revue.

chore est un fourre-tout, pas une catégorie. Mises à jour de dépendances, changements CI et renommages atterrissent tous là, et certains comptent pour les utilisateurs alors que la plupart non.

Donc : la convention vous donne gratuitement type, scope et statut breaking, et laisse la formulation, le regroupement et la sélection entièrement ouverts. Ces trois-là sont le changelog. À qui appartient vraiment une entrée de changelog couvre qui devrait s’occuper de cette formulation, ce regroupement et cette sélection, puisque la convention elle-même n’a aucun avis là-dessus.

Comment génère-t-on un changelog à partir de conventional commits ?

En deux couches, et la seconde doit être obligatoire.

Couche un, automatique. Au merge, dérivez une entrée brouillon du commit : type mappé sur un type de changelog (feat sur Added, fix sur Fixed, un marqueur breaking sur Changed plus un flag), scope gardé comme métadonnée plutôt que comme texte, lien vers la PR. Faites-la atterrir dans la section Unreleased que demande Keep a Changelog.

Couche deux, humaine, et requise. Avant qu’une version sorte, chaque entrée brouillon reçoit soit une réécriture d’une ligne dans le vocabulaire de l’utilisateur, soit est marquée interne et retirée de la vue publique. C’est l’étape que les gens essaient de sauter, et la sauter est ce qui produit des changelogs qui se lisent comme un diff.

Le détail de design important est que la couche deux n’est pas optionnelle dans le pipeline. Si une version peut être taillée avec des brouillons non édités, elle le sera, la semaine où tout le monde est occupé. Quelles étapes appartiennent à la machine et lesquelles à la personne, c’est tout le sujet de l’automatisation du changelog.

Tailler la release est aussi le moment où un tag git, une release et cette entrée de changelog s’accordent ou commencent à diverger ; tags git, releases et votre changelog couvre comment garder les trois synchronisés.

Trois pièges

Les squash merges mangent les footers. Si votre plateforme écrase avec le titre de la PR comme message, le footer BREAKING CHANGE: d’un commit à l’intérieur de cette branche disparaît, et votre outillage cesse silencieusement de voir le changement cassant. Vérifiez ce que votre template de squash garde vraiment.

Les commits de revert produisent des entrées fantômes. Un fix qui est reverté le lendemain génère une entrée pour quelque chose qui n’a jamais été livré, sauf si la dérivation réconcilie les reverts. La plupart des outils ne le font pas.

Le bump de version et le changelog se désynchronisent. Si la version est calculée à partir des commits et le changelog écrit à la main après, ils divergent en environ deux versions. Calculez les deux dans la même passe ou acceptez que l’un des deux soit faux.

Si vous voulez la partie mécanique sans pipeline

Notre générateur de changelog fait l’étape de dérivation dans le navigateur : collez des commits, obtenez des entrées regroupées et typées en sortie. C’est délibérément déterministe et entièrement côté client, donc les commits que vous collez ne quittent jamais votre machine, ce qui compte quand les messages viennent d’un repository privé. Ça fait honnêtement la moitié collecte et ne tente pas la couche deux, parce que la couche deux est un jugement et un outil qui la simule produit exactement le changelog contre lequel cet article argumente.

Pour la version pipeline, outils de changelog couvre ce qui existe.

Le résumé

Les conventional commits répondent “quel type de changement est-ce” de manière fiable et bon marché. Ils ne répondent pas “que devrait-on dire aux gens”, et aucune quantité d’outillage au-dessus du message de commit ne le fera, parce que l’information n’a jamais été dans le message de commit. Budgétez la réécriture.

FAQ

Les conventional commits génèrent-ils automatiquement un changelog ? Ils génèrent automatiquement un brouillon : entrées typées, avec scope, liées. La formulation pour une cliente, le regroupement et la décision de ce qu’il faut laisser de côté ont toujours besoin d’une personne, et un pipeline qui saute cette étape publie des messages de commit.

Quels types de conventional commit apparaissent dans un changelog ? feat et fix toujours, comme Added et Fixed. perf généralement, comme Changed. chore, docs, refactor, test, build et ci sont internes par défaut et n’apparaissent que si une personne en promeut un.

Comment les conventional commits marquent-ils un changement cassant ? Un ! après le type ou le scope (feat(api)!: ...), ou un footer BREAKING CHANGE: dans le corps du commit. Les deux se perdent si un squash merge ne garde que le titre de la PR.

A-t-on besoin de conventional commits pour automatiser un changelog ? Non. Les labels de PR, les templates de PR et les liens d’issues portent les mêmes métadonnées pour les équipes qui mergent par pull request. Les conventional commits sont l’option la moins chère quand l’unité de changement est le commit.


Les affirmations techniques de cet article n'ont pas été vérifiées de façon indépendante. Si quelque chose est faux, dis-le-nous et nous le corrigerons.

À voir sur changeloop : Générateur de changelog, Comparatif d'outils de changelog

changeloop
L'équipe qui construit un changelog qui boucle la boucle. Tes utilisateurs demandent, ton équipe livre, la personne qui a demandé est prévenue.