Parmis les valeurs de Fasterize, on y trouve: “Eliminate Waste”, “Build Quality In” et “Go Fast”.
Nous souhaitions illustrer ces valeurs à travers les pratiques de déploiement continu (ou “Continuous Deployment”) que nous utilisons au quotidien, et en particulier les tests, ingrédient indispensable pour assurer la fiabilité des déploiements. Cet article est aussi l’occasion de vous annoncer un nouveau type de tests dans notre processus de déploiement, fondés sur des snapshots de site web.

Pourquoi déployer en continu ?

Pour ceux qui auraient encore quelques doutes sur l’utilité du déploiement continu, je vous invite à lire ce billet.
Chez Fasterize, le processus de construction logiciel est entièrement automatisé, ainsi que l’exécution des tests mais aussi – et surtout – le déploiement. Nous avons poussé les principes du déploiement continu au maximum dans l’optique:

  • d’apporter de la valeur à nos clients le plus vite possible en innovant constamment
  • de minimiser les coûts liés aux nombreux déploiements sur une infrastructure importante (une centaine de serveurs, sans compter les environnements de développements gérés avec Vagrant et Docker) et variée (mix d’hébergeurs français et Clouds internationaux)
  • d’avoir la possibilité d’ajuster facilement la capacité de notre infrastructure pour s’adapter aux variations de trafic (nous parlons ici d’élasticité de l’infrastructure)
  • d’être capable de résoudre rapidement un incident survenant en production

Le principal ingrédient du déploiement continu : les tests!

Le Continuous Deployment requiert une automatisation complète du processus d’intégration continu ainsi que le déploiement. C’est ce que nous faisons à l’aide de Jenkins, Chef et Capistrano. Mais cela ne suffit pas : l’effort principal à réaliser consiste à tester tout ce qui peut l’être pour garantir le bon fonctionnement des composants qui sont déployés. Nous implémentons pour cela différents types de tests :

Type de tests Exécution
Tests unitaires (plus de 1600) Pendant le build des composants applicatifs
Tests fonctionnels (presque 200) Après chaque déploiement sur un environnement
Tests de performance (une dizaine) Après chaque déploiement sur un environnement
Tests d’infrastructure (plus de 100) Après chaque déploiement sur un environnement

Nous sommes toujours confiants sur la fiabilité de nos déploiements, grâce à une couverture de tests de plus de 90%. Cela nous a en effet permis de déployer plusieurs fois par semaine, voire plusieurs fois par jours, sans aucun problème.

Le problème

Malgré ce niveau de qualité que nous nous efforçons de maintenir et d’améliorer en continu, ce qui devait arriver arriva : nous avons rencontré un incident lors d’une mise en production. Comme à notre habitude, nous avons alors directement procédé à un “post-mortem” (voir un exemple de post-mortem). La cause a été rapidement identifiée et concernait un bug sur la fonctionnalité de chargement différé des javascripts, qui venait de subir une importante mise à jour. Quelques dizaines de minutes plus tard, le correctif était déployé.

Les solutions

Lors du post-mortem, nous avons identifié plusieurs solutions permettant de limiter ce genre de problème :

  • déployer en “canary release” pour ne déployer la nouvelle version que sur un sous-ensemble de serveurs, surveiller le comportement de ces serveurs, puis déployer sur l’ensemble des serveurs si tout fonctionne bien. Cette solution n’empêche pas d’avoir un incident mais permet de diminuer le nombre de clients impactés par une mise à jour problématique
  • faire des tests de snapshots pour identifier rapidement les différences des sites web de nos clients avant et après déploiement, et lever une erreur dans notre pipeline de déploiement le cas échéant. Cette solution n’empêche pas non plus qu’une mise à jour soit la cause d’un incident mais elle permet de détecter le problème bien avant la production. En effet, ce type de test peut-être fait sur chaque environnement et ainsi être corriger avant même de passer en environnement de staging

