Revenir à la liste

Gérer vos versions de paquets avec semantic-release

lundi 14 février 2022-4 min de lecture

Photo de Mick Haupttoto sur Unsplash

Dans le cas d'un paquet npm, il est nécessaire de fournir un numéro de version pour celui-ci. Le modifier de façon manuel peut-être très fastidieux, c'est pourquoi j'ai favorisé l'usage d'un outil comme semantic-release pour automatiser ce processus.

Pourquoi utiliser un outil ?

En gérant manuellement la version, je dois réflechir à plusieurs choses :

  1. Est-ce que ce projet respecte une convention particulière (ex: semantic versioning)
  2. Si oui, est-ce que mes modifications correspondent à un correctif, une fonctionnalité ou un changement majeur ?
  3. Modifier les endroits où la version courante est utilisée (dans mon cas, package.json)
  4. Maintenir un changelog des changements apportés
  5. Publier le paquet sur npm
  6. Créer un tag sur git
  7. Créer une release sur github (ou autre)

Tout ceci ajoute un "mental overhead" inutile pendant la phase de fin de développement. C'est également pour cela que j'utilise toujours la même convention pour tous mes projets nécessitant d'un numéro de version.

La convention semantic versioning

C'est un principe ayant très peu de règles :

Pour une version MAJOR.MINOR.PATCH MAJOR correspond aux changements majeurs introduisant des éléments incompatibles avec l'ancienne API MINOR correspond à l'ajout de nouvelles fonctionnalités compatibles avec l'API existante PATCH correspond à des correctifs de l'API existante

Utiliser un format de message de commit

En utilisant un format spécifique dans nos messages de commit, cela permet 2 choses :

  • Avoir un historique git très explicite
  • Utiliser un outil qui analyse les commits (si vous voyez ou je veux en venir 😏)

Depuis quelques années maintenant, le format de message d'Angular est devenu très populaire.

L'usage basique étant :

<type>(<scope>): <short summary>
  │       │             │
  │       │             └─⫸ Summary in present tense. Not capitalized. No period at the end.
  │       │
  │       └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
  │                          elements|forms|http|language-service|localize|platform-browser|
  │                          platform-browser-dynamic|platform-server|router|service-worker|
  │                          upgrade|zone.js|packaging|changelog|docs-infra|migrations|ngcc|ve
  │
  └─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|test

Avec cela, un outil comme semantic-release sera capable d'analyser nos commits et d'en déterminer la version.

Mise en place et configuration

Pour ajouter semantic-release à votre projet, il faut tout d'abord créer un fichier .releaserc.json à la racine qui contiendra la configuration que vous souhaitez.

Pour notre exemple, nous allons partir du principe que notre projet est un module npm sur Github. Nous souhaitons que lorsque que l'on "push" sur notre branche principale, une CI se déclenche pour analyser nos commits et effectuer ces actions :

  • générer un fichier CHANGELOG.md
  • publier une release sur npm
  • créer un tag sur git
  • publier une release sur Github

Sans trop entrer dans les détails, et étant largement très bien documenté, voici la configuration par défaut sans ajouter de plugin :

{
  "branches": ["main"],
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    "@semantic-release/npm",
    "@semantic-release/github"
  ]
}

Les plugins s'exécutent dans l'ordre de leur définition, gardez bien en tête cela si vous souhaitez le customiser plus tard !

Avec ces plugins par défaut, on peut d'ores et déjà publier une release sur npm et publier une release sur Github. Pour le reste, nous avons des plugins spécialement conçus pour nos besoins à savoir :

  • @semantic-release/changelog : va générer le fichier CHANGELOG.md
  • @semantic-release/git : va générer un commit de version et créer un tag

La composition finale serait donc :

{
  "branches": ["main"],
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    "@semantic-release/changelog",
    "@semantic-release/npm",
    "@semantic-release/git",
    "@semantic-release/github"
  ]
}

Notre fichier de configuration est prêt, il ne reste plus qu'à configurer l'exécution dans la CI Github.

Créer une action Github

Pour créer une action Github, il faut ajouter un fichier contenant la configuration de notre action dans le dossier .github/workflows (s'il n'existe pas, à vous de le créer).

Il est tout à fait possible d'exécuter semantic-release en local. Cependant, il serait dommage de ne pas profiter d'une automatisation complète du processus.

Par chance, il existe déjà une Action Github nous facilitant grandement la tâche de configuration car celui-ci s'occupe de la phase d'installation de semantic-release et des ses plugins.

Nous pouvons créer un fichier release.yaml en prenant soin de bien synchroniser la liste des plugins supplémentaires avec notre fichier .releaserc.json :

on:
  push:
    branches:
      - main

jobs:
  release:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Semantic Release
        uses: cycjimmy/semantic-release-action@v2
        with:
          extra_plugins: |
            @semantic-release/changelog
            @semantic-release/git
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

Pour que cette action fonctionne, elle a besoin de 2 choses primordiales :

  • un GITHUB_TOKEN qui va permettre à semantic-release d'effectuer les actions Github tel que la création de release.

NOTE : ce GITHUB_TOKEN est généré automatiquement pour chaque exécution d'une CI

  • un NPM_TOKEN pour publier notre module sur npm depuis l'action.

NOTE : lors de la création de votre token npm, choisissez bien le type Automation de sorte à ne pas être restreint par l'authentification à 2 facteurs si vous l'avez activé sur votre compte npm.

Une fois votre NPM_TOKEN ajouté en tant que secret à votre repo Github, vous pouvez faire votre 1er commit de test !

Note de fin

Chaque plugin est configurable, et il en existe de nombreux ! Je vous invite à parcourir la documentation et faire les ajustements pour que cela convienne parfaitement à votre cas d'usage.