Chapitre 921 minIntermédiaire
Versions, changelog et mises à jour des dépendances
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- choisir la bonne branche pour un correctif ou un hotfix ;
- calculer le numéro de la version suivante avec SemVer ;
- rédiger une entrée de changelog utile ;
- lire les plages de versions de package.json et composer.json ;
- auditer et mettre à jour les dépendances sans casser l'application.
5 exercices corrigés1 schéma
Livrer une correction ou une évolution, c'est produire une version : un état du code identifié par un numéro (1.4.3), marqué dans Git par un tag, et décrit dans un changelog, le journal des modifications lisible par un humain. Maintenir une application, c'est aussi garder à jour ses dépendances, les bibliothèques qu'elle utilise, et son environnement (PHP, Node.js), sans introduire de régression ni laisser traîner de faille connue. Ce chapitre montre quelle branche utiliser pour un correctif, comment numéroter avec le versionnage sémantique (SemVer), rédiger un changelog utile, lire les plages de versions, et auditer et mettre à jour les dépendances avec npm et Composer.
Suivre les informations d'une version
Quand un utilisateur signale un bug, la première question est : quelle version utilise-t-il ? La réponse doit être facile à trouver, et elle doit mener au code exact.
- Le numéro de version figure dans
package.json(champversion), et l'application l'affiche quelque part : en pied de page, dans un menu « À propos », ou par une route d'API (GET /api/version). - Le tag Git (
v1.4.2) marque le commit exact livré sous ce numéro.git switch --detach v1.4.2te ramène au code que l'utilisateur a sous les yeux, etgit describe --tagste dit où tu en es par rapport au dernier tag. - Le changelog dit ce que contient chaque version et ce qui a changé depuis la précédente.
- Les tickets, les commits et les versions se répondent : le commit cite le ticket (
fix(notes): … (#231)), le changelog cite le ticket, et le ticket est fermé avec le numéro de la version qui le corrige.
Cette traçabilité est exactement ce que le référentiel appelle « recueillir, analyser et mettre à jour les informations sur une version d'une solution applicative ». Les bases (créer et pousser un tag, publier une release sur GitHub) sont détaillées dans le cours Git et GitHub.
Quelle branche pour un correctif ?
Le chemin d'un correctif dépend de l'état de la branche principale par rapport à la production.
| Situation | Branche de départ | Après la correction |
|---|---|---|
Correctif ordinaire : main peut partir en production telle quelle | main → fix/231-total-note | Pull request, fusion dans main, prochaine version corrective |
Correctif urgent (hotfix) : la production est en 1.4.2, mais main contient déjà des évolutions pas prêtes à livrer | Le tag v1.4.2 → hotfix/1.4.3 | Tag v1.4.3, livraison, puis report de la correction dans main |
Maintenance d'une ancienne version : un client reste en 1.x alors que la 2.x est sortie | Une branche de support support/1.x | Correction dans support/1.x et dans main |
Le cas du hotfix est celui qui demande le plus de rigueur :
git switch -c hotfix/1.4.3 v1.4.2 # part du code exact en production
# … le test qui reproduit le bug, la correction, la suite verte …
git commit -m "fix(notes): additionne les montants DECIMAL reçus en texte (#231)"
git tag -a v1.4.3 -m "Version 1.4.3 : total des notes (#231)"
git push origin hotfix/1.4.3 v1.4.3 # la version corrective part en production
git switch main
git cherry-pick <sha-du-commit-fix> # la même correction, reportée dans main
La dernière étape est celle qu'on oublie. Sans elle, la prochaine version issue de main réintroduira le bug corrigé en urgence : une régression livrée avec la meilleure volonté du monde. git cherry-pick recopie un commit précis sur la branche courante ; on peut aussi fusionner la branche de hotfix dans main. Dans le modèle Git Flow, c'est la règle : une branche hotfix part de main et revient à la fois dans main et dans develop (workflows Git).
Numéroter la version : SemVer appliqué à la maintenance
Le versionnage sémantique (SemVer) donne un sens à chaque partie du numéro MAJEUR.MINEUR.CORRECTIF. Pour la maintenance, la règle se lit directement depuis le type de changement.
| Type de maintenance | Changement | Nouvelle version depuis 1.4.2 |
|---|---|---|
| Corrective | Correction rétrocompatible | 1.4.3 |
| Évolutive, additive | Fonctionnalité ajoutée sans rien casser | 1.5.0 |
| Évolutive ou adaptative, cassante | Route supprimée, format de réponse modifié, version de Node.js minimale relevée | 2.0.0 |
| Préventive (refactoring, tests, documentation) | Aucun changement de comportement | Pas de nouvelle version à elle seule ; elle part avec la suivante |
Quand une version regroupe plusieurs changements, le plus fort l'emporte : trois corrections et une fonctionnalité donnent une version mineure ; une correction et un changement cassant donnent une version majeure. Quand un chiffre augmente, ceux de droite reviennent à 0 : après 1.4.3, une fonctionnalité donne 1.5.0, pas 1.5.3.
Avec npm, une commande met à jour le numéro dans package.json et package-lock.json, crée le commit et pose le tag :
npm version patch -m "Version %s : total des notes (#231)" # 1.4.2 → 1.4.3
npm version minor # 1.4.3 → 1.5.0
npm version major # 1.5.0 → 2.0.0
Le %s est remplacé par le nouveau numéro. Côté PHP, une application n'écrit en général pas sa version dans composer.json : c'est le tag Git qui la porte, et l'application peut la lire depuis un fichier généré au déploiement ou depuis une constante.
Rédiger le changelog
Le changelog s'adresse aux personnes qui utilisent ou exploitent l'application : le support, les autres développeurs, parfois les utilisateurs eux-mêmes. Il répond à une question : qu'est-ce qui a changé, et est-ce que ça me concerne ? Le format le plus répandu, Keep a Changelog, range les changements de chaque version en six rubriques.
| Rubrique | Ce qu'on y met | Commit correspondant |
|---|---|---|
| Ajouté | Les nouvelles fonctionnalités | feat |
| Modifié | Les changements d'une fonctionnalité existante | feat, refactor visible |
| Obsolète | Ce qui fonctionne encore mais sera supprimé dans une prochaine version | — |
| Supprimé | Ce qui a été retiré | — |
| Corrigé | Les bugs corrigés | fix |
| Sécurité | Les vulnérabilités corrigées | fix, mise à jour de dépendance |
# Changelog
Les changements notables de Sorbier Frais sont listés dans ce fichier.
Format : Keep a Changelog. Numérotation : versionnage sémantique.
## [Non publié]
### Ajouté
- Badge « hors délai » sur les notes clôturées après le 10 du mois suivant (#257).
## [1.5.0] - 2026-11-16
### Ajouté
- Le comptable peut refuser une ligne de frais en indiquant un motif ; le salarié
voit l'état et le motif de chaque ligne (#250).
### Modifié
- Le total remboursé et l'export comptable excluent les lignes refusées (#250).
### Corrigé
- Le récapitulatif mensuel de février à septembre était vide, et celui de janvier
contenait les frais d'octobre à décembre (#238).
### Sécurité
- Mise à jour de jsonwebtoken en version 9 : l'ancienne acceptait des clés trop faibles.
## [1.4.3] - 2026-11-03
### Corrigé
- Le total d'une note affichait des montants collés (« 012.5019.90 ») au lieu
de leur somme (#231).
Quelques règles font la différence entre un changelog utile et une liste de commits recopiée :
- écrire pour le lecteur, pas pour le développeur : « le total d'une note affichait des montants collés », plutôt que « fix reduce sur string dans totalNote » ;
- regrouper et trier : une correction qui a demandé six commits tient en une ligne ;
- citer le ticket, pour qui veut les détails ;
- dater chaque version au format
AAAA-MM-JJ, la plus récente en haut ; - signaler clairement ce qui casse : une version majeure explique ce que les utilisateurs de l'API doivent changer ;
- alimenter la section « Non publié » au fil des pull requests, pour ne pas reconstituer l'historique de mémoire le jour de la livraison.
Les plages de versions des dépendances
Dans package.json ou composer.json, une dépendance n'est pas déclarée par une version unique, mais par une plage de versions acceptées. Le gestionnaire choisit la plus récente qui respecte la plage.
| Écriture | Versions acceptées | Logique |
|---|---|---|
"5.1.0" | 5.1.0 seulement | Version exacte |
"~5.1.0" | de 5.1.0 à 5.1.x, pas 5.2.0 | Correctifs seulement |
"^5.1.0" | de 5.1.0 à 5.x.y, pas 6.0.0 | Correctifs et fonctionnalités, jamais de changement majeur |
"^0.4.2" | de 0.4.2 à 0.4.x, pas 0.5.0 | En version 0, le deuxième chiffre est traité comme un majeur |
"5.1.x" ou "5.1.*" | toute version 5.1.x | Joker sur le correctif |
">=5.1.0 <6.0.0" | de 5.1.0 inclus à 6.0.0 exclu | Plage explicite |
Le ^ est le choix par défaut de npm install et de composer require. Il repose sur une promesse : un auteur qui respecte SemVer ne casse rien entre deux versions mineures. Promesse souvent tenue, pas toujours. C'est pourquoi le fichier de verrouillage existe : package-lock.json et composer.lock notent la version exacte installée de chaque dépendance, directe ou transitive. Ils doivent être commités. npm ci et composer install installent exactement ces versions ; npm update et composer update choisissent des versions plus récentes dans les plages, et réécrivent le fichier de verrouillage.
Mettre à jour les dépendances
Mettre à jour les dépendances régulièrement coûte peu ; les laisser vieillir trois ans coûte très cher, parce qu'il faut alors franchir plusieurs versions majeures d'un coup. Une routine, par exemple mensuelle, garde le projet à jour.
npm outdated # ce qui a une version plus récente
Package Current Wanted Latest Location Depended by
jsonwebtoken 8.5.1 8.5.1 9.0.2 node_modules/jsonwebtoken sorbier-frais-api
mysql2 3.11.0 3.11.5 3.11.5 node_modules/mysql2 sorbier-frais-api
Current est la version installée, Wanted la plus récente que permet la plage du package.json, Latest la dernière publiée (les numéros de l'extrait sont indicatifs). Deux situations :
- Wanted plus récent que Current (mysql2 ici) : une mise à jour dans la plage, correctif ou mineure.
npm update mysql2, puis les tests. - Latest plus récent que Wanted (jsonwebtoken ici) : une nouvelle version majeure, hors de la plage. Elle peut casser ton code : lis son changelog et son guide de migration, puis
npm install jsonwebtoken@9sur une branche dédiée, adapte le code, lance les tests.
Côté PHP, les commandes équivalentes :
composer outdated --direct # seulement les dépendances déclarées par le projet
composer update monolog/monolog --with-dependencies # met à jour un paquet dans sa plage
composer require --dev "phpunit/phpunit:^13.0" -W # passe à une nouvelle version majeure (ici de PHPUnit 12 à 13)
Pour ne pas dépendre de la mémoire de chacun, des robots ouvrent eux-mêmes une pull request quand une dépendance a une nouvelle version : Dependabot sur GitHub, Renovate ailleurs. L'intégration continue lance les tests sur cette pull request ; il ne reste qu'à lire le changelog de la dépendance et à fusionner si tout est vert.
Les vulnérabilités : npm audit et composer audit
Une dépendance peut contenir une faille de sécurité connue, publiée avec un identifiant CVE et une note de gravité. Les gestionnaires de paquets comparent tes versions installées aux bases d'avis de sécurité :
npm audit # liste les vulnérabilités connues des paquets installés
npm audit --omit=dev # seulement celles des dépendances de production
npm audit fix # applique les mises à jour qui restent dans les plages
composer audit # l'équivalent pour Composer (depuis Composer 2.4)
npm audit fix ne fait que les mises à jour compatibles avec tes plages. Quand la correction exige une version majeure, npm propose npm audit fix --force : la commande installe cette version majeure sans te demander ton avis, ce qui peut casser l'application. Traite plutôt ce cas comme une mise à jour majeure ordinaire, sur une branche, avec les tests.
Face à un avis de sécurité, la démarche est toujours la même :
- Lire l'avis : quelle fonction de la bibliothèque est vulnérable, dans quelles conditions, à partir de quelle version c'est corrigé.
- Évaluer l'exposition : ton application utilise-t-elle la fonction vulnérable ? La dépendance est-elle en production, ou seulement dans les outils de développement ?
- Corriger : mettre à jour vers une version corrigée, ou, s'il n'en existe pas, remplacer la bibliothèque, ou neutraliser l'usage vulnérable en attendant.
- Tracer : un commit dédié, une entrée Sécurité dans le changelog, une version corrective livrée vite si la faille est exploitable.
Le cours Sécurité applicative détaille la chaîne d'approvisionnement logicielle : lire une fiche CVE et son score CVSS, Dependabot, l'inventaire des composants (SBOM) et les attaques par paquet piégé.
Les mises à jour de l'environnement : la maintenance adaptative
Les langages et les plateformes ont un cycle de vie, et une version qui ne reçoit plus de correctifs de sécurité doit être quittée.
- Node.js publiait jusqu'ici deux versions majeures par an, dont seules les paires devenaient LTS (Long Term Support, environ trente mois de maintenance). Depuis octobre 2026, le projet passe à une seule version majeure par an, publiée en avril et promue LTS en octobre : toutes deviennent LTS, à commencer par Node.js 27 (2027). Node.js 20 n'est plus maintenu depuis avril 2026 : une API qui tourne encore dessus doit passer en Node.js 24 ou 26.
- PHP publie une version par an, chaque fin d'année. Chacune reçoit deux ans de correctifs, puis deux ans de correctifs de sécurité seulement. La page Supported Versions du site php.net donne les dates ; le site endoflife.date les rassemble pour la plupart des langages, frameworks et systèmes.
Une montée de version suit la même démarche qu'une mise à jour de dépendance majeure : lire le guide de migration (le manuel PHP a une annexe « Migration » pour chaque version), mettre à jour l'environnement de développement et l'intégration continue, lancer les tests, lire les avertissements de dépréciation dans les journaux. Une fonctionnalité dépréciée marche encore, mais sera supprimée dans une version future : c'est le moment de la corriger. Par exemple, PHP 8.4 a déprécié les paramètres implicitement nullables :
<?php
// Déprécié depuis PHP 8.4 : le type Utilisateur accepte null sans le dire
function journaliser(string $message, Utilisateur $auteur = null): void { /* … */ }
// À écrire : le ? rend explicite que null est permis
function journaliser(string $message, ?Utilisateur $auteur = null): void { /* … */ }
Le code ancien fonctionne toujours en PHP 8.4, mais il produit un avertissement E_DEPRECATED, et il cessera de fonctionner dans une version majeure future. Corriger ces dépréciations au fil de l'eau, c'est de la maintenance préventive ; attendre qu'elles cassent, c'est de la corrective en urgence.
Exercices
Exercice 1 sur 5 La version suivante Réussi À revoir
Sorbier Véhicules est en version 2.1.0. Donne le numéro de chaque nouvelle version, livrée dans l'ordre.
- Correction du bug de chevauchement des réservations.
- Correction d'une faute d'orthographe dans un message, et correction de l'export du planning.
- Ajout d'une destination facultative sur les réservations.
- Correction d'un bug sur la destination, et ajout d'un filtre par destination.
- Suppression de l'ancienne route
/reserver.php, remplacée depuis longtemps par/index.php?action=reserver. - Mise en place de tests automatisés sur le calcul de disponibilité, sans changement de comportement.
Voir la réponseMasquer la réponse de l'exercice 1
2.1.1: une correction.2.1.2: deux corrections, une version corrective.2.2.0: une fonctionnalité rétrocompatible ; le correctif revient à 0.2.3.0: le changement le plus fort (une fonctionnalité) l'emporte sur la correction.3.0.0: une route supprimée casse les liens et les scripts qui l'utilisaient. Elle aurait dû être annoncée dans la rubrique Obsolète d'une version précédente.- Pas de nouvelle version à elle seule : aucun comportement ne change. Les tests partiront avec la prochaine version, sans entrée de changelog (ou une ligne interne si l'équipe le souhaite).
Tu avais trouvé ?
Exercice 2 sur 5 Du git log au changelog Réussi À revoir
Voici les commits fusionnés dans main depuis la version 1.5.0 de Sorbier Frais :
a1f3e2c fix(export): échappe les points-virgules dans les libellés (#259)
77b0c41 test(export): couvre les libellés avec point-virgule
3c9d8aa feat(notes): badge « hors délai » sur les notes clôturées en retard (#257)
e52b917 refactor(remboursement): extrait le calcul kilométrique
9d04f6b build(deps): met à jour express en 5.1.x (correctif de sécurité)
c18a7e3 fix(notes): le badge hors délai s'affichait sur les notes non clôturées (#257)
- Quel numéro aura la prochaine version ?
- Rédige son entrée de changelog.
Voir la réponseMasquer la réponse de l'exercice 2
1.6.0: il y a une fonctionnalité (feat), le changement le plus fort.- Par exemple :
## [1.6.0] - 2026-11-30
### Ajouté
- Badge « hors délai » sur les notes clôturées après le 10 du mois suivant (#257).
### Corrigé
- L'export CSV était décalé quand un libellé contenait un point-virgule (#259).
### Sécurité
- Mise à jour d'Express pour intégrer un correctif de sécurité.
Le refactoring et le test n'apparaissent pas : ils ne changent rien pour les utilisateurs. Le correctif c18a7e3 non plus, car il corrige un défaut de la fonctionnalité #257 avant même sa première livraison : pour les utilisateurs, le badge arrive directement sans ce bug.
Tu avais trouvé ?
Exercice 3 sur 5 Les plages de versions Réussi À revoir
Pour chaque plage, dis si la version proposée est acceptée.
^1.4.2et1.9.0^1.4.2et2.0.0~1.4.2et1.4.9~1.4.2et1.5.0^0.4.2et0.5.0^2.1.0et2.1.0-beta.1
Voir la réponseMasquer la réponse de l'exercice 3
- Oui : même version majeure, et
1.9.0est supérieure à1.4.2. - Non :
^refuse une nouvelle version majeure. - Oui :
~accepte les correctifs de1.4. - Non :
~1.4.2n'accepte pas de nouvelle version mineure. - Non : en version 0,
^traite le deuxième chiffre comme un majeur, et n'accepte que les0.4.x. - Non :
2.1.0-beta.1est une préversion, antérieure à2.1.0. Elle est en dessous de la borne basse, et npm n'installe une préversion que si la plage en mentionne une explicitement.
Tu avais trouvé ?
Exercice 4 sur 5 Un avis de sécurité Réussi À revoir
npm audit sur Sorbier Frais signale une vulnérabilité de gravité élevée dans une bibliothèque de traitement d'images, utilisée uniquement par l'outil qui génère les captures d'écran de la documentation (une dépendance de développement). La correction existe dans une nouvelle version majeure. Que fais-tu, et dans quel ordre ?
Voir la réponseMasquer la réponse de l'exercice 4
- Lire l'avis : la fonction vulnérable, les conditions d'exploitation, la version corrigée.
- Évaluer l'exposition : la bibliothèque n'est pas livrée en production (
npm audit --omit=devne la signale pas) ; elle ne traite que des images produites par l'équipe. Le risque est faible, mais il n'est pas nul : un outil de développement qui s'exécute sur les postes ou dans l'intégration continue peut être une porte d'entrée. - Planifier la mise à jour majeure sur une branche dédiée, vérifier que la génération de captures fonctionne toujours, puis fusionner. Pas besoin d'un hotfix en production : rien ne change pour les utilisateurs.
- Ne pas lancer
npm audit fix --forcesurmainsans regarder : il installerait la version majeure sans vérification. - Tracer : un commit
build(deps): …, et la décision notée dans le ticket.
Si la même faille touchait une dépendance de production utilisée sur les images envoyées par les salariés (les justificatifs), la priorité serait maximale : correction immédiate et version corrective livrée dans la journée.
Tu avais trouvé ?
Exercice 5 sur 5 Un hotfix Réussi À revoir
La production tourne en 1.5.0 (tag v1.5.0). La branche main contient déjà deux fonctionnalités non livrées. Un bug bloque la validation des notes. Écris la suite de commandes Git, depuis la création de la branche jusqu'au report de la correction dans main.
Voir la réponseMasquer la réponse de l'exercice 5
git switch -c hotfix/1.5.1 v1.5.0
# écrire le test qui reproduit le bug, corriger, lancer toute la suite
git add .
git commit -m "fix(validation): … (#264)"
git tag -a v1.5.1 -m "Version 1.5.1 : validation des notes (#264)"
git push origin hotfix/1.5.1 v1.5.1
# livraison de la 1.5.1 en production
git switch main
git cherry-pick <sha-du-commit-fix>
git push origin main
La branche part du tag v1.5.0, pas de main, pour ne pas livrer les deux fonctionnalités inachevées. Le cherry-pick reporte la correction dans main ; on peut aussi fusionner hotfix/1.5.1 dans main. Sans cette dernière étape, la version 1.6.0 réintroduirait le bug. Et le changelog reçoit une section [1.5.1] avec la correction.
Tu avais trouvé ?