ChaosLab : tester modules PrestaShop sur 23 environnements PHP

ChaosLab automatise les tests multi‑PHP pour modules PrestaShop : Docker/Compose, matrice CI, artefacts de debug et politique de compatibilité pour éviter régressions et tickets.

Interface avec des écrans et graphiques pour tester PrestaShop.

Table des matières :

  1. ChaosLab : pourquoi multiplier les environnements PHP quand on développe un module PrestaShop
  2. Définition : ce que ChaosLab appelle un “environnement PHP” (et pourquoi 23 n’est pas absurde)
  3. Construire ChaosLab : architecture Docker/Compose et 23 profils d’exécution
  4. Pipeline CI : exécuter la matrice PHP sans y laisser le temps de build
  5. Exploiter les résultats : compatibilité annoncée, contraintes Composer, dépréciations
  6. Cas limites typiques en modules PrestaShop : ce qui casse entre PHP 7.4 → 8.x (et comment le rendre testable)

ChaosLab : pourquoi multiplier les environnements PHP quand on développe un module PrestaShop

Développer un module PrestaShop « compatible PHP » n’est pas un exercice académique : c’est une stratégie de réduction d’incidents. Le cœur PrestaShop, les dépendances Composer (Symfony, PSR, librairies de paiement, SDK divers) et votre propre code subissent les changements de comportement de PHP (promotions de warnings, typage plus strict, dépréciations, évolutions de l’engine). Résultat terrain : un module qui passe en local sur PHP 8.3 peut provoquer une page blanche chez un client resté en 8.1, ou l’inverse si vous utilisez des features 8.3 sans garde-fous.

La réalité e‑commerce, c’est l’hétérogénéité. Entre un hébergement mutualisé qui force Apache mod_php, un VPS en PHP-FPM, un conteneur Alpine (musl) ou Debian (glibc), et des extensions PHP pas toujours identiques (intl/ICU, gd vs imagick, sodium, zip), vous avez des comportements différents… alors que le bug report remontera juste « Erreur 500 ». Si vous voulez un rappel concret des symptômes et des causes côté PrestaShop, gardez sous la main : Erreur 500 PrestaShop : 10 causes fréquentes et solutions rapides et PrestaShop page blanche : diagnostiquer l’erreur fatale PHP rapidement.

Ce point est encore plus vrai quand votre module touche à des zones « sensibles » de l’écosystème PrestaShop :

  • Paiement / PSP : TLS, cURL/OpenSSL, timeouts, callbacks, webhooks.
  • Export / import : encodage, ext-intl, mémoire, gros volumes.
  • Images : gd vs imagick, profils ICC, différences de build selon OS.
  • Back-office Symfony : container, autowiring, signatures, attributs PHP, compatibilité BO/FO.
  • Cron et CLI : SAPI cli différente de fpm (ini, extensions, disable_functions, droits fichiers).

