ANF Qualité Logicielle
cycle devops

Outils de construction du code final

& d'intégration et de déploiement continus

Cyril L'Orphelin
Préambule

Les pratiques et outils présentés ci-après sont issues de la culture DevOps . Mais c'est quoi le DevOps ?

Le DevOps
  1. l’union des personnes, des processus et des technologies issus du développement (Dev) et opérations (Ops) destinés à fournir continuellement de la valeur aux clients

  2. une culture

  3. une stratégie opérationnelle

Une vision initiale différente
  • Dev: Modifications aux moindres coûts, le plus rapidement possible

  • Ops: Stabilité du système, qualité, sécurité

Le but
  • Améliorer la communication entre les développeurs et l’exploitation afin de réduire le temps de mise sur le marché d’un produit

  • Proposer des bonnes pratiques destinées à répondre au besoin croissant d’industrialisation et de normalisation du système d’information

  • Sécuriser et stabiliser les mises en production

  • Limiter les interventions humaines : sources principales d'erreur

Intégration / livraison / déploiements continus
  • Démarche qualité orientée industrialisation des développements

  • Démarche d'amélioration continue basée sur :

    • la traçabilité des changements et des déploiements
    • la productivité métier
    • l'agilité et la répétabilité
  • Démarche qui doit résoudre les problèmes

    • de détection tardive des bugs
    • de configuration(s) locale(s)
    • d'intégration de code dans une application
    • de disponibilité de version pour le test, la démonstration
Intégration continue


Dans le cadre d’une intégration continue

  • la phase de développement (mise à disposition et test du code) est entièrement automatisée
  • chaque fois que vous poussez du code, les modifications sont validées et fusionnées dans la branche principale
  • le processus d'intégration continue génère des artefacts qui contiennent le code ou les binaires résultants
Intégration continue : les bons ingrédients
  • Utiliser le contrôle de code source

  • Valider tôt, valider souvent

  • Compiler votre solution à chaque commit

  • Automatiser les tests

  • Écouter les retours

  • Développer une culture DevOps

Livraison continue


Dans le cadre d’une livraison continue

  • On automatise la phase de livraison

  • chaque fois qu’un nouvel artefact de build est disponible, l’artefact est automatiquement placé dans l’environnement souhaité et déployé.

Livraison continue : les bons ingrédients
  • Build unique

  • Séparer les préoccupations environnementales

  • Stocker la configuration dans le contrôle de code source (pas forcément au même endroit que le code)

  • Nettoyer vos environnements

  • Maintenir le pipeline

Déploiement continu


Dans le cadre d’un déploiement continu

  • On automatise l’ensemble du processus, de la validation du code à la production

  • L'étape entre les phases de développement et de livraison est automatique

  • Les modifications de code sont donc transmises en direct une fois qu’elles reçoivent la validation et réussissent tous les tests.

Dans les faits, déploiement et livraison continus sont souvent confondus

Déploiement continu : les bons ingrédients
  • Maitriser la livraison continue et l'exploiter

  • Maitriser l'infrastructure

  • Automatiser chaque déploiement

  • Une bonne communication entre Dev et Ops

  • Maitriser les modes de déploiement (Rolling upgrade, Blue-green , canary)

Rolling Upgrade
  • La nouvelle version d’une application remplace progressivement l’ancienne
  • Le déploiement réel se produit sur une période de temps
rolling upgrade
Canary release
  • L'idée : Rendre disponible une nouvelle version du logiciel à un petit sous-ensemble des utilisateurs (10%)

  • Tester en conditions réelles et avoir un retour sur la nouvelle version
  • Plusieurs nouvelles versions d’une fonctionnalité peuvent être testées en parallèle
  • On peut vouloir sélectionner certains "clients" spécifiques pour tester une nouvelle version
  • rolling upgrade
Blue-Green deployment
  • L'idée : Avoir deux environnements de production actifs en même temps (Bleu et Vert), mais un seul est utilisé

  • Déploiement et derniers tests du nouveau logiciel sur l’environnement non utilisé

  • Changement de version active en changeant le routage

    • Changement de version très rapide
    • Retour en arrière facile

