table des matières
  1. Sitographie
  2. Principe de fonctionnement
    1. Projets C et C++
      1. Executor à utiliser.
      2. Sous modules git
      3. Les différents étapes du pipeline
      4. Job de build
      5. Tests unitaires
      6. Couverture du code
      7. Job de documentation
      8. Remarques
    2. Projets Mbed
      1. fichier .gitlab-ci.yml
    3. Projets Laravel
      1. Sitographie
      2. Configuration
      3. Tests
      4. Déploiement
      5. Envoy
      6. Déploiement du site

Ce document décrit la prise en main de la chaîne CI/CD avec Gitlab et les différents exécuteurs proposés

Une chaîne d’intégration et de déploiement continue automatise des actions sur le dépôt git d’un projet.

  • La partie “CI” pour Continious Integration concerne la compilation, les tests ou encore la génération de documentation. Elle va permettre de vérifier que le code poussé sur un dépot répond aux standards défini pour le projet.

  • La partie “CD” pour Continious Delivery concerne le déploiement de l’application ou du site web.

Le schéma ci-dessous résume les différentes étapes qui peuvent être concernées, en fonction du logiciel par la chaîne CI/CD

Chaîne CI/CD

Il existe plusieurs logiciels CI/CD indépendant à Git comme Travis ou Jenkins. Gitlab propose une chaîne CI/CD intégrée à sa solution et c’est cette chaîne que nous allons utiliser. L’avantage est que la chaîne CI/CD, ou pipeline est directement intégrée au projet.

Sitographie

Principe de fonctionnement

Les pipelines sont automatiquement déclenchés quand un fichier .gitlab-ci.yml est présent à la racine du dépôt. Le fichier .gitlab-ci.yml contient une suite d’actions déclenchées automatiquement lors d’un commit. Par exemple, le pipeline ci-après contient 4 actions :

  • Compilation
  • Tests unitaire
  • Couverture du code
  • Génération de la documentation doxygen

Exemple de pipeline

Les pipelines sont déclenchés par des executors disponible sur notre Gitlab. Actuellement, il y a 3 executors disponibles pour vos projets, en fonction des technologies que vous utilisez.

  • Un executor pour les projets C et C++
  • Un executor pour les projets mbed
  • Un executor pour les projets Laravel

Remarque : Si aucun executor n’est disponible pour vos projets (Python, Android…), il est toujours possible d’utiliser des exécutors du DockerHub. Gitlab ira automatiquement chercher les images des containers pour votre pipeline. Il faudra surement ajouter des étapes supplémentaires (consistant à récupérer des logiciels supplémentaires) avant que votre pipeline soit fonctionnel.

Projets C et C++

Un projet modèle est disponible sur ce dépôt. Il contient tous les éléments nécessaires à la mise en place et l’exécution du pipeline décrit ci-après.

Modèle C++

  • Le fichier .gitlab-ci.yml est composé des éléments suivants

Executor à utiliser.

L’image cppimage2 contient l’ensemble des outils nécessaire à la compilation(CMake), aux tests unitaires (Catch2), à la couverture du code (Gcovr) et à la génération de la documentation (Doxygen).

image: cppimage2

Sous modules git

Si votre projet contient des sous modules git, ajouter cette ligne pour les inclure.

variables:
  GIT_SUBMODULE_STRATEGY: recursive

Les différents étapes du pipeline

stages:
  - build
  - test
  - coverage
  - documentation

Job de build

On précise qu’on va exécuter le job:build. Si nécessaire, il est possible d’ajouter des actions avant l’exécution du script (before_script) Ensuite, le script exécute les étapes de compilation, puis génère un exécutable (artifacts) à télécharger dans le dossier build

job:build:
  stage: build
  before_script:
  script:
    - mkdir build && cd build
    - conan install -s build_type=Debug -if conan-dependencies ..
    - cmake -GNinja ..
    - ninja
  artifacts:
    paths:
      - build

Tests unitaires

Une page du site est consacrée aux tests unitaires. Merci de s’y reporter pour le détail de la création des TU et l’importance de ceux-ci.

Les tests unitaires sont réalisés avec le framework Catch2 et sont dans le dossier test du modèle fourni.

L’intérêt est d’avoir une vue immédiate du rapport de test grâce au reporter junit

Rapport de tests

job:test:
  stage: test
  script:
    - cd build/test/bin
    - ./testProjet --reporter junit --out catch_results.xml
  artifacts:
    when: always
    paths:
    - build/test/bin/catch_results.xml
    reports:
      junit: build/test/bin/catch_results.xml

Couverture du code

La couverture du code est un indicateur important. Il permet de s’assurer que la majorité du code de l’application a été compilé par les tests unitaires.

L’artifact généré indique simplement le résumé du taux global de coverage. Si une exploration plus fine est nécessaire, il faut générer également le dossier build pour avoir le rapport complet.

Couverture du code

