Automatiser sa production avec GitLab – partie 2

Automatiser la production avec Gitlab

Automatiser sa production

Découvrez dans cet article comment automatiser tout le processus de déploiement et de contrôle qualité d'un projet, permettant ainsi à la fois d'améliorer la qualité du code et de gagner du temps.

Préambule

Avant de commencer cet article, je tiens d’abord à nuancer mes propos. En effet, bien que le titre soit « L’architecture parfaite », je ne vais pas vous présenter la solution parfaite, capable de résoudre tous vos problèmes ni même de faire votre café.
Je vais plutôt vous présenter l’architecture que nous utilisons en interne pour notre système d’intégration continue, permettant de transformer chaque « commit » en une nouvelle installation propre et visible pour le client.
Cela permet ainsi de surveiller l’évolution des projets en temps réel, et d’échanger avec les clients sur telle ou telle fonctionnalité dès qu’elle est visible plutôt que d’attendre la prochaine release qui ne viendra que dans 3 mois. Ce n’est peut-être pas si loin de la perfection, non ?

Comme il y a beaucoup à dire sur ce sujet, il a été divisé en 3 parties. 

  1. Tout d’abord la première que vous pouvez retrouver ici, décrit tout ce qui se passe à partir du moment où nous écrivons notre code jusqu’au moment où il est réceptionné et stocké sur notre système.
  2. La seconde partie, que vous avez sous les yeux, se concentre presque exclusivement sur la puissance de GitLab-CI et des fichiers « .gitlab-ci.yml ». C’est là que l’on orchestre le tour de magie.
  3. Enfin la dernière partie concernera le déploiement, les tests et la mise en ligne.

Enfin, cet article a été rédigé pour être compréhensible par tous et non uniquement par des développeurs. C’est pour cela que j’ai volontairement pris des raccourcis ou passé certaines informations sous silence.
Enfin, pour les développeurs qui souhaiteraient comprendre mieux le sujet, vous pouvez retrouver un diagramme de ce workflow, réalisé pour l’occasion.

Maintenant que les présentations sont faites, continuons !


Chapitre 2 : GitLab-CI

Dans le chapitre précédent, nous avons créé un commit contenant du code et les tests qui vont avec, et l’avons envoyé sur le serveur GitLab. A présent nous allons voir comment automatiser des tâches et orchestrer la magie qui se cache dans cette architecture.

En plus du code et des tests, il y a un petit fichier à ajouter dans le projet. Il s’agit d’un fichier nommé « .gitlab-ci.yml » (le point avant le nom du fichier est important). Ce fichier ne sert ni à faire fonctionner le site en cours de développement, ni à tester que le système fonctionne… Mais alors à quoi sert-il ?

Ce fichier contient toute une liste d’actions que le serveur doit effectuer en fonction de telle ou telle condition, et c’est là, précisément, que nous allons pouvoir automatiser notre système afin que chaque « commit » soit automatiquement vérifié, tant en termes de fonctionnement qu’en termes de qualité, puis déployé sur un serveur afin que les clients puissent disposer d’une version de leur site à jour.

Commençons donc !

Dossiers

Tout d’abord, il faut bien comprendre le concept qui se cache derrière ces « tâches automatisées ». En vérité, ce n’est pas le serveur GitLab qui va les effectuer. Il va les déléguer à un serveur « worker », un serveur dont le seul rôle est d’exécuter des tâches envoyées par le serveur GitLab.

Ainsi donc notre workflow ressemblera à :

  1. Un développeur envoie un commit au serveur GitLab
  2. Le serveur GitLab regarde s’il y a un fichier « .gitlab-ci.yml » embarqué dans le projet
  3. Le serveur GitLab contacte le serveur worker et lui envoi les instructions présentes dans le fichier « .gitlab-ci.yml »

Ensuite, il faut avoir en tête la hiérarchie des dossiers que nous utilisons pour nos projets. Elle se présente de la manière suivante :

