Versionnage sémantique

Il y a un comportement que je considère comme pratiquement universel chez les développeurs. Lorsqu’on se donne la peine d’y porter attention, il devient clair et limpide que nous le faisons à peu près tous. Cela fait comme partie du processus de développement logiciel. Un peu comme si cela était implicite. Un peu comme la règle non écrite que tous se doivent de suivre.

Vous vous doutez bien de ce que je veux introduire. Nous donnons des numéros de version à tout ce que nous produisons.

Parfois ce sera une version Alpha ou Beta. Une autre fois ce sera une version 0.1. Toutefois, le moment tant attendu sera celui de la version 1.0. Celui de la sortie officielle, loin d’être finale.

Il peut être amusant de donner à brûle-pourpoint des numéros de version. Dans la très grande majorité des cas, ce numéro de version sera sans incidence. On s’en branle un peu non? Le code compile. C’est tout ce qui nous préoccupe.

La nécessité d’avoir une logistique de versionnage plus rigoureuse s’impose lorsqu’il vient le temps de maintenir un bout de code qui sera utilisé en dépendance pour d’autres logiciels. La question devient soudainement différente. Comment je vais communiquer l’importance de mes changements et ainsi que le risque associé à la mise à jour à une version en particulier?

La sémantique

Le versionnage sémantique vise à imposer une structure aux numéros de version qui seront donnés à votre logiciel. Chacun des éléments qui composeront un numéro de version a un but particulier ayant pour but de communiquer l’intention de cette version.

Le document initial a douze règles régissant la mise en oeuvre des numéros de versions. Je vous fais part d’une traduction libre, tirée d’un fork GitHub de la part de DudePascalou.

Les mots clés « DOIT », « NE DOIT PAS », « OBLIGATOIRE », « DEVRAIT », « NE DEVRAIT PAS », « RECOMMANDÉ », « PEUT », et « OPTIONNEL » dans ce document doivent être interprétés comme décrit dans la RFC 2119.

  1. Tout logiciel utilisant le Versionnement Sémantique DOIT déclarer une API publique. Cette API peut être déclarée dans le code lui-même ou dans un document. Dans tous les cas, elle doit être précise et claire.
  2. Un numéro de version standard DOIT prendre la forme X.Y.Z où X, Y et Z sont des entiers non négatifs. X est la version majeure, Y est la version mineure, et Z est la version de patch. Chaque élément DOIT augmenter numériquement par incréments d’une unité. Par exemple : 1.9.0 -> 1.10.0 -> 1.11.0.
  3. Quand un numéro de version majeur est incrémenté, la version mineure et la version patch DOIVENT être remises à zéro. Quand un numéro de version mineur est incrémenté, la version patch DOIT être remise à zéro. Par exemple: 1.1.3 -> 2.0.0 et 2.1.7 -> 2.2.0.
  4. Une fois qu’une version d’un composant est publiée, le contenu de cette version NE DOIT PAS être modifié. Toute modification doit être publiée comme une nouvelle version.
  5. La version majeure zéro (0.y.z) sert au développement initial. Tout peut changer à tout moment. L’API publique ne devrait pas être considérée comme stable.
  6. La version 1.0.0 définit l’API publique. La façon dont le numéro de version est incrémenté après la publication est dépendante de cette API publique.
  7. La version de patch Z (x.y.Z | x > 0) DOIT être incrémentée si des corrections d’anomalies rétro-compatibles sont effectuées. Une correction d’anomalie est définie comme un changement interne qui corrige un comportement incorrect.
  8. La version mineure Y (x.Y.z | x > 0) DOIT être incrémentée si une nouvelle fonctionnalité rétro-compatible est introduite dans l’API publique. Elle DOIT être incrémentée si une fonctionnalité de l’API publique est marquée comme obsolète. Elle PEUT être incrémentée si une nouvelle fonctionnalité ou amélioration est introduite dans le code privé. Elle PEUT inclure des changements de niveau de patch. La version de patch DOIT être remise à 0 lorsque la version mineure est incrémentée.
  9. La version majeure X (X.y.z | X > 0) DOIT être incrémentée si des changements rétro-incompatibles sont introduits à l’API publique. Elle PEUT inclure des changements mineurs et de patch. Les numéros de version de patch et mineurs DOIVENT être remis à 0 lorsque la version majeure est incrémentée.
  10. Une version admissible (de l’anglais pre-release) PEUT être notée par l’ajout d’un tiret et une série d’identifiants séparés par des points suivant immédiatement la version de patch. Les identifiants DOIVENT être composés uniquement de caractères alphanumériques ASCII et de tirets [0-9A-Za-z-]. Des versions admissibles sont utilisables et précèdent la version normale associée (version admissible < version normale). Exemples : 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92.
  11. Une version de construction PEUT être représentée par l’ajout d’un signe « plus » et d’une série d’identifiants séparés par des points suivant immédiatement la version de patch ou admissible. Les identifiants DOIVENT être composés uniquement de caractères alphanumériques ASCII et de tirets [0-9A-Za-z-]. Les versions de construction sont utilisables et suivent la version normale associée (version de construction > version normale). Exemples: 1.0.0+build.1, 1.3.7+build.11.e0f985a.
  12. La priorité DOIT être calculée en séparant les numéros de version, dans l’ordre, en identifiants majeur, mineur, patch, de admissible et de construction. Les numéros de version majeur, mineur, et de patch sont toujours comparés numériquement. Pour les versions admissible et de construction, la priorité DOIT être déterminée en comparant chaque identifiant séparé par un point comme suit : les identifiants composés de chiffres seulement sont comparés numériquement et les identifiants composés de lettres ou de tirets sont comparés dans l’ordre de tri ASCII. Les identifiants numériques précèdent les identifiants non numériques (identifiants numériques < identifiants non-numériques). Exemple : 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-RC.1 < 1.0.0-RC.1+build.1 < 1.0.0 < 1.0.0+0.3.7 < 1.3.7+build < 1.3.7+build.2.b8f12d7 < 1.3.7+build.11.e0f985a.

Dans le vrai monde

Le versionnage sémantique n’est pas la seule façon de donner une identité à une version de votre logiciel. La page dédiée au versionnage logiciel répertorie une multitude de façons d’arriver à cette fin sans utiliser cette façon de faire.

La façon de versionner son logiciel doit être une question débattue au sein de l’équipe de développement. Un bel exemple de ce débat est celui tenu par l’équipe de développement Drupal. La question a été lancée en juin 2012 et il y a eu des échanges jusqu’en février sur ce sujet.

Il est difficile de répertorier les projets utilisant le versionnage sémantique. Toutefois, la façon de nommer les versions n’est pas à prendre à la légère et a beaucoup d’implication pour les contributeurs et utilisateurs.

Après tout, est-ce que de donner un numéro de version qui s’incrémente d’une façon prévisible et logique à travers le temps serait une façon de démontrer qu’un développeur se soucie réellement de ses utilisateurs? Moi, je crois que oui.