Partage d'expérience
en intégration continue


Jean-Christophe FABRE / INRA - LISAH
11 juin 2018

Contexte

Approche

Mise en oeuvre et outils

Contexte

OpenFLUID Logo

Plateforme logicielle de modélisation du fonctionnement des paysages


OpenFLUD in a nutshell


Représentation numérique des paysages
sous forme de graphe d'unités spatiales
(géométries, propriétés, relations)

Développement, couplage, capitalisation, partage de modèles spatiaux
(codes de calcul)

Socle collaboratif pour des approches pluri-disciplinaires de la modélisation des paysages

OpenFLUD in a nutshell


Framework avec API, GUI, ligne de commande, ROpenFLUID
Services web pour la capitalisation et partage de modèles

Plus d'infos sur OpenFLUD


http://www.openfluid-project.org

@OpenFLUID

Code source

  • C++ (+Python +R)
  • ~150000 lignes de code (hors code des modèles)
  • ~400 tests unitaires et d'intégration
  • Nombreuses dépendances : Boost, Qt, GDAL, GEOS, RapidJSON
  • Code source géré sous git, hébergé sur GitHub
  • Build, tests, packaging : CMake
  • Développeurs : permanents et CDDs
  • Licence libre open-source


Packagé et disponible pour Linux, MacOS et Windows

Process de développement

Process formalisés
pour écriture du code, tests, commits, demande d'intégration, releases

Approche

Objectifs


Outiller le process de développement de manière à tester et packager automatiquement lors de chaque révision de code

→ Monter en robustesse
→ Limiter les regressions fonctionnelles
→ Faciliter la mise à disposition

→ Créer un environnement commun et de référence pour le test/packaging
→ Sortir du "Yeah, it works on my computer! 🏆" trompeur

Attentes pratiques


Tester le code et packager le produit:
  • A chaque révision du code (commit ou pull-request)
  • Pour plusieurs distributions Linux, MacOS, Windows
  • En moins de 20 minutes
  • Disponibilité maximale
  • Notifications adressées à l'équipe de développement

Limiter l'investissement technique et financier

Solution possible : on premise

Installation et maintenance en propre
d'une infrastructure et d'un service
d'intégration continue


...

Solution possible : on premise


Solution possible : on premise


Avantages
  • Maîtrise complète
  • Choix technologiques
  • Internalisé (sécurité, confidentialité, ...)
  • Performance

Inconvénients
  • Coût
  • Effort d'installation et de maintenance
  • Taux de disponibilité
  • Pas notre métier

Solution possible : services tiers

Utiliser des services disponibles dans le cloud


...

Solution possible : services tiers


Solution possible : services tiers


Avantages
  • Disponibilité
  • Facilité de mise en oeuvre
  • Coûts très faibles, souvent "gratuits" pour des codes open-source

Inconvénients
  • Performance (~20 mins par OS)
  • Peu de maîtrise, pas d'accès direct à l'environnement pour débuggage
  • Utilisation d'un service git en ligne "quasi" obligatoire
  • Opérateur extérieur : Quid du closed-source? Quid de la pérennité?

Solution retenue : hybride

A chaque demande d'integration de code :
services TravisCI et AppVeyor
  • Fonctionnement lié à GitHub
  • Appliqué aux pull requests avant intégration
  • 1 distribution Linux, Windows, MacOS
  • Build + Tests + Packaging

Chaque nuit : utilisation d'une infrastructure Jenkins on premise
  • Appliqué sur la dernière révision du code source de référence
  • Plusieurs distributions Linux, Windows, MacOS
  • Build + Tests + Packaging + Déploiement + Tests de déploiement

Solution retenue : hybride

Solution retenue : hybride

Mise en oeuvre et outils

Services tiers dans le cloud

Services tiers dans le cloud

Travis CI et AppVeyor


Autorisations via compte GitHub

Réglage actif/inactif par dépôt git

Configuration via des fichiers spécifiques dans la racine des codes sources

Configurer Travis CI : .travis.yml


OS : Linux / MacOS

VM ou container (Linux only)
à partir d'images prédéfinies et configurables

Matrice de parallèlisation des VM / containers

Export facultatif d'artifacts en sortie

Configurer Travis CI

https://github.com/OpenFLUID/openfluid/blob/develop/.travis.yml

language: cpp

matrix:
  include:
    - os: linux
      dist: trusty
      sudo: false
      env: OFBUILD_TRAVIS_BUILDTYPE=debug
    - os: linux
      dist: trusty
      sudo: false
      env: OFBUILD_TRAVIS_BUILDTYPE=release
    - os: osx
      osx_image: xcode9.2
      env: OFBUILD_TRAVIS_BUILDTYPE=release

notifications:
  email:
    on_success: always
    on_failure: always

addons:
  apt:
    packages:
    - cmake
    - git
    - gcc
    - g++
    - gfortran
    - libboost-dev
    - libboost-test-dev
    - qt5-default
    - qtbase5-dev
    - qtbase5-dev-tools
    - qttools5-dev
    - qttools5-dev-tools
    - libqt5svg5-dev
    - libgdal1h
    - libgdal1-dev
    - libgeos++-dev
    - p7zip-full
    - gnuplot
    - graphviz

