J'avais expliqué dans un post précédent que je déployais ce site avec git. Voici comment j'ai récemment amélioré mon modus operandi pour éviter d'avoir à lancer un git pull côté serveur.

Jusqu'ici, mon site se trouvait dans un dépôt "classique" (cloné), directement servi par Apache. Ceci comportait deux désavantages :

  • A chaque modification, je devais me connecter en SSH au serveur, pour faire un pull des changements.

  • En cas de faille de sécurité, l'intégralité du dépôt (c'est-à-dire le contenu du sous-dossier .git) était potentiellement accessible depuis Internet. Or il n'est pas complètement impossible qu'à un moment ou à un autre j'aie commité des informations que je ferais mieux de ne pas divulguer.

Quelques recherches m'ont montré que la bonne technique consiste à utiliser un "bare repo" -- un "dépôt nu", c'est-à-dire réduit à sa plus simple expression : le contenu du dossier caché .git.

Contrairement au dépôt classique, un dépôt nu ne comporte pas de working tree (les fichiers qui sont d'habitude "visibles à l'oeil nu" quand vous clonez votre projet). Sa vocation n'est pas de fournir un espace de travail, mais simplement de conserver la mémoire du projet. En définitive, c'est exactement ce qui se cache derrière vos dépôts origin, qu'ils soient hébergés par GitHub, Gitlab ou Bitbucket.

Bref, j'ai suivi ce tuto, très bien fait. En voici les grandes lignes.

  1. Créer le dépôt nu. Par convention, il est généralement rangé sous /srv/git, et suffixé en .git.

    sudo git init --bare ORIGIN_REPO.git MY_APP.git

    Définir sur ce dossier des permissions qui vous permettront d'y écrire sans droits root. Pour moi, c'est très simple: je suis l'unique utilisateur de la machine.

    sudo chown -R ME:ME MY_APP.git
  2. Mettre en correspondance votre dépôt local et votre nouveau dépôt nu. Depuis votre dépôt local, deux possibilités s'offrent à vous. Vous pouvez attribuer un nom à ce remote, par exemple deploy :

    git remote add deploy ssh://ME@MY_IP/srv/git/MY_APP.git/

    Conséquence : quand vous voudrez pousser sur origin et déployer en même temps, il vous faudra exécuter deux pushs :

    git push origin
    git push deploy

    Mais vous pouvez aussi attribuer deux URL à origin :

    git remote set-url --add --push origin ORIGIN_REPO.git
    git remote set-url --add --push origin ssh://ME@MY_IP/srv/git/MY_APP.git/

    Dans ce cas, il vous suffira de pousser sur origin pour que votre nouveau dépôt nu soit impacté.

    Attention, il faut exécuter le set-url pour les deux adresses, sinon la nouvelle écrasera l'ancienne au lieu de s'y ajouter.

    Dans tous les cas, faites au moins un commit et un push vers votre dépôt nu, pour qu'il récupère la branche voulue (dans mon cas tout simplement master) : git push deploy master ou git push origin master, selon l'option choisie.

  3. Créer le fichier /srv/git/MY_APP.git/hooks/post-receive :

    #!/bin/sh
    
    # Le répertoire qui sera servi en http
    TARGET="/var/www/html/MY_APP"
    
    # Un espace de travail temporaire,
    # où on pourra entreprendre des opérations intermédiaires : composer,changements de droits...
    # Attention, il faut peut-être ajuster les droits sur /srv/tmp
    # pour que le propriétaire du script puisse y écrire sans droits root.
    TEMP="/srv/tmp/MY_APP"
    
    # Notre dépôt nu
    REPO="/srv/git/MY_APP.git"
    
    # On déploie les fichiers vers le dossier temporaire
    mkdir -p $TEMP
    git --work-tree=$TEMP --git-dir=$REPO checkout -f
    
    # On fait ce qu'on veut dans le dossier temporaire
    cd $TEMP
    chown -R ME:WEBUSER .
    find . -type f | xargs chmod 664
    find . -type d | xargs chmod 775
    find . -type d | xargs chmod +s
    
    # On remplace le dossier servi par http
    cd /
    rm -rf $TARGET
    mv $TEMP $TARGET

    Ne pas oublier de rendre ce script exécutable :

    chmod +x /srv/git/MY_APP.git/hooks/post-receive

Et voilà, y'a plus qu'à se lancer !

Une autre méthodologie consisterait à créer un post-receive hook directement dans votre dépôt origin, via l'interface web de votre fournisseur de service, pointant vers un script situé sur votre serveur.
Une description est faite ici. Un inconvénient, toutefois, pour ceux dont le dépôt se trouve chez Bitbucket : la requête contenant le payload du commit n'est pas sécurisée par un quelconque token.

Article suivant Article précédent