Déploiement avec Capistrano et Github (sous Windows)

Le déploiement d’un site internet est toujours une opération un peu stressante lorsque l’on a beaucoup de taches à effectuer. Ça l’est encore plus lorsque celles-ci nécessitent des opérations manuelles comme l’upload de presque tous (surtout pas le dossier « upload »!) les fichiers via ftp, modification d’un table Sql, ajout d’un cron, etc… Bref si toutes ces opérations ne sont pas automatisées, cela peut prendre du temps et, comme tout bon humain que vous êtes, vous vous exposez à commettre des erreurs.

Pensez-vous que Facebook procède de la sorte? Je n’en suis pas sûr. D’autant plus qu’ils vont jusqu’à plusieurs déploiements par jour et qu’ils ont des centaines (voire des milliers) de serveurs. Je plains le petit monsieur de Facebook qui ouvre son « FileZilla » à chaque mise-à-jour. 🙂

Aujourd’hui, le déploiement automatisé existe et est à la porté de tous grâce à des outils comme « Capistrano ». Alors pourquoi ne pas vous y mettre?

Voici les quelques étapes pour déployer du code hébergé sur « Github ». J’ai pris Windows comme plateforme de déploiement, mais j’aurais très bien pu prendre « MacOs » ou « Linux ». La seule différence se situe dans l’installation de git et ruby.

 

Installer git

Git sera notre outils de versioning. Pour exécuter ses commandes, nous avons besoin de l’installer. Voici l’adresse pour l’installateur Windows: http://git-scm.com/download/win.

Après un « next, next, next », je vous propose de lancer « Git Bash » (gardez le ouvert, nous en aurons encore besoin) qui doit se trouver dans « C:/Program Files (x86)/Git » si vous n’avez pas créer de raccourci. Nous allons voir si vous pouvez accéder à votre repository sur github. Mettons nous d’abord dans un nouveau dossier qui va nous servir de test.

Ceci va créer un répertoire « mechant » dans votre dossier personnel (C:/Users/[votre utilisateur]), et vous y emmener.

 

Test de de la communication avec github

Récupérez ensuite l’adresse de votre repository Git. Pour ma part, j’ai pris « https://github.com/Nikoms/deployme.git » qui est un simple exemple créé pour l’occasion.

Il est possible que l’on vous interpelle:

The authenticity of host ‘github.com (192.30.252.130)’ can’t be established.
RSA key fingerprint is xx:xx:xx:xx…….
Are you sure you want to continue connecting (yes/no)?

Confirmez en tapant « yes ». Voici ce que vous devriez voir:

$ git ls-remote https://github.com/Nikoms/deployme.git
952c31e17af96d440057be81e2d09c8ed63c1fa3        HEAD
952c31e17af96d440057be81e2d09c8ed63c1fa3        refs/heads/master

Si vous ne voulez pas utiliser github en mode https, vous devrez générer des clés ssh. Je vous propose de suivre les recommandations ici : https://help.github.com/articles/generating-ssh-keys

 

Installer Ruby

Etant donné que Capistrano fonctionne sous Ruby, vous devez d’abord l’installer. Je vous rassure, vous n’allez pas coder une ligne de code 🙂

Comme nous lancerons notre déploiement sous windows, l’installation se fera via un simple « .exe » que vous trouverez ici: http://rubyinstaller.org/downloads/. N’oubliez pas d’indiquer qu’il faut ajouter « Ruby » dans votre variable « PATH » lors de l’installation.

Pour être certain que tout soit bien installé, dans « Git Bash », tapez « gem -v » (prononcez jèm). Si windows reconnait la commande, vous verrez la version installée.

 

Installation de Capistrano

Installons « la bête », via la console « Git Bash ». Voici la commande:

Voici le résultat:

