SemVer (Semantic Versioning)
- devops
- méthodologie
- versioning
Quand vous voyez "lodash": "^4.17.21" dans votre package.json, le ^ signifie "mets à jour automatiquement les versions mineures et patch". Ça ne fonctionne que parce que lodash respecte un contrat : une mise à jour en 4.x ne cassera jamais votre code. Ce contrat, c'est le Semantic Versioning.
Le format : MAJOR.MINOR.PATCH
SemVer définit trois chiffres, chacun avec une signification précise :
2.4.1
│ │ │
│ │ └── PATCH : correction de bugs (rétrocompatible)
│ └──── MINOR : nouvelle fonctionnalité (rétrocompatible)
└────── MAJOR : breaking change (incompatible)
PATCH (2.4.1 → 2.4.2) : correction d'un bug. Le comportement existant ne change pas. Mise à jour sans risque.
MINOR (2.4.1 → 2.5.0) : ajout d'une fonctionnalité. Tout le code existant continue de fonctionner. Le PATCH revient à 0.
MAJOR (2.4.1 → 3.0.0) : changement incompatible. Du code qui fonctionnait avant peut casser. MINOR et PATCH reviennent à 0.
Pourquoi c'est crucial pour les dépendances
Les gestionnaires de paquets (npm, cargo, pip, bundler) s'appuient sur SemVer pour résoudre automatiquement les versions de vos dépendances :
{
"dependencies": {
"express": "^4.18.0",
"lodash": "~4.17.0",
"react": "18.2.0"
}
}| Notation | Signification | Autorise |
|---|---|---|
^4.18.0 | Compatible avec 4.x | 4.18.1, 4.19.0, mais pas 5.0.0 |
~4.17.0 | Même mineur | 4.17.1, 4.17.21, mais pas 4.18.0 |
4.18.0 | Version exacte | Uniquement 4.18.0 |
>=4.0.0 <5.0.0 | Range explicite | Tout entre 4.0.0 et 4.x.x |
Sans SemVer, ces contraintes n'auraient aucun sens. Le ^ repose sur la promesse que MINOR et PATCH ne cassent rien. Si cette promesse n'est pas tenue, c'est toute la chaîne de dépendances qui devient imprévisible.
Les règles complètes
La spécification SemVer définit des règles précises :
- Une fois publiée, une version est immuable. Pas de modification d'une version existante — jamais.
- La version
0.x.xest spéciale : tout peut changer à tout moment. C'est la phase de développement initial. Pas de garantie de stabilité. - La version
1.0.0définit le premier contrat d'API publique stable. - Les pre-release sont marquées par un suffixe :
2.0.0-alpha.1,2.0.0-beta.3,2.0.0-rc.1. - Les metadata de build sont ajoutées après un
+:1.0.0+build.123.
Qu'est-ce qu'un breaking change ?
C'est la question la plus débattue. Un breaking change est toute modification qui peut casser du code existant qui utilisait l'API publique de manière documentée :
- Supprimer une fonction publique
- Changer la signature d'une fonction (paramètres obligatoires ajoutés)
- Modifier la valeur de retour d'une fonction existante
- Changer le comportement par défaut
- Renommer un export public
Ce qui n'est pas un breaking change :
- Ajouter une nouvelle fonction
- Ajouter un paramètre optionnel avec une valeur par défaut
- Corriger un bug (même si quelqu'un dépendait du bug)
- Améliorer les performances sans changer l'API
Les pièges courants
Rester en 0.x indéfiniment. Certains projets restent en 0.x pendant des années pour éviter de passer en 1.0. Résultat : les utilisateurs ne savent jamais si une mise à jour est safe. Si votre API est utilisée en production, passez en 1.0.
Bumper MAJOR pour des changements mineurs. Passer de 3.0.0 à 4.0.0 parce que vous avez renommé une fonction interne crée de la fatigue de version. Réservez les bumps majeurs aux vrais breaking changes qui impactent les utilisateurs.
Ne pas respecter le contrat. Introduire un breaking change dans un bump PATCH ou MINOR, c'est casser la confiance. Un utilisateur qui met à jour en ^4.0.0 et dont le code casse ne reviendra peut-être pas.
Confondre MINOR et PATCH. Une nouvelle fonctionnalité est un bump MINOR, pas PATCH — même si elle est petite. Le PATCH est réservé aux corrections de bugs.
SemVer en pratique
Pour automatiser le versioning, des outils analysent vos commits et déterminent le type de bump :
# Conventional Commits
feat: add user profile page → MINOR bump
fix: resolve login timeout → PATCH bump
feat!: redesign auth API → MAJOR bump (le ! indique un breaking change)
# Outils
# - semantic-release (JS)
# - python-semantic-release (Python)
# - cargo-release (Rust)La convention Conventional Commits (feat:, fix:, chore:) combinée avec un outil de release automatisé élimine le débat humain : le type de commit détermine le bump.
SemVer est un contrat de confiance entre le mainteneur d'un paquet et ses utilisateurs. Il permet aux outils de dépendances de faire des choix de mise à jour automatiques et sûrs. Respecter ce contrat, c'est permettre à l'écosystème de fonctionner. Le casser, c'est transformer chaque npm update en loterie.