Appuyez sur Entrée pour voir vos résultats ou Echap pour annuler.

GitLab DevOps et déploiement en continu par FTP – Partie 1

Le déploiement en continu d’une application est devenu l’oracle des développeurs. Qu’est-ce qu’il peut y avoir de mieux que de faire un push et voir son code automatiquement déployé dans un environnement de test? Malheureusement, le déploiement en continu est beaucoup plus facile à mettre en place avec des technologies comme Docker et Kubernetes, mais j’avais envi aujourd’hui d’offrir ce genre de fonctionnalité à nos lecteurs qui supportent des applications qui se déploient manuellement par FTP (en PHP par exemple).

Donc aujourd’hui, je vais vous montrer comment on peut faire du déploiement en continu avec GitLab DevOps!

Plan

  • Préparer le dépôt
  • Créer, en node, un utilitaire git pour sortir les différences entre deux commits
  • Créer, en node, un utilitaire pour transférer les fichiers par FTP
  • Créer le pipeline de déploiement dans GitLab

Préparer le dépôt

Le script de déploiement doit faire partie du projet. Je vous suggère de mettre deux dossiers à la racine de votre projet :

  1. deployer – contiendra le script responsable du déploiement
  2. www – contient votre application

GitFunctions

Il existe des méthodes brute force pour déployer. Ce qui se fait habituellement, c’est d’écraser la totalité du site avec le contenu dans git. Par contre, ceci pose un véritable problème si le site pèse plusieurs mégaoctets. Il faut penser que le build va devoir récupérer le code dans sa totalité depuis de dépôt git, puis pousser les fichiers par FTP. Les fichiers doivent donc passer sur le réseau 2 fois, d’où l’utilité de pouvoir faire un diff entre 2 commits. On doit donc comparé le dernier hash qui a été déployé avec le hash du commit de tête de la branche master pour savoir quels fichiers :

  • ont été modifiés
  • ont été créés
  • ont été supprimés

Dans un premier temps, on doit trouver une façon de déterminer quel est le dernier hash de commit qui est sur le serveur. Pour ce faire, simplement créer un fichier deploy.json à la racine du projet qui contient :

Remplacez évidemment le hash par le dernier commit de tête sur votre branche. Lorsque le script aura complété le déploiement, nous irons écraser ce fichier avec le hash du dernier commit qu’on déploie.

Pour communiquer avec le dépôt git, nous utiliserons simple-git. Dans votre nouveau répertoire deployer, exécutez npm init -y puis npm i simple-git. Créons maintenant un nouveau fichier git-functions.js  :

Cette méthode va nous servir à récupérer la liste des commits avec les fichiers modifiés depuis le commit identifié par le hash en paramètre. Maintenant, il faut récupérer le deploy.json qui se trouve sur le serveur qui contient votre application (voir plus haut). Pour ce faire, utilisons request-promise ( npm i request-promise), puis npm i request).

Dans un nouveau fichier deploy.js, notre fichier principal, récupérez le deploy.json depuis le serveur :

Jusqu’ici, rien de bien épeurant. Maintenant, on doit faire un git-log sur le dépôt pour obtenir l’historique de commits, puis filtrer pour ne garder que les commits fait depuis le hash trouvé dans deploy.json. Modifions notre classe GitFunctions pour ajouter simple-git et exécuter un log :

Le point correspond au répertoire courant, donc votre dépôt qui contient le script et le code de votre application. Puis dans la fonction fetchCommitsSinceHash, ajouter :

Si vous exécutez le script, vous devriez voir les derniers commits avec date, hash et auteur dans les logs. Ce qui nous intéresse ici, c’est de retrouver le commit du deploy.json et de ne garder que les commits faits depuis. Profitons-en pour extraire ce code dans une fonction :

Note : j’ai converti les dates en objets Date pour pouvoir les comparer plus facilement.

Puis, modifions la fonction  fetchCommitsSinceHash pour appeler la nouvelle :

Si vous exécutez, vous devriez voir une liste de commits faits après celui du deploy.json. Profitez-en pour extraire ce bout de code dans une méthode! Maintenant, créons la fonction pour récupérer le delta des fichiers modifiés :

Puis pour l’appeler :

Sylvain, pourquoi tu utilises pas un forEach() au lieu d’un vieux for comme ça?

Utiliser await dans une boucle en expression lambda comme forEach() va uniquement faire en sorte que tous les appels vont partir en même temps, mais que l’exécution d’une itération de la boucle va être bloquée par le await. En utilisant un for traditionnel, on s’assure que chaque appel va être terminé avant d’exécuter la prochaine itération.

Si vous exécutez, les logs devraient partir en vrille. Pas de panique. On va décortiquer. Dans la réponse de git-show, on a toujours un ligne par fichier modifié qui débute par diff --git. Donc si on explose la chaîne de caractères sur les retours de chariot puis qu’on ne conserve que les lignes qui commencent par diff --git, on devrait avoir quelque chose de plus clair :

Ce qui donne des entrées comme diff --git a/deployer/git-functions.js b/deployer/git-functions.js

Ici, vous pouvez voir que git-show ajoute un préfixe a ou b au nom de fichier. Dans le cas d’une modification, les deux chemins seront identiques à part le préfixe. Dans le cas d’un renommage de fichier, le premier sera le fichier source et le deuxième sera le fichier de destination. Donc dans tous les cas, on doit considérer le premier chemin comme valide sauf pour le renommage, on utilisera le deuxième.

Maintenant, il faut savoir si le fichier a été modifié, ajouté ou supprimé. Pour ce faire, on peut regarder deux lignes suivant le git-show qui contiendra cette information :

La ligne suivant le diff --git contient ceci lorsqu’un fichier est ajouté ou supprimé. Pour savoir si un fichier a été renommé (déplacé), il faut regarder la ligne d’après, donc 2 après le diff --git :

Sinon, on peut considérer que le fichier en question simplement été modifié. Dans le cas d’un déplacement de fichier, il faudra garder les deux parties du diff --git  (fichiers a et b) afin de supprimer le a et de créer le b .

Je porte votre attention sur les replace() . Je m’assure simplement de retirer le préfixe pour avoir le véritable chemin vers le fichier.

Ce qui devrait retourner :

Ou encore

À partir d’ici, on sait exactement quels fichiers ont été modifiés. Dans le prochain article, je vais reprendre ici. L’objectif va être de convertir cette réponse de GitFunctions vers une suite d’opérations FTP optimisées. Par exemple, si on modifie un fichier dans plusieurs commits, ça ne sert à rien de le recopier plusieurs fois.

Conclusion

Donc aujourd’hui, on a pu explorer ensemble un paquet npm pour interfacer un dépôt git et voir comment on pouvait l’utiliser pour sortir un delta de modifications entre deux hashes sur une branche. La prochaine fois, on va faire le transfert par FTP et connecter le tout à un pipeline GitLab.

Je vous laisse les sources ici.

Si cet article vous a plu, faites-moi plaisir et partagez-le dans vos réseaux!

 

Suivez-nous par courriel!

Saisissez votre adresse courriel pour vous abonner au blog d'Ezo et recevoir une notification de chaque nouvel article par email.