code coverage:
  stage: coverage
  before_script:
  script:
    - cd build
    - conan install -s build_type=Debug -if conan-dependencies ..
    - cmake -GNinja ..
    - ninja
    - ninja coverage
    - gcovr --xml-pretty --exclude-unreachable-branches --exclude CMakeFiles --print-summary -o coverage.xml --root ${CI_PROJECT_DIR}
  coverage: /^\s*lines:\s*\d+.\d+\%/
  artifacts:
    name: ${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
    expire_in: 2 days
    reports:
      cobertura: build/coverage.xml
    paths:
     - build/coverage

Job de documentation

Le job de documentation va générer automatiquement la documentation doxygen en fonction des balises insérées dans votre code.

Remarque : doxygen s’appuie sur le fichier Doxyfile. Il faut que celui-ci soit présent à la racine de votre projet (et correctement configuré)

job:documentation:
  only:
    - master
    - tags
  stage: documentation
  before_script:
  script:
     - doxygen Doxyfile
     - mv html/ public/
  artifacts:
    paths:
      - public

Remarques

  • Le fichier .gitlab-ci.yml est sur le dépôt.
  • Attention à l’indentation des directives, le fichier est rapidement invalide. (Editez le en ligne pour le corriger)
  • Certaines directives sont à adapter. Par exemple, il peut être intéressant de ne générer la documentation que sur la branche master

Projets Mbed

Un modèle de projet mbed6 est disponible à l’adresse suivante

Le fichier d’intégration continue pour Mbed ne contient que l’étape de compilation. En effet, les tests unitaires s’exécutent sur la carte physique et ne sont donc pas exécutables en ligne.

Attention : mbed-os est déjà installé sur l’executor. Il ne faut donc pas que votre projet contienne de fichier mbed-os.lib pour que le pipeline s’exécute correctement. La meilleure pratique consiste à avoir un répertoire avec mbed-os externe à tout projet sur votre poste et à configurer correctement votre projet pour l’utiliser (Gérer plusieurs projets Mbed)

fichier .gitlab-ci.yml

image: mbedimage

variables:
   GIT_SUBMODULE_STRATEGY: recursive
  
stages:
  - build

job1:
  only:
    - master
    - tags
  stage: build
  script:
  - mbed new .
  - mbed deploy
  - mbed compile --source . --source /opt/mbed/mbed-os/ --profile=debug -t GCC_ARM -m NUCLEO_F746ZG
  artifacts:
    paths:
      - BUILD

Projets Laravel

Le pipeline pour Laravel contient deux étapes, l’une pour les tests unitaires, l’autre pour le déploiement de l’application sur un serveur en production.

Sitographie

Laravel CI/CD

Configuration

L’executor laravelimage contient les outils nécessaires pour le framework Laravel9 (php8 notamment) Il est possible d’utiliser un certain nombre de variables pour accéder à la base de données.

image: laravelimage

services:
  - mysql:5.7

variables:
  MYSQL_DATABASE: laravel
  MYSQL_ROOT_PASSWORD: ""
  DB_HOST: mysql
  DB_USERNAME: root

stages:
  - test
  - deploy

Tests

Les test unitaires sont définis dans le dossier app\tests\Unit de Laravel. Ici, ils sont exécutés avec phpunit

unit_test:
  stage: test
  script:
    - cp .env.example .env
    - composer install
    - php artisan key:generate
 #   - php artisan migrate
    - vendor/bin/phpunit

Déploiement

Le job va déployer le site sur le serveur en production. Il est donc nécessaire de configurer celui-ci au préalable pour la connexion d’un utilisateur au serveur ayant les droits sur le répertoire web de notre serveur.

Les étapes préalables consistent à :

  • Créer un utilisateur deployer sur le serveur
  • Lui donner les droits sur le répertoire /var/wwww
  • Générer les clés publiques et privées SSH.
  • Intégrer les clés au dépôt gitlab

Remarque : Se référer à la documentation officielle pour la configuration du serveur et du dépôt.

Envoy

Dans la solution proposée, on utilise envoy pour cloner le dépôt. Le fichier Envoy.blade.php doit être à la racine de votre projet.

  • Se référer à la documentation officielle pour les explications détaillées sur envoy.
@servers(['web' => 'deployer@x.x.x.x'])

@setup
    $repository = 'https://example.com/USER/laravel.git';
    $releases_dir = '/var/www/app/releases';
    $app_dir = '/var/www/app';
    $release = date('YmdHis');
    $new_release_dir = $releases_dir .'/'. $release;
@endsetup

@story('deploy')
    clone_repository
    run_composer
    update_symlinks
@endstory

@task('clone_repository')
    echo 'Cloning repository'
    [ -d {{ $releases_dir }} ] || mkdir {{ $releases_dir }}
    git clone --depth 1 {{ $repository }} {{ $new_release_dir }}
    setfacl -R -m g:www-data:rwx {{ $new_release_dir }}
    cd {{ $new_release_dir }}
    git reset --hard {{ $commit }}
@endtask

@task('run_composer')
    echo "Starting deployment ({{ $release }})"
    cd {{ $new_release_dir }}
    composer install --prefer-dist --no-scripts -q -o
@endtask

@task('update_symlinks')
    echo "Linking storage directory"
    rm -rf {{ $new_release_dir }}/storage
    ln -nfs {{ $app_dir }}/storage {{ $new_release_dir }}/storage

    echo 'Linking .env file'
    ln -nfs {{ $app_dir }}/.env {{ $new_release_dir }}/.env

    echo 'Linking current release'
    ln -nfs {{ $new_release_dir }} {{ $app_dir }}/current
@endtask

Déploiement du site

Une fois gitlab et Laravel configuré, le job de déploiement va récupérer les clés ssh du projet, se connecter au serveur de production et exécuter le script Envoy.blade.php

Remarque : La directive manual indique qu’il faut exécuter manuellement la tâche pour déployer la nouvelle version du site. Dans un fichier plus élaboré, il peut y avoir un serveur de préproduction avec une mise à jour automatique et un serveur en production avec une mise à jour manuelle.

deploy_production:
  stage: deploy
  script:
    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
    - eval $(ssh-agent -s)
    - ssh-add <(echo "$SSH_PRIVATE_KEY")
    - mkdir -p ~/.ssh
    - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'

    - ~/.composer/vendor/bin/envoy run deploy --commit="$CI_COMMIT_SHA"
  environment:
    name: production
    url: http://x.x.x.x
  when: manual
  only:
    - master