{"id":1904,"date":"2018-02-05T10:00:56","date_gmt":"2018-02-05T09:00:56","guid":{"rendered":"https:\/\/blog.alwaysdata.com\/?p=1904"},"modified":"2020-07-07T11:53:54","modified_gmt":"2020-07-07T09:53:54","slug":"deployer-sans-peine-avec-git-hooks","status":"publish","type":"post","link":"https:\/\/blog.alwaysdata.com\/fr\/2018\/02\/05\/deployer-sans-peine-avec-git-hooks\/","title":{"rendered":"D\u00e9ployer sans peine avec Git&nbsp;hooks"},"content":{"rendered":"<p><em>alwaysdata<\/em> vous offre un grand nombre d\u2019acc\u00e8s distants \u00e0&nbsp;vos comptes&nbsp;: SSH, FTP, WebDAV\u2026 Pourtant, d\u00e9ployer un site ou un service en production manque parfois de souplesse. Alors nous avons pens\u00e9 \u00e0&nbsp;vous.<\/p>\n<div class=\"embed-media__giphy\" style=\"width:65%;padding-bottom:47%;\"><img decoding=\"async\" alt=\"sarcastic joke GIF @Giphy\" src=\"https:\/\/media.giphy.com\/media\/CggoHW4h87Ktq\/giphy.gif\"><\/div>\n<h2>Oh oui <em>alwaysdata<\/em>, raconte-nous le d\u00e9ploiement&nbsp;!<\/h2>\n<p>Il y&nbsp;a des choses parfois plus simples que d\u2019autres dans nos m\u00e9tiers de d\u00e9veloppeur\u00b7euse\u00b7s. Le d\u00e9ploiement ne fait malheureusement pas partie de celles-ci. Entre la livraison en FTP, \u00e0&nbsp;l\u2019ancienne&nbsp;; la copie de fichier en SFTP&nbsp;; l\u2019application de patch \u00e0&nbsp;distance\u2026 Il y&nbsp;en a&nbsp;pour tous les go\u00fbts et tous les projets.<\/p>\n<p>Une solution comme <a href=\"https:\/\/www.heroku.com\/\">Heroku<\/a> l\u2019a bien compris&nbsp;: celui ou celle qui produit le code n\u2019a pas \u00e0&nbsp;s\u2019ennuyer avec les probl\u00e9matiques li\u00e9es au d\u00e9ploiement, mais doit se concentrer sur son m\u00e9tier&nbsp;: produire un code de qualit\u00e9. Or tout le monde n\u2019a pas la main sur un\u00b7e DevOp qui va se charger de mettre en production la derni\u00e8re version pour vous laisser travailler. Dans ce cas, vous n\u2019avez pas le choix, il va falloir vous en occuper vous-m\u00eame.<\/p>\n<p>Parce qu\u2019<em>alwaysdata<\/em> est un h\u00e9bergement pens\u00e9 par des d\u00e9veloppeurs, nous nous sommes interrog\u00e9s sur la bonne mani\u00e8re de d\u00e9ployer en production. Nous avons dans nos projets un outil d\u2019automatisation des processus de d\u00e9ploiement, mais la priorit\u00e9 va d\u2019abord au support d\u2019autres technos comme <strong>HTTP\/2<\/strong>.<\/p>\n<p>Alors en attendant, nous avons cherch\u00e9 \u00e0&nbsp;vous simplifier la vie. Et tout comme vous, nous pr\u00e9f\u00e9rerions faire nos livraisons en une ligne de commande. On s\u2019est donc pench\u00e9s sur un d\u00e9ploiement <em>via<\/em> Git.<\/p>\n<h2>Git <code>push<\/code>. Point.<\/h2>\n<div class=\"embed-media__giphy\" style=\"width:65%;padding-bottom:39%;\"><img decoding=\"async\" alt=\"excited friends tv GIF @Giphy\" src=\"https:\/\/media.giphy.com\/media\/artr28YUQ6S0o\/giphy.gif\"><\/div>\n<p>Voil\u00e0 donc ce que nous vous proposons, \u00e0&nbsp;l\u2019image de services conteneuris\u00e9s&nbsp;: un simple <code>git push<\/code> d\u2019une branche de production et c\u2019est&nbsp;r\u00e9gl\u00e9.<\/p>\n<p><em>TL;DR<\/em>&nbsp;: Si vous souhaitez comprendre la m\u00e9canique parce que vous \u00eates curieux\u00b7euse, continuez ici. Si vous souhaitez juste mettre en place le d\u00e9ploiement, vous pouvez directement vous rendre sur le d\u00e9p\u00f4t GitHub <a href=\"https:\/\/github.com\/alwaysdata\/autodeploy-git-hook\">alwaysdata\/autodeploy-git-hook<\/a> o\u00f9 un <em>README<\/em> succinct vous guidera sur la mise en&nbsp;place.<\/p>\n<p>Voyons comment d\u00e9marrer. Il vous faudra&nbsp;:<\/p>\n<ul>\n<li>un acc\u00e8s <strong>SSH<\/strong> pour les r\u00e9glages<\/li>\n<li>votre code versionn\u00e9 avec <strong>Git<\/strong><\/li>\n<li>conna\u00eetre les principes des <em>git-hooks<\/em> (mais \u00e7a, on va vous expliquer)<\/li>\n<li><del>des \u0153ufs, de la farine, du&nbsp;lait<\/del><\/li>\n<\/ul>\n<h3>C\u00f4t\u00e9 serveur<\/h3>\n<p>Commen\u00e7ons par cr\u00e9er un d\u00e9p\u00f4t git contenant votre projet sur votre serveur <em>alwaysdata<\/em> (bien entendu, je vous laisse le soin d\u2019adapter les chemins \u00e0&nbsp;votre convenance, rien d\u2019obligatoire)&nbsp;:<\/p>\n<pre><code class=\"shell\">$ ssh mon-compte@ssh-mon-compte.alwaysdata.net\n$ git init --bare ~\/mon-projet.git\n<\/code><\/pre>\n<p>Nous initialisons le d\u00e9p\u00f4t en version <code>bare<\/code>, c\u2019est-\u00e0-dire qu\u2019il ne contient que les fichiers de <em>config<\/em> et de <em>versioning<\/em>. Dans notre cas, comme nous ne cherchons \u00e0&nbsp;faire que du d\u00e9ploiement, nous n\u2019avons pas besoin de&nbsp;plus.<\/p>\n<p>Ensuite, nous allons cr\u00e9er un script de <code>post-receive<\/code>. C\u2019est lui qui, comme son nom l\u2019indique, sera appel\u00e9 lors d\u2019un <code>push<\/code> vers ce d\u00e9p\u00f4t, avec les r\u00e9f\u00e9rences vers la branche pouss\u00e9e. Nous allons nous en servir pour tester la branche (par exemple, une branche nomm\u00e9e <code>production<\/code>), et d\u00e9ployer le contenu de celle-ci vers le dossier servi par notre instance Apache. Cr\u00e9ez donc sur votre serveur un fichier <code>~\/mon-projet.git\/hooks\/post-receive<\/code> avec le contenu suivant&nbsp;:<\/p>\n<pre><code class=\"shell\">#!\/bin\/bash\nwhile read oldrev newrev ref\ndo\n    if [[ $ref = refs\/heads\/production ]];\n    then\n        echo \"Deploying 'production' branch to production\"\n        git --work-tree=$HOME\/www\/mon-projet --git-dir=$(dirname $PWD) checkout --force production\n        exit 0\n    fi\ndone\n<\/code><\/pre>\n<p>Nous testons que c\u2019est bien la branche <code>production<\/code> qui vient d\u2019\u00eatre pouss\u00e9e, et nous r\u00e9alisons dans ce cas un <code>checkout<\/code> vers le dossier <code>~\/www\/mon-projet<\/code> (le chemin que vous avez d\u00e9fini pour votre site dans l\u2019interface d\u2019administration) qui contient les fichiers servis par le serveur HTTP.<\/p>\n<p>N\u2019oubliez pas de rendre le script ex\u00e9cutable avec <code>chmod +x ~\/mon-projet.git\/hooks\/post-receive<\/code>.<\/p>\n<h3>En local<\/h3>\n<p>Revenez maintenant dans votre d\u00e9p\u00f4t local sur votre machine de d\u00e9veloppement. Rendez-vous dans votre projet, et ajoutez le d\u00e9p\u00f4t de d\u00e9ploiement situ\u00e9 sur votre serveur <em>alwaysdata<\/em>&nbsp;:<\/p>\n<pre><code class=\"shell\">$ cd mon-projet\n$ git remote add deploy mon-compte@ssh-mon-compte.alwaysdata.net:~\/mon-projet.git\n<\/code><\/pre>\n<p>Et voil\u00e0&nbsp;! Il vous suffit maintenant de pousser la branche <code>production<\/code> vers ce d\u00e9p\u00f4t, et le d\u00e9ploiement sera automatique&nbsp;:<\/p>\n<pre><code class=\"shell\">$ git push deploy production\nCounting objects: 3, done.\nDelta compression using up to 4 threads.\nCompressing objects: 100% (2\/2), done.\nWriting objects: 100% (3\/3), 291 bytes | 291.00 KiB\/s, done.\nTotal 3 (delta 1), reused 0 (delta 0)\nremote: Deploying 'production' branch to production\nremote: Already on 'production'\nTo mon-compte@ssh-mon-compte.alwaysdata.net:~\/mon-projet.git\n   39949b8..86bd6c7  production -&gt; production\n<\/code><\/pre>\n<p>D\u00e9sormais, il vous suffit de <em>merge<\/em> sur votre branche de <code>production<\/code> la derni\u00e8re version \u00e0&nbsp;d\u00e9ployer, de <code>git push<\/code> sur le serveur, et le tour est&nbsp;jou\u00e9&nbsp;!<\/p>\n<h2>Oui, mais moi, je ne fais pas que d\u00e9ployer des fichiers statiques<\/h2>\n<p>Alors effectivement, nous avons illustr\u00e9 un cas assez simple ici, et nous sommes conscients que vous avez probablement d\u2019autres routines \u00e0&nbsp;mettre en place lors d\u2019un d\u00e9ploiement.<\/p>\n<p>Vous pouvez, par exemple, avoir besoin de relancer votre instance Apache pour que les changements soient pris en compte. Dans ce cas, il suffit d\u2019ajouter au <em>hook<\/em> <code>post-receive<\/code> la ligne suivante, juste apr\u00e8s l\u2019instruction <code>git checkout<\/code>&nbsp;:<\/p>\n<pre><code class=\"shell\">curl --basic --user \"API_KEY account=ACCOUNT:\" --data '' --request POST https:\/\/api.alwaysdata.com\/v1\/site\/SITE_ID\/restart\/\n<\/code><\/pre>\n<p>Cette requ\u00eate cURL va appeler l\u2019API d\u2019<em>alwaysdata<\/em> en utilisant votre <em>cl\u00e9 d\u2019API<\/em>, nom de <em>compte<\/em>, et <em>identifiant de site<\/em> \u00e0&nbsp;red\u00e9marrer pour relancer le service de fa\u00e7on transparente.<\/p>\n<p>L\u00e0 encore, rien de plus \u00e0&nbsp;faire d\u00e9sormais que de pousser la branche de <code>production<\/code>.<\/p>\n<h2>Encore&nbsp;!<\/h2>\n<div class=\"embed-media__giphy\" style=\"width:65%;padding-bottom:36%;\"><img decoding=\"async\" alt=\"theres more cole sprouse GIF @Giphy\" src=\"https:\/\/media.giphy.com\/media\/l0Exdm9UbTHAFcJi0\/source.gif\"><\/div>\n<p>Vous en voulez encore&nbsp;? Avec plaisir&nbsp;!<\/p>\n<p>Vous avez probablement besoin d\u2019automatiser le processus sur plusieurs sites. Nous avons donc lib\u00e9r\u00e9 le code source de ce petit hook sur le d\u00e9p\u00f4t GitHub <a href=\"https:\/\/github.com\/alwaysdata\/autodeploy-git-hook\">alwaysdata\/autodeploy-git-hook<\/a>. Le script est configurable avec des variables bash en haut du fichier, pour que vous ayez le moins de changements \u00e0&nbsp;effectuer.<\/p>\n<p>Nous sommes malgr\u00e9 tout conscients que ce script est encore rudimentaire. Vous avez probablement des migrations \u00e0&nbsp;jouer sur vos bases de donn\u00e9es, ou des appels \u00e0&nbsp;faire pour mettre \u00e0&nbsp;jour vos <em>assets<\/em> statiques lors d\u2019une mise \u00e0&nbsp;niveau. N\u2019h\u00e9sitez pas \u00e0&nbsp;nous faire part de vos besoins dans les <strong><a href=\"https:\/\/github.com\/alwaysdata\/autodeploy-git-hook\/issues\">issues<\/a><\/strong> du d\u00e9p\u00f4t, ou \u00e0&nbsp;proposer vos <a href=\"https:\/\/github.com\/alwaysdata\/autodeploy-git-hook\/pulls\">pull-requests<\/a> pour que nous puissions am\u00e9liorer encore cet outil ensemble.<\/p>\n<div class=\"embed-media__giphy\" style=\"width:65%;padding-bottom:36%;\"><img decoding=\"async\" alt=\"helpful bill murray GIF @Giphy\" src=\"https:\/\/media.giphy.com\/media\/l0ErK5H6exTmBN7ri\/giphy.gif\"><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Vous en avez assez des processus de d\u00e9ploiement fastidieux pour mettre votre projet en ligne&nbsp;? Passez \u00e0&nbsp;la vitesse sup\u00e9rieure en laissant Git d\u00e9ployer \u00e0&nbsp;votre place&nbsp;!<\/p>\n","protected":false},"author":12,"featured_media":3422,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"wp_typography_post_enhancements_disabled":false,"footnotes":""},"categories":[230],"tags":[167,169,174,196,197],"class_list":["post-1904","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized-fr","tag-deploiement-fr","tag-devops-fr","tag-git-fr","tag-script-fr","tag-shell-fr"],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.alwaysdata.com\/fr\/wp-json\/wp\/v2\/posts\/1904","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.alwaysdata.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.alwaysdata.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.alwaysdata.com\/fr\/wp-json\/wp\/v2\/users\/12"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.alwaysdata.com\/fr\/wp-json\/wp\/v2\/comments?post=1904"}],"version-history":[{"count":0,"href":"https:\/\/blog.alwaysdata.com\/fr\/wp-json\/wp\/v2\/posts\/1904\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.alwaysdata.com\/fr\/wp-json\/wp\/v2\/media\/3422"}],"wp:attachment":[{"href":"https:\/\/blog.alwaysdata.com\/fr\/wp-json\/wp\/v2\/media?parent=1904"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.alwaysdata.com\/fr\/wp-json\/wp\/v2\/categories?post=1904"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.alwaysdata.com\/fr\/wp-json\/wp\/v2\/tags?post=1904"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}