Comment déployer sur un serveur distant en une commande GIT, pas à pas

stadja@LTN
5 min readMay 23, 2018

--

En tant que développeur indépendant, je travaille sur plusieurs projets à la fois. Plusieurs projets sur plusieurs serveurs… et parfois je fais plusieurs mises en prod par jour.

Bien sûr, comme beaucoup de monde, ça fait longtemps que je ne fais plus jamais de mise en prod en déposant les fichiers sur un ftp (yuk !). J’utilise GIT pour gérer tout ça.

Au début, je développais sur mon environnement de dev. Je faisais un push sur une branche. Puis je me connectais en ssh sur le serveur distant et faisait un pull de cette même branche. J’ai fait ça pendant quelque temps et puis ça ma saoulé. J’avais déjà entendu parlé des hooks de GIT, mais j’avais l’impression qu’il fallait configurer de façon très compliqué plein de choses soit sur framagit, sur github ou sur gitlab… bref, relou.

Depuis 3 ans maintenant, grâce à ce super tutoriel je ne m’embête plus avec tout ça. Depuis mon serveur de dev je fais un tout simple

$ git push DISTANT-SERVER BRANCH-TO-BE-PUSHEDDISTANT-SERVER est le nom du serveur distant, genre “preprod” ou “prod” 
BRANCH-TO-BE-PUSHED est le nom de la branche que je veux déployer, genre “develop” ou “master”

ET BIM, le tout est déployé.

Alors je vais faire une simple adaptation pas à pas, en Français et le plus simple possible, du tutoriel pour expliquer comment faire ça.

1. Avoir un accès SSH sur le serveur distant

Bon, le premier pas important est d’avoir un accès ssh sur le serveur distant à l’aide d’une clé privée et d’une clé publique depuis votre environnement de dev. Ça tombe bien, j’ai écrit un tutoriel simple sur comment on fait ça: ici, ouf !

2. Avoir un dépot GIT existant

Bon bein là vous pouvez faire tout ce que vous voulez comme répot GIT. Moi j’utilise framagit. Mais ça peut être n’importe quoi. Et d’ailleurs, pas besoin que ça soit un dépot avec un origin exterieur… ça peut très bien être un dépot local. L’important c’est que dans votre dossier de travail vous ayez bien initialisé git et crée la branche que vous voulez déployer sur votre serveur. Par exemple une branche MASTER ou un truc du genre.
Le prochain tutoriel sera sans doute un petit tutoriel sur Git-flow, ça ne fera pas de mal !

3. Créer votre dossier à déployer sur votre serveur distant

$ ssh DISTANT-USER@SERVER_HOST
$ mkdir DEPLOY-FOLDER

DISTANT-USER: c’est l’utilisateur qui se connecte au serveur distant
SERVER_HOST : c’est votre hôte de connexion ou l’ip de votre serveur distant
DEPLOY-FOLDER: c’est le dossier de déploiement (par exemple /var/www)

4. Création du dépot de déploiement

On va créer un dépot “nu” (bare repository, quelqu’un a une bonne traduction ?) qui ne contiendra pas les données, mais juste les infos nécessaires aux déploiements.

Tout d’abord on va crée un dossier contenant ce dépot sur votre serveur distant

$ ssh DISTANT-USER@SERVER_HOST
$ mkdir BARE-REPOSITORY-FOLDER

BARE-REPOSITORY-FOLDER: c’est le dossier du dépot de déploiement (par exemple /home/DISTANT-USER/deploy) => l’important c’est que vous y ayez accès par ssh

Ensuite, on va crée ce dépot

$ cd BARE-REPOSITORY-FOLDER
$ git init --bare PROJECT-NAME.git

PROJECT-NAME: bein… le nom du projet (genre “project”)

Bravo, c’est las partie la plus importante et c’est fait.

5. Mettre en place un hook post-receive

Bon, alors là c’est le gras du machin.
On va mettre en place un hook (une accroche ?) post-receive (bein qui va se déclancher après la réception). En gros, on va executer un script bash une fois que le déplot de déploiement va recevoir un push. BIM.

Donc tout d’abord on va créer le hook en question… moi j’utilise `nano`, mais vous pouvez utiliser ce que vous voulez de `vi` à `gedit` (brrrr…)

