Chocoblog

Chocoblog

Billets sur l'informatique, les logiciels libres et retours d'utilisation sont au programme avec la possibilité de publier des billets de copains.

PeerTube - Partie 1 : releases & mises à jour

Pour rappel, PeerTube est une application web, s'installe sur un serveur et tourne via NodeJS. Voir le sommaire pour plus d'informations.

Avant même qu'un projet libre ou open-source ne prenne un peu d'ampleur, il faut savoir comment le diffuser. Cette diffusion a des répercussions importantes sur les mises à jour du logiciel, et il est difficile d'en changer. D'où l'intérêt de choisir une bonne méthode dès le début.

J'ai mis longtemps à savoir quelle méthode de release utiliser. Chaque gros projet web semble choisir une méthode différente, et aucune n'a l'air de prendre le dessus. J'ai étudié plusieurs options puis en ai retenue une, qui semble être appréciée par les administrateurs de PeerTube, de par sa simplicité et son efficacité. À l'époque, je n'avais pas vraiment trouvé d'articles de développeurs donnant leur ressenti sur leur façon de releaser leur projet web. J'espère donc que ce billet de blog sera utile à certains.

Voici grosso modo les choses dont on a besoin :

  • Facilement récupérer la dernière version compilée du logiciel (le build de PeerTube prend beaucoup de temps)
  • Remplacer la version existante
  • Installer les dépendances NodeJS
  • Gérer une hiérarchie de dossiers, afin que certains ne soient pas écrasés lors des mises à jour (dossiers de stockage et configuration)
  • Revenir à une précédente version sans trop de galères

Voici donc un petit tour d'horizon des différentes méthodes que j'avais considérées.

Git

Git permet de facilement mettre à jour une application avec un git pull, et de pouvoir naviguer entre les différentes branches et tags. Mais ça peut vite devenir lourd lorsque le projet grandit, et possède beaucoup de commits/branches. Il me paraît un peu dommage de récupérer toutes les révisions de développement, alors qu'au final l'administrateur n'est intéressé que par un instantané du code.

De plus, on devrait mettre les fichiers compilés directement dans le Git ce qui n'est pas idéal. Ou sinon les administrateurs devraient compiler eux-même PeerTube, mais ça prend du temps et beaucoup de CPU/RAM. J'ai donc décidé de ne pas partir sur cette méthode.

NPM

NPM a l'avantage de gérer et d'installer lui-même les dépendances NodeJS, en plus de stocker et transmettre de manière transparente le code. Un npm install peertube qui diffuserait uniquement les fichiers compilés aurait permis d'avoir quasiment un PeerTube fonctionnel. Le soucis c'est qu'on devient très dépendant de NPM (l'outil et le fournisseur), et on se retrouve avec une hiérarchie de dossiers qu'on peut difficilement contrôler.

Paquet GNU/Linux

Un paquet natif à la distribution GNU/Linux qu'on utilise (.deb ou .rpm) est aussi une solution très pratique pour les administrateurs. En une commande, tout s'installe correctement sur sa distribution. Et surtout, ça s'ajoute à l'inventaire des paquets présents sur le serveur tout en gérant les conflits et dépendances système (PostgreSQL, NodeJS etc). Sauf que ça demande beaucoup de travail pour les développeurs car il faut générer plusieurs types de paquets selon les distributions Linux, en plus des connaissances sur leur construction. N'ayant pas ces connaissances, j'ai décidé de ne pas retenir cette méthode. Il me semble cependant qu'il s'agit de la manière la plus pratique pour releaser et mettre à jour un logiciel, si on a le temps et les compétences nécessaires.

Docker

Docker est assez efficace pour diffuser, installer ou tester un logiciel. Mais pour moi c'est quelque chose en plus d'une méthode de release classique, car Docker divise et peut donc rebuter certains administrateurs. Ça ajoute aussi une surcouche au logiciel qui peut entraîner quelques effets de bord. Et honnêtement, créer un logiciel est déjà assez compliqué comme ça :)

On peut aussi se dire que diffuser son logiciel seulement via Docker est un parti pris : les développeurs gagnent du temps en utilisant une seule méthode de release dans un environnement testé et approuvé. Je ne porte pas Docker dans mon coeur, donc là encore j'ai décidé de ne pas retenir cette méthode.

Diffuser un ZIP

C'est finalement la méthode choisie pour PeerTube.

Un zip a l'avantage d'être un format simple, efficace et très utilisé. On peut le diffuser via GitHub, Gitlab ou directement sur le site web officiel du projet. Les administrateurs ont donc juste à utiliser wget ou curl pour récupérer l'archive, puis unzip.

Un ZIP c'est beau, mais il faut aussi savoir comment organiser les dossiers et remplacer la version existante. Car on n'a pas de .gitignore pour dire de ne pas toucher tel ou tel dossier (de configuration ou de stockage de données), et pas de git checkout pour facilement repasser à la version précédente du logiciel. Pour palier à ces deux situations, je me suis inspiré de la méthode de release de Seafile :

  • On télécharge le ZIP
  • On extrait l'archive dans un dossier mon-projet-x.y.z
  • On crée un lien symbolique mon-projet-latest pointant sur mon-projet-x.y.z
  • mon-projet-latest est la version courante, utilisée par nginx pour servir les fichiers statiques et systemd pour démarrer le serveur

On peut donc facilement jongler entre les différentes versions du projet (il suffit de changer le lien symbolique) et tous les dossiers à côté de mon-projet-latest ne seront pas affectés par les mises à jour (on peut imaginer avoir un dossier config, data etc). On a donc un arbre de dossiers de la forme :

.
├── config
├── mon-projet-latest -> version/mon-projet-x-y-z
├── data
└── version

Le dossier version contient les versions précédentes du logiciel.

L'installation pour organiser les dossiers peut être un peu lourde (ça rajoute 2 ou 3 commandes en plus et les administrateurs ne savent pas tout le temps où on veut en venir), mais les mises à jour sont très efficaces : on télécharge l'archive puis on l'extrait, on installe les dépendances, fait pointer le lien symbolique vers le nouveau dossier et le tour est joué. Il n'y a plus qu'à redémarrer le service.

Se pose cependant la gestion des dépendances : pour PeerTube, qui est un projet web NodeJS, il faut (ré)installer les nombreux modules via NPM ou Yarn une fois le fichier ZIP extrait. Je me suis demandé pendant un moment s'il n'était pas plus pertinent de mettre les dépendances directement dans le ZIP. Mais j'ai réalisé que ce serait du gâchis d'espace et de réseau : les versions récentes de NPM et Yarn embarquent un cache local donc il est assez rapide et efficace de réinstaller les dépendances directement via ces outils. Cette vision des choses a cependant l'air d'être remise en question par Yarn 2. À voir dans l'avenir si on ne finit pas par ajouter les dépendances directement dans le ZIP.

Le seul désavantage de cette technique c'est que vous ne pouvez pas vous assurer des versions des dépendances système de votre projet (PostgreSQL, Redis...) comme avec un paquet .deb ou .rpm : il faut coder une vérification directement dans le logiciel.