/var
  /www
    /releases
      /<identifiant_unique_de_notre_commit>
      /<identifiant_unique_d’un_ancien_commit>
      /<identifiant_unique_d’encore_un_autre_commit>
    /shared
      /fichiers_communs_utilisés_par_toutes_les_installations
    /current
  • Le dossier « releases » contient toutes les installations, chacune disposant d’un identifiant unique généré automatiquement.
  • Le dossier « shared » contient tous les fichiers et dossiers communs aux installations, par exemple le fichier de configuration possédant les informations à utiliser pour connecter le site à la base de données. Ces fichiers sont copiés depuis le dossier « shared » et collés au bon endroit à chaque nouvelle installation.
  • Le fichier « current » est un peu spécial étant donné qu’il s’agit d’un raccourci pointant sur l’installation visible pour les clients. Ainsi nous pouvons installer le site autant de fois que nécessaire pour avoir une version stable et correcte, avec tous les tests au vert, et sans jamais que cela impacte le client. Puis lorsque tout est bon, il nous suffit simplement changer la cible du raccourci vers la dernière version que l’on vient d’installer.

A présent que le workflow est clair, nous pouvons commencer à rédiger notre fichier de configuration.

Configuration

Malheureusement, pour des raisons de confidentialité, je ne peux présenter le fichier que nous utilisons, et puis ce ne serait pas très intéressant de décortiquer une à une les 200 lignes d’actions automatisées, d’autant plus qu’elles varient en fonction des projets. Je vais plutôt vous présenter une version basique de ce fichier, qu’il suffira de remplir en fonction des besoins.

stages:
  - build
  - test
  - deploy

install:
  stage: build
  script:
    # Create required structure if missing
    - mkdir -p "/var/www/shared"
    - mkdir -p "/var/www/releases"
    - mkdir -p "/var/www/releases/$CI_COMMIT_SHA"

    # Clone git branch, force reset to the current commit and remove git files
    - cd "/var/www/releases/$CI_COMMIT_SHA"
    - git clone -b dev <mon_projet_git> .
    - git reset --hard $CI_COMMIT_SHA
    - rm -rf .git*
    - cp "/var/www/shared/config.yml" "/var/www/releases/$CI_COMMIT_SHA/config.yml"

test:
  stage: test
  script:
    # Run phpunit
    - cd "/var/www/releases/$CI_COMMIT_SHA"
    - phpunit -c . --coverage-text --colors=never

    # SonarQube
    - cd "/var/www/releases/$CI_COMMIT_SHA"
    - echo "sonar.projectKey=$CI_PROJECT_NAME" > ./sonar-project.properties
    - echo "sonar.projectName=$CI_PROJECT_NAME" >> ./sonar-project.properties
    - echo "sonar.projectVersion=$CI_BUILD_ID" >> ./sonar-project.properties
    - echo "sonar.php.tests.reportPath=test-result/junit.xml" >> ./sonar-project.properties
    - echo "sonar.php.coverage.reportPaths=test-result/coverage.xml" >> ./sonar-project.properties
    - /usr/sonar-runner/bin/sonar-scanner

deploy:
  stage: deploy
  only:
    - master
  script:
    # Update symlink
    - cd "/var/www"
    - rm -f current
    - ln -s "./releases/$CI_COMMIT_SHA" ./current

    # Remove old releases (keep 5 last releases)
    - cd "/var/www/releases/"
    - "directories=$(ls -t -d * | tail -n +6)"
    - 'if [[ $directories ]]; then echo "removing old releases :"; echo ${directories}; sudo rm -rf $directories; fi'
    - "unset directories"

Bien, à présent que j’ai perdu la moitié des lecteurs avec ce code, je vais essayer de les récupérer en reprenant point par point ce fichier. Vous verrez, avec les explications, c’est très facile à comprendre.

Déclaration

