Fin août, j’ai publié la version 0.9.3 d’einvoicing, ma gem de facturation électronique. Elle n’ajoute ni ne corrige aucune fonctionnalité. La 0.9.2 ne se chargeait pas dans un projet qui n’avait pas déjà bigdecimal, alors que ses 317 tests passaient chez moi.
Chez moi, ça marche
La gem utilise bigdecimal pour les montants et rexml pour lire le XML. Ruby les installait autrefois avec lui, il faut maintenant les déclarer comme dépendances, et je ne l’avais pas fait. Sur mon poste, d’autres gems les installaient déjà. Ailleurs, require "einvoicing" échouait immédiatement, et la validation Peppol dès qu’elle lisait du XML.
Les tests tournent dans le repo. Le package publié ne contient que les fichiers listés dans le gemspec et les dépendances déclarées, et il s’installe sur un Ruby que je ne contrôle pas. Aucun test ne regardait ce package.
Trois écarts entre le repo et le package
- Une dépendance présente sur le poste, absente chez l’utilisateur. C’est l’écart qui a été publié.
- Un fichier lu à l’exécution mais absent du gemspec. La gem embarque un profil sRGB dans chaque PDF/A-3 : retiré de la liste, tous les tests restent verts et la gem publiée ne produit plus de facture conforme. Je l’ai provoqué exprès, et aucun contrôle ne le voyait.
- Un lockfile résolu sur Ruby 4.0, qui retient des versions exigeant Ruby 3.3 alors que la gem promet de tourner sur 3.2.
Les contrôles ajoutés
Le premier construit la gem comme pour une publication, l’installe dans un environnement vide et la charge. Il compare ensuite, fichier par fichier, ce que le repo utilise à l’exécution et ce que le package contient. Une dépendance non déclarée fait échouer le chargement, un fichier manquant est identifié.
Le second parcourt le lockfile et vérifie que chaque version accepte Ruby 3.2. Une gem qu’il n’a pas pu vérifier, par exemple quand RubyGems limite les requêtes, compte comme un échec.
Ces contrôles avaient eux-mêmes des trous, signalés en relecture. Le premier chargeait le package sans regarder son contenu, si bien que retirer un fichier de traduction laissait tout au vert. Corrigé, il vérifiait qu’un glob du gemspec trouvait quelque chose au lieu de vérifier chaque fichier attendu. J’ai reproduit chaque trou en cassant le package exprès avant de le corriger.
Au-delà de Ruby
Le même écart existe partout où l’on teste une chose et en livre une autre : un installeur essayé sur la machine qui l’a compilé, une image Docker construite avec un cache local, une application mobile validée sur le téléphone du développeur.
Si vous faites développer un logiciel, demandez sur quoi tourne la dernière vérification avant livraison. Si elle tourne sur la machine du prestataire plutôt que sur ce qui vous est livré, elle ne couvre pas ce que vous recevez.
La 0.9.3 et la 0.4.0 d’einvoicing-connect sont en ligne depuis le 31 août. Leur intégration continue lance désormais les tests sur Ruby 3.2 et 4.0, l’installation du package dans un environnement vide sur ces deux versions et la vérification du lockfile.