juillet 31, 2011 2

Déploiements automatisés : ruby, ssh et doigts de pieds en éventail !

By in gestion de projets

Quand j’ai pris mes nouvelles fonctions, il y a quelques mois maintenant, au sein d’Ykone, j’avais beaucoup de travail en attente : des bugs, des évolutions, des améliorations… et pas mal de réflexion et un peu de recul sur les process en cours. J’ai déja abordé l’implantation de scrum chez nous, et si le travail est loin d’être achevé, tous les intervenants dans la boucle ont pris les devant et commencent à prendre leur part du travail très au sérieux (malgré quelques couacs inhérents à la taille de notre structure).

L’autre point très sensible qui m’a rapidement occupé (ne serait-ce que de part la réflexion nécessaire dans un premier temps), le workflow du pôle technique.

Avec une application de quelques 20 000 pages, 3 langues, des centaines de marques référencées, des milliers de visuels de bonne qualité, 2 webservices, 2 flux à destination de partenaires, plusieurs bases de données … en bref, notre projet est devenu une vraie grosse application. Mais, la complexité croissante, malgré l’équipe grandissante, à mon arrivée, les mises en productions se jouaient de la manière suivante : après avoir développé un nouveau module, une nouvelle fonctionnalité, les développeurs devaient suivre une “todo list” des fichiers a pousser en production via ftp, jouer les fichiers sql nécessaires à la mise a jour de la base, et vérifier que tout fonctionne bien. Avec au passage, plusieurs problèmes : oubli de versionner les fichiers concernés, possibilité d’écraser le travail des collègues, css et js a compresser et concaténer à la main avant déploiement, avec le risque encore une fois d’en oublier, obligation de flusher le cache du CDN à la main … Bref, sur de projets de petite envergure, ça peut être tolérable, mais, dans une équipe de 3 ou 4, ça devient vite l’enfer, augmentant le risque d’erreurs, le stress, et du coup les prises de tête.

Aussi ai-je décidé qu’il fallait en finir avec ces situations ou l’échec et la frustration n’avaient finalement pas leur place : une mise en production, surtout après des itérations d’une a deux semaines, se doit d’etre simple, rapide, sure.

Capistrano, l’arme ultime pour des déploiements maitrisés et sûrs

Capistrano est une gem ruby vous permettant de configurer ce que l’on appelle des “recettes”.

Une recette est la procédure, plus ou moins simple, que Capistrano va suivre à la lettre pour executer vos moindres ordres.

Dans la pratique, nous avons décidé de tirer parti du plugin Multistage de Capistrano pour définir à la lettre les comportements espérés pour nos différents environnements de staging. Nous disposons en effet d’une préprod, classique et (espérée) parfaite réplique de la prod, de la prod donc, et d’un troisième environnement de recette propre à chaque développeur.

Capistrano prend tout son sens lorsque l’on détaille une recette:

Clairement, rien de très sorcier. On définit les variables destinées aux connections ssh, les paramètres scm (git, bazaar, svn etc …), puis on étend la tache pour créer un certains nombre liens symboliques, quelques chmod, et le tour est joué.

Pour lancer un déploiement, encore une fois, la simplicité est de mise :

cap prod deploy

C’est aussi simple.

D’autres exemples, et plus de documentation et d’exemple sur le wiki du github du projet. Mais si capistrano à ainsi réglé nos problemes de déploiement, certains point noirs subsistent . En particuliers, la compression des css et js.

YUI-compressor et uglify-js : ultimate combo

Encore une fois, sur des projets de petite envergure, la compression des css et des jss peut facilement se faire à la main avant déploiement. Mais, après avoir vu avec quelle facilité Capistrano peut manipuler les fichiers d’un projet versionné, j’ai donc décidé de mettre en place un hook post deploiement pour compresser, avec les outils de mon choix, css et js. C’est à ce moment là qu’interviennent le yui-compressor pour les css, et uglify-js pour toute la codebase javascript.

Bundle-phu, concaténation à la volée et mise en cache des css et js qu’il vous faut

Si vous avez suivi, pour le moment, nous disposons de css et de js compressés, mais tout le monde vous dira que moins de requetes http, c’est  mieux. Notre application tourne sous ZEND framework. Tous les assets sont chargés avec l’aide de 2 helpers de vue :

$view->headScript() et $view->headLink()

Résumé du processus de déploiment pour notre application php