$ ssh DISTANT-USER@SERVER_HOST
$ cd BARE-REPOSITORY-FOLDER/PROJECT-NAME.git/hooks
$ nano post-receive

nano: j’utilise nano, mais vous pouvez utiliser ce que vous voulez hein... de vi à gedit (brrrr…)

Et maintenant le script à mettre dedans

#!/bin/bash
TARGET="DEPLOY-FOLDER"
GIT_DIR="BARE-REPOSITORY-FOLDER/PROJECT-NAME.git"
BRANCH1="BRANCH-TO-DEPLOY"
while read oldrev newrev ref
do
if [[ $ref = refs/heads/$BRANCH1 ]];
then
echo "Ref $ref received. Deploying ${BRANCH1} branch to preprod..."
git --work-tree=$TARGET --git-dir=$GIT_DIR checkout $BRANCH1 -f
chown www-data:www-data -R $TARGET
else
echo "Ref $ref received. Doing nothing: only the ${BRANCH1} branch may be deployed on this server."
fi
done
A remplacer:
DEPLOY-FOLDER: dossier de déploiement (ex: /var/www)
BARE-REPOSITORY-FOLDER: dossier du dépot nu (ex: /home/deploy)
PROJECT-NAME: nom du projet (ex: project)
BRANCH-TO-DEPLOY: la branch de déploiement (en prod par exemple: master)

Donc ce script va regarder quelle branche est envoyé sur le dépot. Si elle correspond à BRANCH-TO-DEPLOY elle va déployer le code dans le dossier DEPLOY-FOLDER.

Il ne reste plus qu’à…

6. Ajouter une dépot externe sur la machine de dev

Donc on va maintenant faire ce qu’il faut pour que l’environnement de dev puisse pousser la branche sur le dépot de déploiement

Sur votre environnement de dev, vous faites:

$ cd WORKING-DIRECTORY
$ git remote add REMOTE-SERVER DISTANT-USER@SERVER_HOST:BARE-REPOSITORY-FOLDER/PROJECT-NAME.git

WORKING-DIRECTORY: le dossier dans lequel vous développez et avez un dépot GIT en cours
REMOTE-SERVER: le serveur distant, par exemple “production” ou “preprod”

7. PREMIERE TENTATIVE DE DEPLOIEMENT

Attention, c’est parti… on sert les dents…

$ git push REMOTE-SERVER BRANCH-TO-DEPLOY

BIM !

Et voilà. Un premier déploiement sans bouger les fesses de son environnement de dev... Parfait :)

8. Des petits trucs en plus

Alors vous pouvez modifier le script du post-receive pour qu’il accepte plusieurs branches par exemple (moi en preprod j’aime qu’il accepte “develop” ET “master”). De plus vous pouvez ajouter des petites commandes de gestion de droit (un chown général pour être sûr que les fichiers appartiennent bien à www-data dans mon cas… ou des trucs du genre).

Voici mon script un peu tweaké

#!/bin/bash
declare -A branches=(
[develop]=1 [master]=1
)
TARGET="/home/prod/www"
GIT_DIR="/home/prod/deploy"
while read oldrev newrev ref
do
BRANCH=${ref/"refs/heads/"/""}
if [[ -n "${branches[$BRANCH]}" ]];
then
echo "Ref $ref received. Deploying ${BRANCH1} branch to preprod..."
sudo chown debian:www-data -R $TARGET
git --work-tree=$TARGET --git-dir=$GIT_DIR checkout $BRANCH -f
cd $TARGET
sudo chmod 777 -R /home/vdlv/www/translate/langcache/
composer install
sudo chown www-data:www-data -R $TARGET
else
echo "Ref $ref received. Doing nothing: you can't deploy ${BRANCH} branch on this server."
fi
done

Pour finir

Bein c’est tout… mais c’est déjà beaucoup. Moi ça m’a changé la vie ce système… depuis je l’utilise partout histoire d’avancer hyper vite sur mes projets et sans avoir besoin de me souvenir de 1000 accès ssh. Bref, c’est cool et ça fait gagner énormement de temps.

Comme la dernière fois, si vous avez des questions ou si y’a des choses qui marchent pas pour vous ou des choses à redire: commentez on verra ensemble pourquoi :)

--

--

stadja@LTN

https://ltn.agency | J’écris pour Le Tarsier Numérique tous les petits défis techniques que nous rencontrons et dont nous voulons vous parler.