PROJET AUTOBLOG


Sam & Max: Python, Django, Git et du cul

Site original : Sam & Max: Python, Django, Git et du cul

⇐ retour index

La notation de version SemVer 7

jeudi 1 janvier 2015 à 07:52

Il y a des tas de manières d’indiquer la version d’un logiciel.

Ubuntu utilise l’année et le mois, à l’envers : la 14.04 indique une version sortie en avril 2014.

Avant la 1.2, angular utilisait les versions paires pour signifier la stabilité, et impaire pour l’instabilité.

Quelques projets utilisent des numéros de branche Git ou Svn.

Certains utilisent des noms du genre “kangourou-cosmique” pour marquer le coup.

Et d’autres mélangent plusieurs techniques.

En Python, la méthode recommandée est nommée SemVer, pour Semantic Versioning.

Explications

Tout est basé sur la notion d’API publique. Si vous ne vous souvenez pas de ce qu’est une API publique, c’est par ici.

Une bibliothèque versionnée avec SemVer doit clairement documenter toute son API publique pour dire : voici les bouts de codes que vous pouvez utiliser sans risque.

Beaucoup de devs ne font pas, tout comme on fait souvent du REST non pur, on fait souvent du SemVer non pur, mais je vous le dis sinon des puristes viendront jouer de la moustache en commentaires.

Le principe est simple : votre versioning est noté x.y.z, x, y et z étant des entiers positifs. A moins que le nombre soit 0, aucun nombre ne doit commencer par 0.

Le x représente une version majeure, qui introduit au moins un changement incompatible dans l’API publique.

Le y représente une version mineure, qui introduit au moins une nouvelle fonctionnalité dans l’API publique.

Le z représente une correction de bug ou un changement dans l’API privée.

Et c’est tout.

En pratique

Si vous réparez un bug, z augmente de 1.

Ex : 1.3.4 devient 1.3.5

Si vous introduisez un nouveau paramètre optionnel, une fonction outil indépendante, un nouvel attribut public, y augmente de 1, et z est remis à 0 :

Ex : 1.3.4 devient 1.4.0

Si une fonction retourne maintenant ne serait-ce qu’un tuple au lieu de précédemment une liste, x augmente de 1, y et z sont remis à 0 :

Ex : 1.3.4 devient 2.0.0

FAQ

Le numéro de version va monter très vite non ?

On ne change le numéro de version que pour une version publiée. Si vous faites plein de petits changements mais que vous ne déclarez pas ce nouveau code comme la dernière version officielle, pas besoin de changer de version : vous êtes encore en développement.

N’oubliez pas aussi que c’est VOTRE job de vous assurez que votre programme reste compatible. Faites des adapters, des alias, introduisez les fonctionnalités de manière optionnelle, depréciation à l’avance… Il y a des moyens de faire ça proprement.

C’est quand même over chiant pour une lib qui vient de sortir et que personne n’utilise, non ?

Jusqu’à la version 1.0.0, le SemVer ne s’applique pas. En 0.y.z, on peut faire du freestyle.

Mais si je suis en beta ?

On peut signaler des informations supplémentaires en mettant un tiret après son versioning. Le style est libre mais la convention est généralement x.y.z-status. Ex : 1.3.3-alpha, 1.3.3-beta, 1.3.3-rc1, etc.

Attend, je fais une release parfaitement compatible, mais avec une fonction publique qui ne retourne plus 1 mais True, je vais pas bumper pour ça quand même ?

Si. Si vous ne voulez pas le faire, mettez le dans une branche à part, et attendez une release plus grosse pour introduire ce changement.

J’ai une correction de bug qui introduit une changement incompatible dans l’API publique, je fais quoi ?

On bump. Ça n’arrive pas si souvent que ça qu’un bug change l’API publique, faut pas charrier.

Ouais, genre tu le fais…

Non, je ne fais pas du SemVer pur. Mais sur une lib qui est très utilisée, c’est un système indispensable. Si j’avais la responsabilité de pondre Django, ouais, je ferais du SemVer pur.

Ok, je l’ai fais mais j’ai pas l’impression d’y gagner quoi que ce soit.

Le bénéfice n’est pas pour l’auteur, mais pour les utilisateurs. Si un autre utilisateur à votre lib comme dépendance, il peut déclarer dans son fichier setup.py:

requires=['votrelib>=1.3.1<2.0.0']

Ainsi il est certain que ça ne pétera pas si vous faites votre boulot correctement car la lib installée par pip sera toujours dans une version entre la 1.3.1 qu’il sait compatible, jusqu’à la 2.0.0 qui sera incompatible.