Points de contrôle automatisés avant un développement ou comment maîtriser un déploiement
Vous avez une mise en production hyper importante aujourd'hui. Votre client (interne) vous a mis la pression et vous avez dû raccourcir les délais pour être à l'heure. Vous packagez votre release d'application, vous la passez sur l'environnement de tests fonctionnels, tout se passe bien. Vous la passez sur l'environnement d'intégration et tout se passe bien, mais vous noter un ou deux comportement étrange, sans gravité, bizarre. Vous décidez de la passer en pré-production, et là ... Tout plante ! L'application ne se lance même plus et c'est la page blanche...
Vous avez une mise en production hyper importante aujourd'hui. Votre client (interne) vous a mis la pression et vous avez dû raccourcir les délais pour être à l'heure. Vous packagez votre release d'application, vous la passez sur l'environnement de tests fonctionnels, tout se passe bien. Vous la passez sur l'environnement d'intégration et tout se passe bien, mais vous noter un ou deux comportement étrange, sans gravité, bizarre. Vous décidez de la passer en pré-production, et là ... Tout plante ! L'application ne se lance même plus et c'est la page blanche...
Pourquoi ?
Vous investiguez et vous découvrez que l'environnement de pré-production n'est absolument pas à jour (choisissez une ou plusieurs lignes dans la liste) :
- mauvaise version de PHP
- mauvaise version de votre framework MVC habituel
- mauvaise version de votre librairie de composants interne partagée
- extension SOAP manquante
- répertoire de log inexistant sur la machine (votre application ne le crée pas si il n'existe pas...)
- connexion à la base de données non fonctionnelle car les identifiants ont changé...
- ...
La catastrophe.
Vous décidez donc de regarder sur la machine de production, et bien sûr vous faites les mêmes découvertes...
Résultat: votre mise en production est décalée de 1/2 journée, vous mettez la pression aux équipes plateformes pour qu'elles mettent tous les environnements à jour, et vous prenez un savon par votre client (interne) qui vous prend pour un amateur.
Comment éviter cela ?
Vous pouvez acheter le dernier outils à la mode qui compte XXXX k€ et qui vérifie tout, mais c'est long à mettre en place et surtout ca coûte très cher dans votre budget (ou celui des équipes plateformes), en plus les tests réalisés seront soit très générique soit il faudra peut être un peu tordre l'outils pour faire certaines vérifications un peu spécifique à votre application (test de la connexion mysql, vérification de la version de votre framework préféré...)
Une autre solution consiste à réaliser un petit script, PHP, qui va faire tous les tests spécifiques qui vous intéresse et vous faire un rapport directe. Appellons le "PHP Sanity Check(er)".
Une contrainte cependant : tout doit tenir dans un script (1 fichier) et aucune installation ou dépendance autre que le dépôt du fichier dans l'arborescence du serveur web ne doit être nécessaire. En effet, il serait dommage que votre script ne fonctionne qu'avec une dépendance à la librairie TUTU et que cette librairie ne soit pas installée sur la plateforme (qui le vérifierait ?)
Le script peut être très simple et faire une série de version_compare(), de stream_socket_client(), de file_exists(), extension_loaded(), de vérification de variable $_SERVER.... c'est du PHP, vous pouvez donc tout faire ;), par contre, avant d'utiliser mysql(i)_connect, vérifiez (via un test dans le script) que l'extension mysql(i) est bien chargée !
Oui mais j'ai plusieurs applications croisées avec plusieurs environnements, ce qui m'oblige à faire des suites de tests différentes, comment faire ? je duplique le script pour chacun des cas et je maintiens les différentes versions ? une usine à gaz !
Non.
Vous êtes malin.
Vous développez donc une seule fois, vous faites des fichiers de configuration spécifiques à chacun des applications/environnements et "vous générez un script spécifique pour chacun des cas".
Comment ?
Grâce, par exemple à Phing et Phar.
Vous créez votre script générique qui prend une liste de tests écrit dans un fichier de configuration (par exemple xml). Voici un exemple de fichier :
<?xml version='1.0' encoding='iso-8859-1' ?> <psc> <test info="PHP Version" type="php:minimum-version" arg1="5.0.0"/> <test info="Windows Platform" type="php:os" arg1="winnt"/> <test info="Google is Reachable" type="network:tcp-port-reachable" arg1="www.google.com" arg2="80"/> </psc>
Votre script lit le contenu du fichier xml, en sort une liste de tests correspondant à des appels de méthodes de classes :
- Php::checkMinimumVersion('5.0.0')
- Php::checkOs('winnt')
- Network::checkTcpPortReachable('www.google.com','80')
Vous écrivez ensuite les classes Php (dans Php.php ;)) et Network (dans Network.php) qui contiennent chacunes les méthodes listées, vous pouvez bien sûr en rajouter d'autres, si elles ne sont pas listées dans le fichier de configuration elle ne seront pas utilisées.
Vous faites en sorte que chacune des méthodes lève une exception si le test ne passe pas avec un message d'erreur compréhensible sur le problème.
A l'exécution, vous récupérez le résultat d'exécution de chacune des méthodes (en faisant un try/catch par dessus) et vous affichez cela dans un tableau HTML qui va bien avec des couleurs verte et rouge.
Mais à quoi sert Phar ?
Venons-en à Phar. Phar ou encore "PHP Archive" permet de condenser plusieurs scripts PHP dans un seul fichier (.phar), il peut être compressé ou non. Le moteur PHP saura exécuter le fichier .phar comme si il était un script .php La seule différence est que le .phar contenant plusieurs fichiers php, il faut lui indiquer précisément quel est le premier script a exécuter (celui-ci pourra faire des includes des autres éventuellement).
Vous pouvez donc faire plein de fichiers/scripts/classes dans votre outils et les packager dans un seul et même fichier .phar en y embarquant même le fichier de configuration nécessaire. A l'exécution, vos scripts se comporteront comme si ils étaient dans un répertoire sur le disque et vous pourrez utiliser les includes.
Mais à quoi sert Phing ?
Phing, est un outils de scripting cross-platform (xml) écrit en PHP (port de Ant venant de Java). Il permet de décrir des batchs de commandes (systèmes souvent) à réaliser sous forme xml (ca marche donc sous windows, mac, linux...), voici ce que nous pourrions faire pour packager notre PHP sanity Checker pour générer un .phar à installer sur les plateformes pour notre application TOTO :
<target name="package" depends="init" description="Packages the phar script to deploy on platform (use -Dsuite=<your-suite>)">
<delete dir="tmp/package"/>
<mkdir dir="tmp/package"/>
<mkdir dir="tmp/package/config/suites"/>
<copy file="config/suites/${suite}.xml" tofile="tmp/package/config/suites/default.xml"/>
<copy todir="tmp/package">
<fileset dir=".">
<include name="**/*.php"/>
</fileset>
</copy>
<phar to="tmp/check.phar">
<fileset dir="tmp/package">
<include name="**/*"/>
</fileset>
</phar>
</target>
Pour exécuter cette liste de commandes, vous faites :
$ phing package -Dsuite=mon-application
ce qui aura pour but de packager le fichier mon-application.xml avec vos scripts php (ceux de votre outils de tests) dans un fichier tmp/check.phar.
Dernière étape, vous déployez (vous copiez) le fichier check.phar sur votre plateforme cible dans l'arborescence du serveur web, et vous accédez à ce fichier comme si il s'agissait d'un fichier .php (configurer apache pour qu'il traite les fichiers .phar comme les fichiers .php).
Des commentaires ?
Commentaires
Tu ne veux pas faire une usine à gaz, mais tu t'embarques avec phing, phar et un fichier de config. XML.
OK, tu n'as qu'un seul script PHP à maintenir, mais par contre tu te retrouves avec X fichiers de config. XML.
Je pense qu'un script PHP pour chaque couple application/environnement serait une solution plus simple et donc plus efficace.
Effectivement on aurait pu se passer de Phar et Phing en ayant par exemple 1 fichier de script générique, n fichiers de configuration. Ca m'embête vis a vis du processus de livraison pour mes équipes de production, mais c'est tout a fait faisable et pertinent.
Par contre, faire 1 script spécifique par couple application/environnement, ca oblige à dupliquer la partie commune (affichage du résultats, code des tests de vérifications...) ce qui multiplie les erreurs possibles et rend plus difficile la maintenance. J'avoue cependant que c'est souvent ce que l'on rencontre dans les projets, car ca reste la solution la plus simple.
Par contre, qui/quoi garantit que ton / tes scripts de vérification ne contiennent pas d'erreurs et qu'il te dise que la connexion mysql testée est en succès alors que c'est faux ? Il peut être nécessaire d'ajouter des tests unitaires pour vérifier que les tests de santé que tu réalises sont bien implémentés et fonctionnent tel que prévu. Si tu as plusieurs scripts avec du code dupliqué, tu auras des tests dupliqués aussi, ce qui n'est pas optimal et une vraie contrainte pour les développeurs...
Il existe donc plusieurs méthodes, à choisir en fonction des besoins et des contraintes. De mon côté, tous les développements PHP sont accompagnés de tests unitaires cela à donc un impact sur l'architecture du code et notamment la mutualisation des méthodes/fonctions. D'autre part, j'évolue déjà dans un environnement Phing, la cout de mise en oeuvre est donc limité pour ma part.
En tout cas merci pour ton retour qui est une critique très intéressante !
Aller, j'enfonce le clou : tu dis que le script ne doit pas dépendre d'une bibliothèque. Mais il faut avoir installé l'extension phar sur toutes les becanes pour que ta solution fonctionne !
;-)
De mémoire (à vérifier), un phar est exécutable par PHP même si l'extension Phar n'est pas activé (c'est un des intérêts). Exemple : quand tu installes PHP sur ta machine en local (par exemple sous windows), tu peut ajouter le support de Pear, pour cela tu dois exécuter le fichier go-pear.phar (de mémoire encore) qui fonctionne même si ton installation de php est standard (je ne crois pas qu'avant la version 5.3 l'extension phar soit activée par défaut).
Depuis la 5.3, l'extension phar en native (de mémoire encore).
Je pense donc que ca ne pose pas de problème, mais dès que j'ai 5 minutes je teste, si ca ne marche pas je vous le dis.
Dans l'hypothèse ou ca ne fonctionnerait pas, ton script serait en erreur (il ne se lancerait pas), et tu le verrais tout de suite à son exécution, ce n'est donc pas une erreur silencieuse, et tu peux y remédier tout de suite. Le niveau de criticité me semble donc assez bas à partir du moment ou tu peux ajouter des extensions sur le serveur en fonction des besoins.
Il est probable, bien que l'extension phar ne soit pas nécessaire pour exécuter un phar, que les extensions de compression le soit tu as compressé ton phar (à vérifier). Mais je ne vois pas l'intérêt de compresser le phar dans notre cas.