ChaosLab, dans ce contexte, n’est pas « un labo pour faire joli » : c’est une matrice d’exécution reproductible qui vous force à voir les écarts avant la release. Martin Fowler résume bien l’esprit CI (et pourquoi on ne veut pas découvrir les régressions en prod) : « Continuous Integration is a software development practice where members of a team integrate their work frequently, usually each person integrates at least daily. » (Martin Fowler, Continuous Integration, https://martinfowler.com/articles/continuousIntegration.html). L’idée de ChaosLab est la même, appliquée à la compatibilité multi‑PHP.

Un bon indicateur que vous avez besoin d’une matrice multi‑environnements : si votre support contient des tickets du type « ça marche chez nous / ça ne marche pas chez le client », sans reproduction immédiate. ChaosLab sert précisément à remplacer l’argument d’autorité par un verdict exécutable : “profil X + scénario Y = KO/OK”.

Définition : ce que ChaosLab appelle un “environnement PHP” (et pourquoi 23 n’est pas absurde)

Dans PrestaShop, “PHP version” est une info trop grossière. Un environnement PHP utile pour tester un module, c’est au minimum : (1) une version d’interpréteur (8.1 vs 8.2 vs 8.3…), (2) une SAPI (cli, fpm, apache), (3) un OS/libc (Debian/glibc vs Alpine/musl), (4) un set d’extensions + leurs versions (curl, intl/ICU, mbstring, gd/imagick, zip), (5) des options ini (errorreporting, displayerrors, opcache, assert, memory_limit). Chacun de ces éléments peut changer le comportement observable de votre module.

Exemples concrets qui cassent des modules PrestaShop : ext-intl et la version ICU influencent la translittération et certains formats (dates, collations), donc votre logique de slugs, d’exports ou de recherche peut diverger. ext-curl + OpenSSL changent des défauts TLS (SNI, cipher suites), donc certains SDK/API se mettent à refuser des connexions. Sur Alpine, des binaires (imagick, certains libs) n’ont pas les mêmes compatibilités et vous vous retrouvez avec un “fonctionne sur Debian, échoue sur Alpine”. Et côté performance, OPcache/JIT peut masquer (ou amplifier) des fuites mémoire et des comportements non déterministes.

Pour rendre la notion d’« environnement » actionnable, vous pouvez formaliser un contrat de test minimal (une checklist simple, mais systématique) :

  • PHP : version + SAPI + mode d’exécution (CLI, FPM derrière Nginx, Apache).
  • OS : Debian/Ubuntu vs Alpine, et architecture (x86_64/arm64 si pertinent).
  • Extensions critiques : curl, intl, mbstring, gd/imagick, zip, openssl, pdo_mysql (et souvent sodium).
  • INI : error_reporting, log_errors, memory_limit, default_charset, opcache.enable, opcache.jit (si activé), zend.assertions.
  • Dépendances : version de Composer + contraintes composer.lock (ou stratégie de lock par branche).
  • Stockage/DB : version MySQL/MariaDB + collation (utile si le module manipule des tri/LIKE ou recherche).

C’est pour ça qu’une cible “23 environnements PHP” est pragmatique si vous la construisez en profils. Docker l’exprime sans ambiguïté : « A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another. » (Docker, What is a container?, https://www.docker.com/resources/what-container/). ChaosLab se base sur cette standardisation pour répliquer des environnements réellement rencontrés (et pas uniquement “PHP 8.x”).

Un mini-scénario (typique, et frustrant sans matrice) : un module génère des slugs produits via translittération. En recette, tout est OK. En production, un marchand FR sur un stack différent constate des URL incohérentes sur certains caractères accentués, et vos redirections SEO explosent. Avec ChaosLab, vous isolez immédiatement si le différentiel vient de intl/ICU (et vous ajustez : tests de non‑régression + translittération contrôlée, ou normalisation Unicode explicite).

Construire ChaosLab : architecture Docker/Compose et 23 profils d’exécution

Le pattern le plus robuste consiste à séparer les tests en deux couches :

  • Couche A (pure PHP) : exécuter les tests unitaires de votre module (classes “métier”, services, SDK wrappers) sur tous les profils PHP. Ici, vous ne dépendez pas forcément du cœur PrestaShop, donc vous pouvez aller plus large (y compris des versions EOL si vous avez des clients legacy, en connaissance de cause).
  • Couche B (intégration PrestaShop) : installer une instance PrestaShop compatible avec la version PHP du profil, installer/activer le module, puis exécuter des smoke tests (hooks principaux, routes BO si vous en avez, commande cron, etc.). Cette couche ne doit couvrir que les combinaisons réalistes (ex. PrestaShop 9.x ne tourne pas sur PHP 7.4).

Concrètement, ChaosLab se matérialise bien en Docker Compose multi-services (PHP + web + DB) et une liste de profils. Exemple minimaliste (extrait, volontairement incomplet) :

# compose.yaml
services:
  php:
    build:
      context: .
      args:
        PHP_VERSION: ${PHP_VERSION}
        VARIANT: ${VARIANT} # debian|alpine
        SAPI: ${SAPI}       # cli|fpm|apache
    volumes:
      - ./:/workspace

  db:
    image: mariadb:11.4
    environment:
      MARIADB_ROOT_PASSWORD: root
      MARIADB_DATABASE: prestashop

  web:
    image: nginx:1.27
    depends_on:
      - php
    # ... fastcgi_pass vers php-fpm si SAPI=fpm

Deux recommandations qui évitent des “faux positifs” quand vous multipliez les profils :

  • Épinglez ce qui doit l’être (versions d’images, packages, extensions) et documentez ce qui est volontairement variable (ICU, OPcache/JIT…). Sinon vous testez une cible mouvante.
  • Rendez les tests idempotents : installation/activation du module doit pouvoir être rejouée proprement (base recréée, tables nettoyées, cache vidé). C’est particulièrement important sur la couche B.

Le “23” vient d’un découpage en profils (pas uniquement en versions). Une grille réaliste en 2026 pour du module PrestaShop pourrait être : PHP 7.4 / 8.0 / 8.1 / 8.2 / 8.3 / 8.4 × (Debian fpm, Debian cli, Alpine fpm) = 18, + 5 profils “edge” (OPcache agressif, zend.assertions=1, mbstring.func_overload si legacy, ICU différent, error_reporting=E_ALL + conversion warnings en exceptions dans votre harness). L’objectif n’est pas d’être exhaustif : il est de capturer les ruptures les plus fréquentes.

Pour éviter l’effet “usine à gaz”, vous pouvez formaliser vos profils comme une petite table de décision (et la versionner) :

Famille de profils But Exemple de signal détecté
“Compat” (versions PHP) Détecter ruptures de langage dépréciations PHP 8.2, types stricts, warnings
“SAPI” (cli/fpm/apache) Détecter différences INI/exécution timeout, memory_limit, max_input_vars, upload
“OS/libc” (Debian/Alpine) Détecter différences de build / libs imagick, ICU, certificats, chemins
“Edge” (ini agressif) Faire ressortir signaux faibles warnings → exceptions, assertions, OPcache

Avant de pousser cette usine, partez d’un staging identique à la prod pour calibrer vos profils (SAPI, extensions, ini). Si vous n’avez pas déjà cette base, construisez-la correctement : Staging PrestaShop : créer un environnement Docker fidèle à la production et, si vous allez jusqu’à générer des environnements “jetables” par branche, PrestaShop CI/CD : générer des démos à la demande en minutes.

Pipeline CI : exécuter la matrice PHP sans y laisser le temps de build

La condition de réussite, c’est la parallélisation + le caching. Sur GitHub Actions (ou GitLab CI), la stratégie classique est un matrix sur vos 23 profils, avec cache Composer (vendor + cache) et cache Docker layers. Vous limitez la couche intégration PrestaShop à 4–8 combos réellement supportés, et vous gardez la couche A (unit tests) sur les 23. La métrique à viser n’est pas “0 minute”, c’est “un feedback utilisable” : typiquement < 10–15 minutes pour la couche A, et < 20–30 minutes pour la couche B en parallèle (selon la taille des images).

Un point souvent sous-estimé : la matrice est utile uniquement si les jobs produisent des artefacts en cas d’échec (sinon vous avez 23 jobs rouges et aucune explication). En pratique, archivez au minimum :

  • logs PHP (error_log), logs web (Nginx/Apache),
  • logs PrestaShop (var/logs/* selon versions),
  • rapport PHPUnit (JUnit XML + couverture si nécessaire),
  • “snapshot” minimal de config (versions PHP, liste d’extensions, php -i filtré, composer show).

Exemple de matrice (simplifié) côté GitHub Actions, juste pour illustrer la structure :

strategy:
  fail-fast: false
  matrix:
    include:
      - php: "8.1"
        variant: "debian"
        sapi: "cli"
      - php: "8.3"
        variant: "debian"
        sapi: "fpm"
      - php: "8.3"
        variant: "alpine"
        sapi: "fpm"
      # ... compléter jusqu'à vos 23 profils

Les étapes CI qui payent immédiatement sur un module PrestaShop :

  1. ps-validator en CLI pour détecter packaging, métadonnées, classes suspectes, conventions. L’intégration est documentée ici : ps-validator : intégration CI/CD du Validator PrestaShop en terminal.
  2. PHPUnit (ou Pest) sur la couche A. Si vous avez déjà un setup type ps_onepagecheckout, reprenez le pattern : ps_onepagecheckout : exécuter les tests PHPUnit avec Docker et PrestaShop.
  3. Smoke tests (HTTP + CLI) : installation, activation, exécution d’un hook critique, et vérification de logs. Ici, un simple curl sur un endpoint front, et une commande CLI qui touche votre code suffit souvent à détecter 80% des incompatibilités.

Deux bonnes pratiques pour conserver du temps de build sans perdre de couverture :

  • Découper les scénarios : un smoke test “activation + hook” n’a pas besoin d’une génération d’images complète ni d’un thème lourd.
  • Tester la résolution Composer de façon contrôlée : un job “lock” (sur composer.lock) + un job “résolution libre” (sans lock, sur un profil de référence) peut vous révéler une dépendance trop permissive avant qu’elle ne casse des clients.

Pour garder un signal exploitable quand ça casse, vous devez investir dans l’observabilité “dev”. Log PHP structuré, XDEBUG_MODE=debug,develop uniquement sur les jobs qui échouent (ou à la demande), et un run reproductible en local. L’article Xdebug VS Code : configurer le débogage PHP pas à pas vous évitera les allers-retours inutiles. Pour les CTO/DevOps, l’aspect IaC/standardisation est le même combat : DevOps : Infrastructure as Code avec Terraform et conteneurs pose des bases solides.

Exploiter les résultats : compatibilité annoncée, contraintes Composer, dépréciations

Une matrice ChaosLab n’a de valeur que si vous en tirez une politique de support explicite : versions PHP supportées, versions PrestaShop cibles, versions Symfony implicites. Et cette politique doit se refléter dans composer.json (contraintes php, contraintes des dépendances, et éventuellement une configuration platform pour stabiliser la résolution). Composer est votre premier filtre : si votre module déclare php: ^8.2, ne venez pas “tester” 8.0 en espérant que ça passe ; c’est un autre produit.

Concrètement, exploitez vos résultats pour produire une section “Compatibilité” dans le README (et idéalement dans la fiche module), avec :

  • une liste claire des versions PHP supportées (et celles non supportées),
  • les limitations connues (ex. “fonction X nécessite ext-intl”, “conversion WebP nécessite imagick”),
  • votre politique de correctifs (sur quelles branches vous backportez).

ChaosLab sert aussi à gérer la dette liée aux dépréciations. Sur PHP modernes, des warnings deviennent plus visibles (voire convertis en exceptions selon votre harness), et les librairies tierces changent leurs signatures. Le piège classique : vous corrigez en local, mais vous introduisez une régression sur un autre profil (différences ICU, ext-json, ext-mbstring). C’est précisément là que 23 environnements PHP font sens : vous validez que vos correctifs restent orthogonaux.

Un exemple très courant depuis PHP 8.2 : les propriétés dynamiques sont dépréciées. En module PrestaShop, ça survient souvent via des surcharges/objets “fourre-tout” ou des DTO improvisés. Sans matrice, le warning peut passer inaperçu (logs filtrés) jusqu’au jour où un client a un error_reporting plus strict, ou une conversion warnings→exceptions. Avec ChaosLab, vous voyez tout de suite le profil qui remonte le signal et vous appliquez un correctif durable (déclarer la propriété, utiliser un tableau dédié, ou encapsuler proprement l’état).

Enfin, versionnez votre module proprement. Le meilleur garde-fou reste SemVer, pas pour “faire joli”, mais pour découpler correctifs et ruptures. La spécification est très claire : « Given a version number MAJOR.MINOR.PATCH, increment the MAJOR version when you make incompatible API changes… » (Semantic Versioning 2.0.0, https://semver.org/). Combinez ça avec une doc de compatibilité (table PHP/PrestaShop) et vous réduisez les tickets. Pour garder un œil sur le contexte PHP (EOL, évolutions sécurité), vous pouvez recouper avec https://www.php.net/supported-versions.php et l’historique : PHP : histoire, versions majeures et évolutions de sécurité.

Si vous avez besoin d’un repère “officiel” pour comprendre ce qui change entre versions, les pages de migration du manuel PHP sont aussi très utiles (ex. incompatibilités et dépréciations) : https://www.php.net/manual/en/migration82.php.

Cas limites typiques en modules PrestaShop : ce qui casse entre PHP 7.4 → 8.x (et comment le rendre testable)

Le premier lot de cassures est “bête” mais coûteux : typage plus strict, fonctions qui n’acceptent plus null, et warnings plus agressifs. Exemples : count(null) (source de warnings), accès à des offsets sur null, implode() avec ordre d’arguments historique, ou strpos() avec des types inattendus remontant de Tools::getValue(). Dans ChaosLab, forcez au moins un profil avec error_reporting=E_ALL et logs non filtrés, sinon vous ne verrez jamais ces signaux faibles avant que le client ne les voie.

À rendre testable : ajoutez 2–3 tests unitaires “garde-fous” qui simulent les entrées sales (valeurs vides, null, tableaux au lieu de strings). Le but n’est pas de tester PHP, mais de figer le comportement attendu de votre module face aux entrées réelles d’un marchand (champ de config vide, paramètre GET absent, valeur BO enregistrée en chaîne vide, etc.).

Deuxième lot : compatibilité Symfony/PSR et interfaces. Avec PrestaShop 9.x (Symfony 6.4 côté BO), vous allez toucher des patterns “modernes” (services container, autowiring, attributs, contrôleurs). Si votre module vise plusieurs branches PrestaShop, la même classe peut devoir supporter deux signatures / deux environnements. C’est là que des choix d’architecture s’imposent : isoler l’intégration PrestaShop (adapters) de votre code métier, et tester le métier en couche A sur 23 profils. Pour l’alignement Symfony/PrestaShop, vous avez un point de référence utile : PrestaShop modules : optimiser la compatibilité Symfony 6.4 et Admin API et, côté écosystème Symfony pur, Symfony : composants réutilisables, Flex et productivité développeur.

À rendre testable : sur la couche B, ne vous contentez pas de “le module s’installe”. Testez au moins un flux BO réel (ex. ouverture de page de config, sauvegarde d’un champ, et relecture). Beaucoup d’incompatibilités Symfony se révèlent au moment où le container compile, où un service n’est pas trouvé, ou quand une signature d’interface ne colle plus.

Troisième lot : sécurité et sérialisation. Beaucoup de modules historiques traînent des usages de unserialize() (cache maison, stockage d’état, payloads). Sur PrestaShop, ce n’est pas “juste” un problème de compatibilité : c’est un risque d’object injection si la donnée est influençable. Si vous avez ce type de code, ChaosLab doit inclure un profil qui active des tests de sécurité basiques (fuzz sur endpoints, validation d’entrées, recherche de patterns dangereux) et vous devez migrer vers des formats sûrs (JSON signé, chiffrement, serialize() uniquement sur données internes non exposées, etc.). Un rappel très concret du type d’impact possible : Vulnérabilité PrestaShop ps_facetedsearch : analyse RCE via unserialize(). Si vous industrialisez, renforcez aussi votre supply chain : PrestaShop : sécuriser APIs et modules avec SBOM, WAF et CI/CD.

Un dernier cas limite “terrain”, très fréquent en France/Europe (sans tomber dans le folklore) : les modules qui parlent à des services tiers (transporteurs, ERP, paiement) dépendent souvent de la chaîne TLS du serveur, des CA disponibles et des options OpenSSL/cURL. Ça se manifeste par des erreurs intermittentes et difficiles à reproduire (“SSL certificate problem”, handshake refusé, timeout). Ici, ChaosLab n’est pas seulement un test de langage : c’est un moyen de rejouer des profils d’hébergement réalistes (mutualisé vs VPS, images Debian vs Alpine) et de capturer les erreurs bas niveau dans des logs exploitables.


À lire aussi