Bundle-phu, inspiré du plugin Ruby on Rails bundle-fu, permet par défaut de compresser tous les fichiers css et js à la volée, d’en créer un unique, et de le cacher. Dans notre cas, seule la concaténation et la gestion du cache nous intéresse, ne voulant pas alourdir inutilement le chargement des fichiers avec un passage inutile par les yuicompressor (en prod qui plus est, aucune raison selon moi d’alourdir notre serveur déja bien occupé avec d’autres choses, comme le ZEND par exemple, mais ça c’est une autre histoire…).

Au final, en supprimant tout le surplus inutile, on profite d’un système de concaténation et de caching simple, efficace, et très léger, à base de MD5 et de filemtime().

Qu’est ce qu’on y gagne ?

Je ne nierai pas que la réflexion, le choix, et la mise en œuvre de ce processus à nécessité plus de temps que prévu. Entre les évolutions, les développements, les kickoffs pour de nouveaux projets,  le manque de temps temps de tous pour monitorer le bon fonctionnement, nous avons mis, grosso-modo, 2 ou 3 semaines (interrompues et non consécutives, cela va de soi) pour traiter ce sujet. Mais le jeu en valait la chandelle.

  • Des releases stables, avec rollback faciles en cas d’erreur(s).
  • Mettre en production en 5/10 minutes, c’est quand même autre chose qu’un déploiement par ftp peu sûr et long…
  • Une contrainte de moins, c’est moins de stress, et la possibilité de se concentrer sur les livrables, pas la livraison.
  • En automatisant la compression de assets et leur concaténation, on s’assure une qualité constante, sans surprise
  • Enfin, l’emploi de Capistrano permet de rapidement mettre en place de nouvelles actions, l’intégration de nouveaux outils, via quelques lignes de plus dans ces fameuses recettes.

Au final, avec quelques mesures simples, un peu d’huile de coude, et une bonne documentation, tout le monde est ravi au sein de l’équipe. Certains points restent à affiner, comme par exemple la gestion du déploiement de tags svn (oui, nous sommes en svn au bureau), pour éviter le déploiement du trunk complet,le jeu de tests unitaires et fonctionnels avant déploiement, ou l’envoi d’un mail en cas de déploiement reussi ou échoué…

Il est important de noter au passage que Capistrano vous permet de gérer et d’agir sur un nombre illimité de serveurs en même temps, avec la même recette.

D’autres solutions de déploiements à envisager

Et vous, qu’attendez vous pour automatiser cette partie de votre workflow ? Avez-vous d’autres techniques intéressantes pour faire de vos déploiements une étape simple et sans douleur ?

Tags: , , ,

2 Responses to “Déploiements automatisés : ruby, ssh et doigts de pieds en éventail !”

  1. Bien le bonjour,

    Pour notre part (lol), nous utilisons la fonction de déploiement intégrée à symfony qui fait un simple rsync du svn (trunk, branch, tag, peu importe) et le déploie sur l’environnement voulu :
    (à la racine de symfony)
    ./symfony project:deploy appname environment –go
    L’argument go permet de lancer le déploiement, sans cela, c’est une “répétition” du déploiement.

    Cela a quelques contraintes bien sûr :
    - la compression des assets doit être faites en amont sur la pre-prod
    - les scripts sql à jouer se font directement en prod via des migrations doctrine (déjà répétées en pre-prod) mais lancées à la main, ce qui peut induire des erreurs humaines

    Cet article m’a donné envie d’automatiser tout cela.
    Mais je pencherai peut-être plus pour fabric (l’habitude).

    Merci beaucoup madame.

  2. pixelboy dit :

    Hello,

    concernant fabric, quand tu parles d’habitudes, tu parles de la syntaxe , de python, ou de son utilisation dans un autre environnement que les vôtres (lol bis) ?
    En effet, l’un des aspects non abordés dans cet article concerne justement les mise a jours de base. Actuellement, notre équipe génère des sql que l’on doit jouer, quand bon nous semble, en local, en preprod, ou prod. Mais rien n’est exclu concernant la possibilité de les jouer un a un une fois le déploiement terminé. Nous ne nous sommes pas encore penchés sérieusement sur la question pour des raisons de temps, et parce que les habitudes ont parfois la vie dure.

    Content en tout cas que cet article t’aie donné envie d’aller encore plus loin que ce que l’excellent Symfony offre déjà.

    A bientôt ma petite ;)

Leave a Reply