Blog
L'intégration continue

Partager

Nombreux sont ceux qui ont été confrontés à des erreurs en production à cause d’un déploiement sans vérification et/ou d’un oubli, notamment car les tests n’ont pas ou mal été effectués... La plupart de ces erreurs peuvent raisonnablement être évité par l’intégration continue.

Erreur 503

Définition

Développer un projet exige d’intégrer ensemble le travail de plusieurs développeurs. Chaque bout de code fonctionne indépendamment mais la réunion de ces fonctionnalités peut engendrer des comportements inattendus.

Dans ces conditions, certains outils s’avèrent indispensables, comme les logiciels de gestion de versions pour revenir en arrière ou la mise en place de méthodes de travail dites « agiles » afin de confronter les fonctionnalités le plus tôt et le plus souvent possible.

Pour maintenir la cohésion du code, l’intégration continue repose donc sur le contrôle du dépôt, la vérification de non-régression des fonctionnalités, la détection des problèmes d’intégration et finalement l’automatisation de cette suite de tests. On intègre donc toutes les fonctionnalités du produit, en même temps, en continu.

Pourquoi l’utiliser ?

Les outils de l’intégration continue

Que ce soit installer ou mettre à jour les dépendances pour un projet web avec Composer, Bower ou Npm, lancer les tests avec Code Sniffer pour vérifier la norme, Mess Detector pour vérifier la complexité du code, Phpunit pour faire des tests unitaires et vérifier que tout fonctionne comme il faut, cela prend du temps et requiert toutes une suite d'outils installés sur le poste du développeur.

Ensuite il faut se connecter au serveur de pré-production, que ça soit par SSH ou bien par FTP et y copier les fichiers fraîchement testés sans faire l’erreur de copier un fichier de configuration qui pourrait écraser le fichier existant et tout faire planter. Il faut ensuite re-tester dans des conditions proches de la production.

Avec l’intégration continue, vous réunissez toutes ces commandes dans un script pris en charge par votre CI. Cela permet de ne plus avoir à faire toutes les opérations fastidieuses qui étaient nécessaires jusqu’à présent pour tester et déployer un site. Le développeur n'a que son code à tester, l'ensemble des fonctionnalités réunies est testé automatiquement.

Quelques exemples

L’outil le plus utilisé à BigInt pour faire de l’intégration continue est GitLab-CI qui est piloté par GitLab grâce au « gitlab-runner ». Travis-CI, Jenkins sont quant à eux plus souvent utilisés par la communauté Github qui ne propose pas de solution intégrée.

Voici un petit exemple de fichier de configuration (gitlab-ci.yml) pour le déploiement d'un site en PHP :

before_script:
    - php7.1 composer.phar selfupdate
    - php7.1 composer.phar install

stages:
    - test
    - deploy

test:phpcs:
    stage: test
    script:
        - php7.1 composer.phar qa:phpcs

test:phpmd:
    stage: test
    script:
        - php7.1 composer.phar qa:phpmd

test:phpunit:
    stage: test
    script:
        - phpdbg7.1 -qrr vendor/bin/phpunit --coverage-text --colors=never

deploy:api:preprod:
    stage: deploy
    script:
        - "which ssh-agent || (sudo apt-get update -y && sudo apt-get install openssh-client -y)"
        - eval $(ssh-agent -s)
        - ssh-add <(echo "$SSH_DEPLOY_PRIVATE_KEY")
        - rsync --progress --archive ./ deploy@preprod-server:/var/www/api/
        - done
    only:
        - master

deploy:api:prod:
    stage: deploy
    script:
        - "which ssh-agent || (sudo apt-get update -y && sudo apt-get install openssh-client -y)"
        - eval $(ssh-agent -s)
        - ssh-add <(echo "$SSH_DEPLOY_PRIVATE_KEY")
        - rsync --progress --archive ./ deploy@prod-server:/var/www/api/
        - done
    only:
        - production

Ce fichier est en YML, un format parfaitement intégré à Gitlab-CI. Nous allons analyser ce fichier :

L'instruction `before_script` comme son nom l’indique sera exécuté avant chaque job. Ici, nous initialisons différents outils qui serviront par la suite.

Ensuite, la liste des étapes qui devront être effectuées est définie par le bloc d'instructions `stages`

Puis, nous avons la liste des job à proprement parler, le nom n’a pas d’importance ce n’est qu’un repère visuel. Dans chaque job on définit à quel stage celui-ci devra être exécuté, suivi des commandes à exécuter identifiées par le mot-clé « script » et optionnellement la branch git par l'instruction `only`. Si aucune branche n’est spécifiée, le job sera exécuté sur toutes les branches poussées par les développeurs.

Dans cet exemple, nous testons toutes les branches poussées sur le git avec phpcs, phpmd et phpunit. Ensuite, le code est déployé pour les branches « master » ou « production ». Les étapes se déroulent dans l'ordre du fichier et l'ensemble du job s'arrête à la première erreur rencontrée.

Dans un contexte plus large, nous pourrions alerter chaque développeur qui pousse un nouveau commit sur sa branche de développement ou envoyer un mail lorsque le déploiement s'est bien passé. Il est aussi possible de générer un badge de « qualité de service» en calculant le taux de code vérifié ou code coverage.

Conclusion

L’intégration continue permet donc l’amélioration de la qualité du code et donc du produit. Il faut toujours écrire les tests unitaires, d'intégration et d'acceptance mais si l’on couple ceci avec le déploiement continu, c’est un gain de temps non négligeable car il n’est plus nécessaire d’effectuer les tests et le déploiement à la main.

comments powered by Disqus