Fetching: highline-1.6.19.gem (100%)
Successfully installed highline-1.6.19
Fetching: net-ssh-2.7.0.gem (100%)
Successfully installed net-ssh-2.7.0
Fetching: net-sftp-2.1.2.gem (100%)
Successfully installed net-sftp-2.1.2
Fetching: net-scp-1.1.2.gem (100%)
Successfully installed net-scp-1.1.2
Fetching: net-ssh-gateway-1.2.0.gem (100%)
Successfully installed net-ssh-gateway-1.2.0
Fetching: capistrano-2.15.5.gem (100%)
Successfully installed capistrano-2.15.5
Parsing documentation for highline-1.6.19
Installing ri documentation for highline-1.6.19
Parsing documentation for net-ssh-2.7.0
Installing ri documentation for net-ssh-2.7.0
Parsing documentation for net-sftp-2.1.2
Installing ri documentation for net-sftp-2.1.2
Parsing documentation for net-scp-1.1.2
Installing ri documentation for net-scp-1.1.2
Parsing documentation for net-ssh-gateway-1.2.0
Installing ri documentation for net-ssh-gateway-1.2.0
Parsing documentation for capistrano-2.15.5
Installing ri documentation for capistrano-2.15.5
6 gems installed

Voilà, c’était dur je sais, mais ça, c’est fait!

Création du projet

Vous êtes donc, à ce stade, dans votre dossier « mechant » dans « Git Bash ». Nous allons, à présent, créer un fichier qui va vous permettre de configurer les paramètres nécessaires au déploiement. Facile, une ligne de commande:

N’oubliez pas le « . » 🙂 Voici ce que vous devriez voir:

[add] writing ‘./Capfile’
[add] making directory ‘./config’
[add] writing ‘./config/deploy.rb’
[done] capified!

En d’autres termes, cette commande va vous créer un fichier de config (config/deploy.rb) et un scénario de déploiement (Capfile). Pour cet article, nous nous intéresserons uniquement au fichier de configuration.

 

Configuration

Ouvrez le fichier config/deploy.rb avec votre éditeur de texte préféré (notepad par exemple). Effacez tout le contenu, nous allons procéder par étape.

Tout d’abord, ajoutons les informations pour la connexion au serveur distant:

Je pense que tout ca est très clair 🙂

Passons à la configuration de git:

Capistrano ne fonctionne pas qu’avec git. Vous pouvez aussi déployer avec SVN, mercurial, etc… ou même sans repository!

La variable « deploy_via » est interessante, car elle vous permet  de déployer votre application de plusieurs manières différentes:

  • :copy : Fait un checkout en local (donc sous Windows), et envoi les fichiers (tar et gzipé) sur votre serveur distant. Pratique si votre serveur n’a pas Git installé et que vous n’avez pas la main dessus 🙂
  • :checkout (pas défaut si vous n’indiquez rien): Fait un clone sur le serveur distant. Il faut donc git installer sur celui-ci.
  • :remote_cache : Fait un « fetch » plutot qu’un « clone » sur le serveur distant. C’est options est donc plus rapide que « :checkout »

Passons aux rôles du/des serveurs:

Je n’ai qu’un seul serveur, les 3 adresses sont donc les mêmes. Vous pouvez avoir autant de serveur que vous le souhaitez

  • web: Adresse du serveur web. Pour les sites à fort trafic, vous avez sans doute plusieurs serveurs derrière un load balancer
  • app: Adresse du/des serveur(s) d’application
  • db: Adresse du serveur DB. Comme je n’en ai qu’un c’est le master.

Ces 3 variables sont obligatoires. Dans mon cas je n’ai pas de serveur DB, mais j’indique quand même l’ip du serveur. Je n’ai pas de migration de DB, donc de toute manière, aucune action ne sera exécutée.

Le plus gros est fait. Mais il reste encore 2 variables que j’aimerais vous présenter. Capistrano utilise beaucoup la commande « sudo » pour se mettre en « root ». Dans mon cas, je n’ai pas accès à cette commande. Pas de soucis, ils ont prévu le coup, on rajoute une ligne:

Dernière petite touche. En temps normal, Capistrano va faire un « touch » des dossiers « images », « stylesheets » et « javascripts ». Comme je n’en ai pas dans mon exemple, j’ajoute cette ligne:

Et voilà! C’est tout, vous êtes prêt à faire du déploiement automatisé. Bien entendu, il existe d’autres variables, en voici la liste: https://github.com/capistrano/capistrano/wiki/2.x-Significant-Configuration-Variables

 

Place au déploiement!

La première fois que vous allez déployer votre application, il faut d’abord que Capistrano crée une arborescence sur votre serveur distant. Dans « Git Bash », vous allez donc exécuter ceci:

Ceci va créer cette structure de dossiers sur votre serveur:

  • releases
  • shared
    • log
    • pids
    • system

Le dossier « releases » contiendra toutes les versions de vos déploiements rangés par date/heure. Nous y reviendrons plus tard.
Le dossier « shared » contiendra tout ce qui peut être partagé entre version, comme les logs, les fichiers uploadés par vos utilisateurs, etc…

Nous allons à présent faire un petit « check » pour voir si Capistrano pense que notre déploiement va fonctionner. Il vérifie les droits, l’existence de dossier, etc…

Si vous avez le message « You appear to have all necessary dependencies installed », c’est que ca s’annonce pas mal 🙂

Essayons donc de déployer notre code, en n’oubliant pas de croiser les doigts.

Cette petite commande en appelle d’autres:

  • cap deploy:update_code :
    • En local (parce que je l’ai précisé avec la variable deploy_via), il clone votre repository dans un dossier temporaire.
    • Compresse le dossier temporaire
    • Upload le fichier compressé sur le serveur distant
    • Décompresse le fichier dans le dossier « releases/[YmdHis] » (ex: 20110926162059 pour un déploiement à 16:20:59 le 16/09/2011) qui sera la release en cours.
  • cap deploy:finalize_update
    • crée les dossiers « log », « public », « tmp » dans votre release actuelle.
    • C’est ici que Capistrano fait un touch des assets (css, js, images) si vous n’indiquez pas « set :normalize_asset_timestamps, false« .
  • cap deploy:create_symlink
    • Crée un lien symbolique »current », au même niveau que « releases » et « shared », vers la release en cours.
  • cap deploy:restart
    • Ne fait rien dans notre cas

Etant donné que c’est notre premier déploiement, il faut encore créer un lien symbolique du dossier de notre site internet (ex: /home/monsiteInternet.com) vers le dossier « current » (/home/loginssh/deploy/current).  Pour tous vos prochains « deploy » , le lien symbolique de « current » se positionnera sur la bonne release, ce qui mettra votre site à jour automatiquement. Elle est pas belle la vie?

Bien sûr, qui dit déploiement, dit « rollback ». En effet, tout ca c’est génial, mais si vous remarquez que rien ne fonctionne comme il faut, il est nécessaire de pouvoir (vite) faire marche arrière. Rien de plus simple avec Capi’, une ligne de code suffit:

Avec cette commande, Capistrano va simplement changer le lien symbolique de « current » pour le placer sur la release précédente. Cela parait magique, mais comme toutes vos releases sont dans le dossier « releases », et rangées par date, il peut facilement la retrouver.

 

Conclusion

Nous sommes en 2013 et mettre à jour un site n’a plus rien de sorcier. Vous remarquez que cela peut aussi être fait sur un serveur qui n’a ni Git, ni Ruby installé, et ce, sans les droits « root ». Tout cela en une ligne de commande avec un taux d’erreur franchement très bas. Sans compter, le « rollback », tout aussi simple, qui est un sacré filet de sécurité « au cas où ».

Ce que je vous ai présenté n’est que la partie émergée de l’iceberg. Il y a un nombre incroyable de possibilités. En effet, vous pouvez à tout moment, lancer des lignes de commandes pendant la migration grâce aux « hooks ».

Voici un petit exemple très basique: j’aimerais créer un dossier « sql » juste après les opérations de « deploy:setup », rien de plus simple, je rajoute ceci à mon fichier:

Cela peut aller très loin, surtout qu’il existe des extensions à la pelle.

Je conseillerai à tout le monde d’au moins commencer par le déploiement de code, même si vous n’utilisez pas de système de versioning . Une fois que vous vous sentez à l’aise, passez aux assets, à la migration de base de données, etc…