Blue-Green deployment : Phase de test
blue green 1
Blue-Green deployment : Phase de test validée
blue green 2
Les outils de ci/cd
  • Un CVS : git / github / gitlab / svn …

  • Un IDE : Eclipse , NetBeans , IDEA ...

  • Des outils de build : Jenkins, GitLab CI, GitHub Actions, teamCity ...

  • Une plateforme d’analyse du code : SonarQube , Code Climate...

jenkins logo
  • Jenkins est un outil d’intégration continue descendant du projet Hudson.

  • Jenkins propose avant tout une gestion de tâche automatisée sur des projets enregistrés sur la plateforme.

  • Jenkins est un serveur Web, multiplateforme, développé en JAVA. Jenkins est construit en suivant un modèle maître/esclave.

  • Son principe est d’exécuter des scripts et d’utiliser le résultat de la commande pour définir le succès ou non de la construction du projet.

  • Muni de greffons (plugins, addons) Jenkins permet aussi de rapporter des métriques intéressantes tels que des graphiques d’évolution des tests unitaires, le code coverage ou encore le respect de normes de code.

Jenkins / Blue Ocean
jenkins logo
Gitlab CI CD
La solution Gitlab CI
Un exemple
GITLAB CI : Vocabulaire

Les pipelines
Les pipelines est le composant de premier niveau de l’intégration, de la livraison et du déploiement continus de GitLab. Les pipelines gèrent des étapes qui contiennent des tâches qui sont exécutés sur des runners.

Les étapes (stages)
Les étapes sont simplement une division logique entre des ensembles de tâches. Toutes les tâches d’une même étape sont exécutées en parallèle (s’il y a suffisamment de runners) et l’étape suivante ne commence que lorsque toutes les tâches de l’étape précédente sont terminées sans erreurs. Il suffit que l’une des tâches échoue pour que l’ensemble du pipeline échoue à part quelques cas particuliers.

Les tâches
Une tâche est un ensemble d’instructions qu’un runner doit exécuter et peut produire un artefact.

Les artefacts
Un artefact peut contenir des fichiers et/ou dossiers qui vont être stockés au sein des pipelines pour être utilisé par d’autres tâches.

pipeline gitlab
Le manifeste
  • Il faut déclarer un manifeste .gitlab-ci.yml à la racine du projet

  • Dans ce manifeste vous allez pouvoir définir des stages, et des jobs

  • Basé sur une syntaxe yaml

                stages :
    - lint
    - test

image: "python:3.7"

job_lint :
    stage : lint
    script :
      - pip install pylint
      - cd src
      - pylint MyClass

job_test:
    stage : test
    script :
      - cd src
      - python -m unittest discover
                
                
Etape 1 : Définissez les étapes du pipeline
  • Dans un premier temps, je définis les étapes de mon pipeline avec le mot clé stages.

  • Ce mot clé permet de définir l'ordre des étapes.

  • Ici, la première étape va être le lint, et ensuite les test

                    stages :
    - lint
    - test

image: "python:3.7"

job_lint :
    stage : lint
    script :
      - pip install pylint
      - cd src
      - pylint MyClass

job_test :
    stage : test
    script :
      - cd src
      - python -m unittest discover
                
                
Etape 2 : Définissez les jobs à effectuer
  • image : l'image Docker qui va être lancée par GitLab afin d'exécuter les lignes de script que nous avons définies

  • stage : le nom de l'étape qui va apparaître dans notre pipeline d'intégration continue. Cela correspond aussi au stage auquel sera exécuté le job

  • script : ce sont les lignes de script à lancer afin d'exécuter l'étape. L'installation et l'exécution de pylint pour la partie lint et dans la partie test, nous lançons les tests unitaires. Si un seul de ces tests échoue, le pipeline s'arrête.

                    stages :
    - lint
    - test

image: "python:3.7"

job_lint :
    stage : lint
    script :
      - pip install pylint
      - cd src
      - pylint MyClass

job_test :
    stage : test
    script :
      - cd src
      - python -m unittest discover
                
                
Usage des variables dans le manifeste
  • Variables customisées déclarées dans Gitlab dans la partie CI/CD: $DB_URL, $passwords ...

  • Variables d'environnement liées aux projets, liées au repository, à l'exécution de la CI/CD : $CI_PROJECT_ID, $GITLAB_USER_NAME,$CI_JOB_STAGE ...