C’est cette deuxième solution que nous allons décrire dans la suite de cet article.

Snapshot avant mise en production Snapshot après mise en production Comparaison
OK
KO

Ces tests sont applicables uniquement dans un contexte où l’affichage de la page web ne doit pas évoluer. C’est le cas de Fasterize puisque nous avons vocation à améliorer la performance des sites web sans aucun changement visuel par rapport au site d’origine.

Mise en oeuvre des tests de snapshots chez Fasterize

La solution technique implémentée se décompose en plusieurs parties :

  • l’interface d’administration intégrée à “fasterize.com” permettant de configurer une (ou plusieurs) URL(s) à tester pour chaque compte utilisateur. Pour chaque URL, il est également possible de configurer un seuil de tolérance de pixels différents (voir explication plus bas)
  • l’API exposant plusieurs services :
    • un service permettant de générer un snapshot pour chaque URL passée en paramètre. Ce service renvoie un ID de batch. Notre API étant implémentée en Node.js, nous avons opté pour la librairie node-webshot qui utilise PhantomJS pour générer un snapshot d’une URL
    • un service pour comparer les snapshots des deux derniers batchs exécutés. Ce service prend en paramètre un seuil de tolérance de pixels différents par URL (voir explications plus bas). Nous utilisons la librairie automated-screenshot-diff pour générer une image diff à partir de deux images de snapshot en entrée. Les images diff résultantes sont noires, à l’exception des pixels différents, ce qui nous permet de calculer facilement leur nombre. Ce service renvoie un ID de comparaison.
    • un service permettant de générer une vue récapitulative pour une comparaison d’URLs comprenant: les images des snapshots, les images de diff et les nombres de pixels différents
  • les tâches Capistrano permettant d’appeler les services de l’API avec les URLs configurées sur les comptes utilisateurs
  • les jobs Jenkins pour exécuter les tâches Capistrano

Comme évoqué ci-dessus, l’une des difficultés de l’exercice est de gérer un seuil de tolérance de pixels différents. En effet, la plupart des sites contiennent soit un slideshow, soit des publicités avec vidéos ou animations CSS, soit des panneaux de recommandations qui varient d’un affichage à l’autre, soit des éléments graphiques en AB test, etc… En clair, il est quasiment impossible d’obtenir deux snapshots identiques au pixel près pour une même URL. C’est la raison pour laquelle nous devons gérer un seuil de tolérance.

A l’heure où nous écrivons ce billet, ce seuil de tolérance est configuré manuellement, et ajusté régulièrement. Cette étape est assez fastidieuse, c’est pourquoi nous préparons une implémentation permettant de définir ce seuil automatiquement à partir d’une dizaine de comparaisons de snapshots effectuées à l’initialisation, qui nous permettront de prendre la valeur moyenne de pixels différents pour cette série de comparaisons.

Voici un exemple de vue récapitulative de comparaison de snapshots :

Conclusion

Les déploiements de la plateforme Fasterize sont plus fiables que jamais! Les tests de snapshots nous permettent de rapidement identifier les changements ayant des impacts visuels sur les sites de nos clients.

Ces tests sont entièrement intégrés à notre processus de déploiement sur les différents environnements, comme le montre le schéma ci-dessous :

Nous pensons désormais à utiliser ces services de génération et comparaison de snapshots pour une autre utilité : offrir à nos clients une fonctionnalité de configuration automatique des règles d’optimisation Fasterize pour leur site. En effet, les comparaisons de snapshots permettraient d’identifier rapidement les règles d’optimisation Fasterize non compatibles avec le site, nous pourrions donc définir la combinaison de règles optimale pour le site.

Enfin, nous pensons à ouvrir l’API de génération et comparaison de snapshots au public.

Si vous êtes intéressés pour intégrer ce type de tests dans votre processus de déploiement, faites-nous signe! 😉


Hello SMX Paris !