Génération automatique de releases basée sur l'historique des messages de commits avec GitLab

L’objectif est de générer automatiquement un changelog basé sur l’historique des commits et d’alimenter les releases notes GitLab avec ce changelog.

Prérequis

La génération automatique du changelog va se baser sur les messages de commit et nécessite pour cela l’utilisation de la norme Commits Conventionnels.

Pour faire simple, cette norme définit une liste de préfixes dans les messages de commits pour permettre de les catégoriser. Les préfixes disponibles sont par exemple fix:, feat:, docs:, style:, refactor:, etc.

Une fois le bon préfixe choisit, il vous suffit d’ajouter un descriptif libre. C’est ce descriptif qui sera alors utilisé dans le changelog. Exemple : feat: automatic release note generation based on commits.

Génération du changelog avec git-cliff

Maintenant que notre historique de commits est propre et suit la convention Commits Conventionnels, nous allons pouvoir passer à la génération du changelog et pour cela, nous allons utiliser git-cliff.

Présentation de git-cliff

git-cliff est un outil dont l’objectif est de générer le changelog en prenant l’historique des commits et de fournir le résultat au format Markdown. Les commits sont ainsi regroupés en fonction de la version et du type de commit (fix:, feat:, etc.).

Une image Docker de git-cliff permet de l’exécuter en local grâce à la commande suivante à partir de la racine de votre projet Git :

docker run --rm -t -v $(pwd)/.git:/app/ orhunp/git-cliff

Un exemple de fichier résultat :

# Changelog

## [unreleased]

### Features

- Automatic release note generation based on commits

## [1.0.0] - 2022-06-23

### Features

- Initial commit
- Creating a Hadoop TDP cluster on AWS

### Styling

- Update font-color
- Update profil picture

Il est possible de personnaliser le résultat en modifiant le fichier de configuration pour, par exemple, traduire ou modifier les titres associés à chacune des catégories.

Pour plus d’informations sur la personnalisation du résultat, je vous renvoie au README du projet git-cliff.

Intégration dans un pipeline GitLab

Afin d’automatiser la génération de ce changelog en vue de l’intégrer dans les notes de versions, nous allons donc ajouter un job dans le pipeline GitLab :

build:changelog:
  stage: build
  image:
    name: orhunp/git-cliff:latest
    entrypoint: [""]
  before_script:
    - apt update
    - apt install -y git
    - export PREVIOUS_TAG=`git describe --abbrev=0 HEAD~`
    - echo ${PREVIOUS_TAG}
  script:
    - |
      if [ -z "${PREVIOUS_TAG}" ]; then
        git-cliff -c config/cliff.toml > CHANGELOG.md
      else
        git-cliff -c config/cliff.toml -r . ${PREVIOUS_TAG}.. > CHANGELOG.md
      fi
  needs: []
  cache:
    key: ${CI_COMMIT_REF_SLUG}-CL
    policy: push
    paths:
      - CHANGELOG.md
  variables:
    GIT_STRATEGY: clone # clone entire repo instead of reusing workspace
    GIT_DEPTH: 0 # avoid shallow clone to give cliff all the info it needs

Par défaut, l’outil git-cliff génère le changelog complet. Comme nous ne souhaitons avoir que le changelog de la version courante, nous récupérons dans la variable PREVIOUS_TAG le tag précédent via la commande git describe --abbrev=0 HEAD~. Il nous suffit ensuite de spécifier à git-cliff que nous souhaitons générer le changelog à partir du tag précédent jusqu’au commit courant.

Le fichier résultat au format Markdown est ensuite ajouté au cache du pipeline.

Génération de la release

La dernière étape de notre pipeline une fois le fichier de changelog généré consiste à créer la release. Pour cela, GitLab met à disposition une image dédiée qui sera parfaite pour notre usage :

deploy:release:
  stage: deploy
  image: registry.gitlab.com/gitlab-org/release-cli:latest
  before_script: []
  script:
    - echo 'running release_job'
  needs: [
    "build:changelog",
  ]
  cache:
    key: ${CI_COMMIT_REF_SLUG}-CL
    policy: pull
    paths:
      - CHANGELOG.md
  release:
    name: '${CI_COMMIT_TAG}'
    description: 'CHANGELOG.md'
    tag_name: '${CI_COMMIT_TAG}'
    ref: '${CI_COMMIT_TAG}'
  rules:
    - if: $CI_COMMIT_TAG

Le fichier de changelog généré lors de l’étape précédente est alors extrait pour alimenter la description de la release. À noter que si le job build:changelog s’exécutait à chaque commit poussé dans le projet GitLab, nous avons ici logiquement limité l’exécution du job deploy:release à la présence d’un tag.

Conclusion

Grâce à ces deux jobs qui peuvent être ajoutés dans n’importe quel pipeline GitLab, il est possible de créer automatiquement une release avec le changelog de votre projet.

Il ne reste plus qu’à soigner les messages de commits pour permettre d’avoir un changelog parfait associé aux releases !