stage: test
  script:
    - echo "$CI_JOB_STAGE"  # calls a predefined variable
    - echo "$TEST"          # calls a custom variable of type `env_var`
    - echo "$VAR_FILE"      # calls a custom variable of type `file` that contains the path to the temp file
    - cat "$VAR_FILE"       # the temp file itself contains the variable value
OUTPUT$ echo "$CI_JOB_STAGE"
test
$ echo "$TEST"
ceci est une variable ci/cd de test
$ echo "$VAR_FILE"
/builds/cylo/template-tp.tmp/VAR_FILE
$ cat "$VAR_FILE"
Ceci est un fichier qui doit contenir une variable

Cleaning up file based variables
Job succeeded 
Gitlab-CI : Restreindre un environnement
  • A l'aide des mots clés only , except , et environnement, vous pouvez créer des règles de déploiement différentes suivantes
  • Ainsi on veut déployer sur l'environnement : review\$CI_ENVIRONMENT_SLUG toutes les branches à l’exception de la banche master :
  • deploy_review :
      stage : deploy
      script :
        - echo "Deploy a review app on $CI_ENVIRONMENT_SLUG"
      environment :
        name: review/$CI_COMMIT_REF_NAME
        url: https://$CI_ENVIRONMENT_SLUG.example.com
      only :
        - branches
      except :
        - master
  • Si on ne veut déployer en production que la branche master
  • deploy_prod:
      stage: deploy
      script:
        - echo "Deploy on prod"
      environment:
        name: production
        url: https://www.example.com
      only:
        - master
      when: manual
  • when: manual permet de ne pas déclencher automatiquement le déploiement en production, une intervention manuelle est nécessaire
Les Gitlab Pages et la CI
    Avec les Gitlab Pages, vous pouvez publier des sites statiques directement à partir d'un repository Gitlab
  • il suffit de publier du contenu html (généré automatiquement ou pas) dans le répertoire public

  • il faut ajouter un job spécifique intitulé pages

  • et il faut configurer les pages dans l'onglet Pages du menu Parameters

  •  Exemple avec le générateur de site Hugo
                image: monachus/hugo
    
    pages :
      script :
        - hugo
      artifacts :
        paths :
          - public
      only:
        - master
            
Le déploiement continu : un pas plus loin
ci cd with k8's
Le déploiement continu : un pas plus loin
Exemple simplifié du déploiement de la documentation du CCIN2P3stages :
  - build
  - test
  - docker
  - wok

default :
  image : docker:latest

sphinx :
  stage : build
  image : gitlab-registry.in2p3.fr/documentation/centre-de-calcul/cc-in2p3-docs-engine:master
  script :
    - './ci/doc_build.sh'
  artifacts :
    name: "CC-IN2P3"
    paths :
      - /builds/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/ci/htmloutput

preview_master :
  stage : test
  image : gitlab-registry.in2p3.fr/documentation/centre-de-calcul/cc-in2p3-docs-engine:master
  script:
    - './ci/doc_test_master.sh'
  needs:
    - job : sphinx
      artifacts : true

docker:
  stage: docker
  services :
    - docker : dind
  script :
    - docker login -u "$OPENSHIFT_NGINX_REGISTRY_USER" -p "$OPENSHIFT_NGINX_REGISTRY_PWD" $CI_REGISTRY
    - docker build --pull -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" ./ci/
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
    - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA"
  needs :
    - job : sphinx
      artifacts : true

wok :
  image : docker.io/appuio/oc:v3.11
  stage : wok
  script :
    - 'oc login $WOK_URL --insecure-skip-tls-verify --token $WOK_TOKEN'
    - 'oc project $WOK_PROJECT'
    - 'oc patch deployment $DEPLOYMENT_NAME -p "{\"spec\": {\"template\": {\"spec\": {\"containers\": [{\"name\": \"$CONTAINER_NAME\", \"image\":\"$CI_REGISTRY_IMAGE:$CI_COMMIT_TAG\"}]}}}}"'
 
Documentation de la CI/CD Gitlab


Les mots clés de Gitlab CI


Des exemples de manifests


La liste des variables prédéfinies
DEMO