#####################################################

install:
  - |
    if [ "${TRAVIS_OS_NAME}" == "osx" ]
    then
      brew install qt5 rapidjson doxygen
      export PATH=$PATH:$(brew --prefix qt5)/bin
    fi

before_script:
  - echo "SET(OPENFLUID_ENABLE_MARKET 1)" > CMake.in.local.cmake
  - echo "SET(OFBUILD_TESTS_ENABLE_FORTRAN 1)" >> CMake.in.local.cmake
  - echo "SET(OFBUILD_UNITTESTS_RUN_OPTIONS \"--log_level=all\")" >> CMake.in.local.cmake
  - mkdir _build
  - cd _build
  - |
    if [ "${TRAVIS_OS_NAME}" == "linux" ]
    then
      if [ "${OFBUILD_TRAVIS_BUILDTYPE}" == "debug" ]
      then
        cmake .. -DOPENFLUID_ENABLE_HEAVYTESTING=1
      elif [ "${OFBUILD_TRAVIS_BUILDTYPE}" == "release" ]
      then
        cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
      fi
    elif [ "${TRAVIS_OS_NAME}" == "osx" ]
    then
      cmake .. -DCMAKE_PREFIX_PATH=$(brew --prefix qt5)/lib/cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local
    fi

script:
  - |
    if [ "${TRAVIS_OS_NAME}" == "linux" ]
    then
      if [ "${OFBUILD_TRAVIS_BUILDTYPE}" == "debug" ]
      then
        make && ctest --output-on-failure -E GitProxy_TEST # excluding git proxy from testing due to too old git version in trusty
      elif [ "${OFBUILD_TRAVIS_BUILDTYPE}" == "release" ]
      then
        make && cpack
      fi
    elif [ "${TRAVIS_OS_NAME}" == "osx" ]
    then
      make && cmake -P ofpack-osx-brewcask.cmake
    fi
    

Configurer AppVeyor


OS : Windows

VMs à partir d'images prédéfinies et configurables

Import facultatif de données et outils externes

Export facultatif d'artifacts en sortie

Configurer AppVeyor

https://github.com/OpenFLUID/openfluid/blob/develop/.appveyor.yml

version: 'build-{build}'
image: Visual Studio 2015
clone_folder: C:\projects\openfluid
skip_tags: true

install:
  - ps: Start-FileDownload 'http://www.openfluid-project.org/resources/tools/OpenFLUID-buildsupport-win32.zip'
  - cmd: 7z x "OpenFLUID-buildsupport-win32.zip" -o"C:\OpenFLUID-buildsupport\"

environment:
  SUPPORT_DIR : C:\OpenFLUID-buildsupport

before_build:
  - cmd: cd C:\projects\openfluid
  - cmd: mkdir _build-release
  - cmd: cd _build-release
  # Remove entry with sh.exe from PATH to fix error with MinGW Generator for CMake
  - cmd: set PATH=%PATH:C:\Program Files\Git\usr\bin;=%
  # Use MinGW from Qt tools instead of default installation
  - cmd: set PATH=%PATH:C:\MinGW\bin;=%
  - cmd: set PATH=C:\Qt\Tools\mingw491_32\bin;C:\Qt\5.4\mingw491_32\bin;%PATH%
  - cmd: cmake .. -G "MinGW Makefiles" -DCMAKE_PREFIX_PATH=C:\OpenFLUID-buildsupport -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=.

build_script:
  - cmd: cd C:\projects\openfluid\_build-release
  - cmd: mingw32-make -j 2
    

Exécuter Travis CI et AppVeyor

Les services sont exécutés automatiquement à chaque pull request

Exécuter Travis CI et AppVeyor


En fin d'exécution, une notification est ajoutée au pull request,
à l'adresse de l'intégrateur



→ Acceptation ou refus d'intégration du code

Service on premise

Infrastructure du service on premise


Jenkins : outil d'intégration continue, en réaction ou planification
https://jenkins.io

Serveur maître Jenkins +
  • Esclave Docker pour distro linux (Ubuntu, Debian, Fedora)
  • Esclave Windows
  • Esclave MacOS

Configurer le service on premise


Configurer les tâches sur le maître et les affecter à chaque esclave

Installer le client Jenkins sur chacun des esclaves

Environnement et scripts sur les esclaves Docker, MacOS, Windows

Exécution du service on premise

Exécution du process planifié toutes les nuits
Appliqué au code source de référence

Exécution du service on premise


Reporting sur le serveur maître via interface web



Notification des acteurs du projet par mail

Eléments d'analyse

Système d'intégration continue complet

Satisfait nos besoins... actuels

Un certain degré d'adaptabilité

Incertitude vis à vis de la pérennité des services tiers dans le cloud
(épisode GitHub en cours...)
Coût de maintenance limité mais néanmoins présent

Indispensable!


#!/usr/bin/env sh

git commit -m "Merci de votre attention"
git push audience nice