---
title: Le code était juste, le package livré ne l'était pas
description: Une gem dont les 317 tests passaient et qui ne se chargeait pas sans
  deux dépendances non déclarées. Les contrôles qui vérifient le package livré.
url: https://sxnlabs.com/opensource/2026/09/24/verifier-le-package-livre-pas-le-code/
lang: fr
date: '2026-09-24T09:00:00+02:00'
tags:
- Open source
- RubyGems
- E-invoicing
- Livraison
- CI
---

# Le code était juste, le package livré ne l'était pas

Fin août, j'ai publié la version 0.9.3 d'[einvoicing](https://sxnlabs.com/gems/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.

<figure class="schema">
  <img width="1000" height="470" src="/images/posts/package-livre/depot-contre-package.fr.svg" alt="Deux blocs reliés par la commande gem build. À gauche, le repo : les fichiers, les gems déjà installées sur le poste, un Gemfile.lock résolu en Ruby 4.0, vérifié par les 317 tests. À droite, le package : seulement les fichiers listés, seulement les dépendances déclarées, installé sur le Ruby de l'utilisateur dès 3.2, vérifié par le nouveau contrôle. En dessous, ce qui peut se perdre au passage : une dépendance, un fichier, une version compatible 3.2." />
  <figcaption>Les tests vérifient le repo, l'utilisateur installe le package.</figcaption>
</figure>

## 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](https://github.com/sxnlabs/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.
