PrestaFlow : versionner ses baselines visuelles sans exploser le repo
Le problème qu’on découvre au 3ème mois
L’annexe régressions visuelles a insisté sur un point : commit visual-baseline/. Les baselines font partie de vos tests, un baseline hors-repo est un test qui ne survit pas au premier git clone.
Vrai. Sauf que le corollaire arrive rarement dans les discussions initiales : à quelle vitesse visual-baseline/ grossit ?
Ordre de grandeur pris de l’annexe thème : un thème sérieusement testé, c’est 6 gabarits × 3 breakpoints × 5 locales × 2 versions PS = 180 baselines. Une capture pleine page pèse facilement de quelques centaines de KB à plus d’un MB selon la taille de page et le contenu. Disons de 50 à 300 MB de PNG dans le repo Git, uniquement pour les baselines visuelles — et chaque mise à jour en ajoute une nouvelle copie à l’historique.
Un repo Git de plusieurs centaines de MB à cause d’images :
- clone lent (grosse latence pour les nouveaux contributeurs)
- historique qui explose (chaque MAJ de baseline duplique le fichier)
- GitHub avertit au-delà de 50 MiB par fichier et refuse au-delà de 100 MiB ; sa documentation recommande de garder un dépôt idéalement sous 1 GB, et en tout cas sous 5 GB
- IDE lent (rescan des fichiers, indexation)
Cette annexe donne quatre stratégies pour vivre avec, dans l’ordre où on les adopte quand le problème apparaît.
Stratégie 1 : compression + limites explicites
Le plus simple, à faire d’entrée de jeu. PNG accepte l’optimisation sans perte (optipng, oxipng) : même image, pixel pour pixel, dans un fichier plus petit. Le gain varie selon l’image ; mesurez-le sur vos propres captures. Évitez en revanche pngquant, qui réduit la palette avec perte : les pixels changent, et vos comparaisons avec eux. Un pre-commit hook qui optimise toutes les baselines commitées protège la taille du repo dès le début.
.git/hooks/pre-commit :
#!/usr/bin/env bash
files=$(git diff --cached --name-only --diff-filter=ACM | grep '^visual-baseline/.*\.png$')
if [ -n "$files" ]; then
echo "$files" | xargs -I {} oxipng -o 4 {}
echo "$files" | xargs git add
fi
Combiné avec une limite explicite dans le README (“une baseline > 500 KB doit être justifiée : soit une capture full-page, soit un écran très dense — sinon, réduire le viewport ou restreindre le sélecteur”), ça garde le total sous contrôle.
Suffisant tant que vous restez sous ~50-80 baselines. Au-delà, passez à la stratégie 2.
Stratégie 2 : Git LFS
Git LFS (Large File Storage) est l’extension standard pour versionner de gros fichiers binaires sans les mettre dans l’historique Git. Le repo stocke des pointeurs (200 octets par fichier), les vraies données vivent sur un serveur LFS séparé (GitHub, GitLab et Bitbucket en ont un intégré, avec quotas).
Setup :
git lfs install
git lfs track "visual-baseline/**/*.png"
git add .gitattributes
git commit -m "chore: track visual baselines with Git LFS"
.gitattributes généré :
visual-baseline/**/*.png filter=lfs diff=lfs merge=lfs -text
Résultat : l’historique Git ne contient plus que des pointeurs. Par défaut, git clone télécharge quand même les fichiers LFS de la révision extraite (seulement la version courante, pas tout l’historique). Pour cloner sans les baselines, GIT_LFS_SKIP_SMUDGE=1 git clone …, puis git lfs pull le jour où on en a besoin.
En CI, actions/checkout ne récupère pas les fichiers LFS par défaut : sans l’option, visual-baseline/ ne contient que des pointeurs texte, et chaque comparaison échoue.
- uses: actions/checkout@v4
with:
lfs: true
Quotas — selon la documentation GitHub consultée le 24/09/2026, un compte GitHub Free (personnel ou organisation) inclut 10 GiB de stockage LFS et 10 GiB de bande passante par mois. Au-delà, c’est facturé à l’usage : 0,07 $ par GiB stocké et par mois, 0,0875 $ par GiB téléchargé. Chaque run de CI qui télécharge les baselines consomme de la bande passante : c’est souvent ce poste-là qui dépasse le premier.
Suffisant tant que votre budget LFS reste raisonnable et que vos contributeurs ont Git LFS installé.
Stratégie 3 : baselines hors-repo, blob storage
Quand LFS coûte trop cher (ou que vous voulez découpler le stockage des baselines du repo Git), on héberge les baselines sur un blob storage direct — S3, Cloudflare R2, Backblaze B2, Scaleway Object Storage. Le repo ne contient plus que le code.
Deux étapes :
- Script d’upload/download. Un helper
composer run visual:pulltélécharge les baselines depuis le bucket,composer run visual:pushupload les nouvelles. La branche courante définit le chemin de préfixe. - Convention de nommage stable. Les baselines de PrestaFlow suivent déjà
{name}--{tag}.png(voir annexe régressions visuelles) — c’est utilisable tel quel comme clé S3.
Coût : selon la grille tarifaire de Cloudflare consultée le 24/09/2026, R2 facture le stockage 0,015 $ par GB et par mois (les 10 premiers GB sont gratuits), sans frais de sortie (les opérations sur les objets restent facturées au-delà d’un quota gratuit). Pour 20 GB de baselines, 0,15 $ par mois de stockage. Environ cinq fois moins cher au GB stocké que Git LFS au-delà de son quota, et surtout sans facture de bande passante.
Contrepartie : un contributeur qui n’exécute pas visual:pull avant de lancer les tests obtient des baselines manquantes → PrestaFlow crée de nouvelles baselines à partir de ses captures, sans rien comparer → il risque de les pousser avec visual:push et d’écraser les bonnes. Il faut donc :
- un check dans le script de test qui vérifie que
visual-baseline/n’est pas vide avant de lancer les régressions visuelles - une doc claire dans le README (“avant tout run de tests visuels,
composer run visual:pull”)
Suffisant tant que vous êtes prêt à maintenir un petit outillage custom.
Stratégie 4 : déléguer à la plateforme prestaflow.io
L’Action officielle (PrestaFlow/github-action@v2, input visual activé par défaut) synchronise déjà les baselines avec la plateforme. Elles vivent côté serveur, sont téléchargées dans visual-baseline/ avant chaque run (en écrasant un fichier du dépôt qui porterait le même nom), et les nouvelles captures + diffs sont envoyées à la fin.
Ce qui change avec cette stratégie : votre repo ne contient plus aucun PNG de baseline. La plateforme fait autorité, l’Action est le seul intermédiaire. Le développeur qui itère en local sans la plateforme (avec la CLI PrestaFlow seule, comme au niveau 1 de l’article 2) ne bénéficie plus des baselines partagées — il en crée localement, elles ne remontent pas.
C’est le choix par défaut pour les projets qui utilisent déjà l’Action officielle. Zéro outillage à maintenir côté repo, zéro coût LFS. Le prix : l’usage de la plateforme est un prérequis pour toute contribution qui touche aux baselines.
Tableau de décision
| Contexte | Stratégie |
|---|---|
| Projet expérimental, moins de 50 baselines, pas de plateforme | 1 (compression + limites) |
| Projet actif, 50-500 baselines, budget LFS OK | 2 (Git LFS) |
| Projet actif, beaucoup de baselines, veut éviter LFS | 3 (blob storage) |
| Projet qui utilise déjà l’Action officielle | 4 (plateforme) |
Les stratégies sont cumulatives : la compression (1) reste bénéfique quel que soit le stockage final. Vous pouvez démarrer avec la 1, migrer vers la 2 ou la 3 quand le repo devient lourd, basculer vers la 4 le jour où vous passez à l’Action officielle.
Éviter les régressions de churn
Chaque MAJ de baseline ajoute une nouvelle copie du PNG à l’historique Git, au stockage LFS ou au bucket versionné, selon la stratégie. Sur un projet actif où le thème évolue, ça monte vite.
Deux réflexes pour limiter le churn :
- Ne pas capturer plein écran quand un sélecteur suffit. Un
visualCheckpoint('newsletter-block', selector: '.block_newsletter')produit une image de quelques dizaines de KB, là où la home entière en pèse souvent des centaines. Le diff est aussi plus lisible. - Regrouper les MAJ de baseline. Une refonte de thème qui touche 30 écrans → 1 seul commit “baselines refresh: theme v2 upgrade” qui met à jour d’un coup les 30 baselines, plutôt que 30 commits épars. L’historique reste lisible et un rollback ciblé reste possible.
Interaction avec les autres annexes
- Régressions visuelles — cette annexe est le complément infra de celle-ci. Une couvre le pourquoi et le comment fonctionnel (
visualCheckpoint, seuils, tags), celle-ci couvre le stockage physique. - Tester un thème — l’ordre de grandeur “60 à 200 baselines” y était mentionné sans discuter du coût de versioning. Cette annexe complète.
- Cloud runs — la stratégie 4 s’inscrit dans le workflow global de la plateforme, où les baselines ne sont qu’un asset parmi d’autres (résultats, captures d’échec, diffs).
Notes
Dans la Série PrestaFlow — article 27 sur 35