Tout d’abord, nous avons tout en haut du fichier la déclaration des différentes étapes que ce fichier traite. Cela permet à GitLab de s’organiser en fonction de ce qu’on va lui demander par la suite. Dans notre cas nous avons donc les étapes suivantes :

  1. « build » qui aura pour rôle d’installer le site et de le rendre fonctionnel.
  2. « test » qui vérifiera que le site fonctionne parfaitement, après avoir été installé.
  3. « deploy » qui se chargera de remplacer l’ancienne version « visible » du site par la nouvelle que l’on vient d’installer et de tester.

Nous pouvons donc traduire ces étapes de la manière suivante :

  1. Installer le site dans un dossier, quelque part, sans pour autant le rendre disponible aux clients.
  2. Si l’installation à réussi, alors on vérifie que rien n’est cassé et que le code est toujours de qualité.
  3. Si tous les voyants sont au vert, alors on rend « visible » cette nouvelle installation à la place de l’ancienne à laquelle les clients avaient accès.

Installation

Le 2ème bloc de code, nommé « install », qui aurait pu être nommé de n’importe quelle manière, s’occupe de la première étape de notre processus. Exécuté à l’étape (ou « stage » en anglais) « build », il crée les dossiers nécessaires s’ils n’existent pas déjà, télécharge les fichiers de code du site internet et les place dans le dossier adéquats.

C’est aussi ici que viendraient toutes les actions supplémentaires propres à la technologie sur laquelle est basé le site. Par exemple installer les vendors via composer, créer une nouvelle base de données, changer les permissions des fichiers, etc.

Tests

Le 3ème bloc de code, nommé « test », s’assure que tout fonctionne correctement. C’est là qu’entrent en scène les tests unitaires et fonctionnels expliqués à la fin du chapitre précédent. Le serveur worker va donc exécuter ces tests et vérifier une à une toutes les fonctionnalités couvertes par ces tests. Ainsi, plus nous avons de tests, plus il y a de fonctionnalités couvertes et donc plus le site est protégé de régression potentielle qui pourrait survenir après des mois ou des années de développement.

Si tous les tests sont corrects, alors nous passons au contrôle qualité.
Chez WAX Interactive, nous utilisons SonarQube, qui est une application serveur dont le seul rôle est de prendre du code en entrée, contrôler que ce dernier respecte les normes et conventions de codage, et alerte les développeurs si quelque chose n’est pas correct.

Déploiement

Enfin, le 4ème bloc de code, nommé « deploy », n’est exécuté que lorsque le commit reçu concerne la branche nommée « master » (qui est notre branche principale) et que tous les tests sont au vert. Elle a pour rôle de remplacer la version visible du site par cette nouvelle version que nous venons d’installer et de tester, puis d’effacer les installations trop anciennes. Personnellement, je conserve les 5 dernières versions et supprime toutes les autres. Cela me permet de revenir en arrière si besoin sans pour autant saturer le serveur avec des centaines de versions d’un même site.

Au final, lorsque l’on met tout ça bout à bout, on se retrouve avec une page « pipelines » sur notre GitLab ressemblant à ceci :

Liste des pipelines

On peut voir entre 2 et 3 ronds verts pour chaque déploiement. Le premier concerne l’installation du site sur le serveur. Le second les tests de non-régression, et le dernier concerne la mise à disposition du site aux clients.

Dans ce chapitre, nous avons vu comment récupérer un commit, installer une nouvelle version d’un site, tester chacune de ses fonctionnalités, contrôlé que le code est propre et respecte de manière rigoureuse les conventions de codage, et finalement nous avons rendu cette nouvelle version du site disponible aux clients.

Il ne reste plus qu’à décrire de manière plus avancée le comportement des tests ainsi que du contrôle qualité, mais cela se fera dans la 3ème partie de cet article.

Michael Barbey
Publié le par
Michael Barbey
0 Commentaire

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *