Aller au contenu principal

R2DevOps votre assistant pipeline Gitlab CI/CD

· 12 minutes de lecture
Stéphane ROBERT

logo

R2DevOps est un outil complet qui a pour objectif de vous aider à construire votre pipeline CI/CD en partant de zéro.

Introduction

Cette solution, open source et collaborative, s'adresse surtout aux développeurs qui ne maîtrisent pas encore la construction de pipelines CI/CD sur Gitlab et Github. Ici, on parle bien de pipelines CI/CD, permettant de :

  • de compiler l'application (build),
  • lancer des tests unitaire, d'intégration (test),
  • de construire un package versionné (package),
  • déployer l'application (deploy)
  • de lancer des tests de sécurité et de non-régression (test)
  • de générer la documentation,
  • ...

Cocorico ce produit a été développé par 2 Frenchies répondant au nom de Thomas Boni et Aurélien Coget qui ont monté leur entreprise. Il s'agit de go2scale, basé dans la région de Montpellier, qui propose d'aider les entreprises à optimiser les processus de développement logiciels.

Découverte de R2DevOps

Je connais cette solution depuis quelque temps, mais je n'avais jamais pris le temps de la tester à fond. Ce sera chose faite maintenant.

Les sites à connaitre :

Initialisation de mon projet de test

Je vous propose de tester R2DevOps sur un simple projet de construction d'image Docker. Je vais créer une image contenant l'outil Python lastversion. Cet outil permet de retrouver facilement la dernière version d'une très grande partie des projets ou distributions. Personnellement, je l'installe avec pipx :

pipx install lastversion

Quelques exemples :

lastversion terraform
1.3.1
lastversion ubuntu
22.4
lastversion asdf
0.10.2
lastversion ansible
2.13.4

Voilà je vous propose de baser l'image Docker à partir d'une image Python Slim Debian.

Voici le Dockerfile :

FROM python:3.10-slim-bullseye as builder
WORKDIR /
COPY pyproject.toml ./
RUN apt update &&\
apt install --no-install-recommends -y build-essential libffi-dev libssh-dev python3-dev &&\
pip install --no-cache-dir poetry==1.2.0 setuptools==65.3.0 pip==22.2.2 --upgrade &&\
poetry lock &&\
poetry export -f requirements.txt --output requirements.txt &&\
pip3 wheel -r requirements.txt

FROM python:3.10-slim
WORKDIR /
COPY --from=builder /*.whl /wheels/
RUN apt update &&\
apt install --no-install-recommends -y gettext &&\
pip3 install --no-cache-dir /wheels/*.whl &&\
rm -rf /wheels &&\
apt autoclean &&\
apt clean

J'ai simplifié au possible, mais en gardant le multi-stage pour limiter la taille de l'image. J'ai regroupé mes pratiques pour optimiser la taille des images ici. J'ai retiré la partie, on va dire bonnes pratiques comme l'utilisation de la directive USER qui permet de restreindre les droits des containers. Plus d'infos ici

Vous remarquez que j'utilise poetry pour gérer les dépendances Python. Pourquoi ce choix ? Tout simplement pour voir comment va réagir R2DevOps à sa présence. Mais aussi pour utiliser renovate qui permet de détecter les nouvelles versions et de créer des Pull-Request sur vos projets en les intégrant. Plus d'infos ici. Renovate est une alternative à Dependabot.

Voici son contenu :

[tool.poetry]
name = "lastversion-docker"
version = "0.1.0"
description : ""
authors = ["Stephane Robert <stephane.robert@fr.clara.net>"]

[tool.poetry.dependencies]
python = "^3.10"
lastversion = "2.4.5"

[tool.poetry.dev-dependencies]

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

J'ai ajouté aussi des fichiers .gitignore, .dockerignore et un .gitlab-ci.yml qui lui a été créé par GitLab au moment de la création du dépôt intégré des tests d'analyse statique du code (SAST). D'ailleurs pour voir le contenu de ces fichiers, je vous propose d'y aller. C'est par .

r2devops générateur pipeline

Voilà tout est prêt. J'ai testé la création en locale de mon image ça fonctionne :

docker build . -t lastversion:2.4.5

=> => exporting layers 0.6s
=> => writing image sha256:f47351a09dd6ae25c4d76d3bfd5c5e7b91664b4b7a7e6b8d3d0b29a6cc093243 0.0s
=> => naming to docker.io/library/lastversion:2.4.5

docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
lastversion 2.4.5 f47351a09dd6 47 seconds ago 203MB

On génère le pipeline avec R2DevOps

Il existe deux façons d'utiliser R2DevOps : une manuelle en utilisant le générateur de Pipelines et une autre plus automatisée en utilisant le Hub. Il se charge de créer le fichier de pipelines et d'une branche pour le lancer une première fois.

En utilisant le générateur de pipelines CICD

Pour utiliser le générateur de pipelines, il faut se rendre à cette URL : pipeline.r2devops.io

r2devops générateur pipeline

J'agis comme si j'étais un développeur junior, donc je rentre l'url de mon projet (il faut donc qu'il soit publique !) et je clique sur [Generate a pipeline].

Et voilà le résultat :

# R2Devops.io pipeline generation
#
# List of technologies detected in the project : dockerfile, json, markdown, yaml,

# Default stage list
stages:
- build
- tests
- review
- provision
- release
- deploy
- others

# Include jobs from r2devops.io
include:

# Doc: https://r2devops.io/_/r2devops-bot/docker_build
- remote: https://api.r2devops.io/job/r/r2devops-bot/docker_build/2.0.0.yml



# Doc: https://r2devops.io/_/r2devops-bot/gitleaks
- remote: https://api.r2devops.io/job/r/r2devops-bot/gitleaks/1.1.0.yml



# Doc: https://r2devops.io/_/r2devops-bot/trivy_image
- remote: https://api.r2devops.io/job/r/r2devops-bot/trivy_image/1.1.0.yml


docker_build:
variables:
DOCKER_CONTEXT_PATH: './'
DOCKERFILE_PATH: 'Dockerfile'

gitleaks:
allow_failure: true

trivy_image:
allow_failure: true

Au premier coup d'œil plûtot sympa. On a trois include pointant sur des templates dont :

  • un pour le build
  • un pour détecter d'éventuelles données sensibles qui ne devraient pas s'y trouver.
  • un pour lancer le scan de l'image avec trivy

En plus on a les liens pour retrouver leurs documentations. Un rapide coup d'œil sur la documentation de celui de Trivy, et toutes les variables sont indiquées : comme la version utilisée TRIVY_VERSION fixé par défaut à 0.9.2. Aie elle est loin cette version, elle date de Juillet 2021 ! Mais heureusement on a le lien qui permet de créer une issue sur le dépôt hébergeant ce template.

Pour utiliser ce pipeline, il suffit donc de créer une branche sur son dépôt et d'y déposer à la racine le fichier .gitlab-ci.yml. On commit et push et c'est parti.

Tout s'est bien passé, mais comme le résultat est le même avec le Hub je le détaillerai plutôt dans cette partie.

r2devops générateur pipeline

Mais, où est passé le step de SAST ? Celui qui avait été créé par GitLab. Perdu. D'ailleurs pas de trace ici d'utilisation d'un outil de SAST. Pourquoi ne pas les intégrer puisque fourni par GitLab ? C'est peut-être une fonctionnalité de la version PREMIUM (Hub). D'ailleurs on pourrait aussi pointer l'absence d'un outil de Lint, ici Hadolint qui gère les Dockerfile.

En passant par le hub

Je me rends sur le R2DevOps.io, je clique sur [Try R2DevOps for Free] et on me propose de m'enregistrer avec soit mon compte Github ou soit mon compte Gitlab. Ce que je fais en prenant mon compte Github.

Je demande à connecter mon compte Gitlab pour qu'il pilote les pipelines de mes dépôts. Il me demande de créer un PAT (Personnal Access Token) sur mon compte GitLab, mais je mets quoi comme droits. Ça manque d'explications, pas de lien. Je file sur la documentation et je trouve droits API. Le token est enregistré. Et là je me retrouve avec un écran ou sont listés tous mes dépôts, dont celui que j'ai généré pour tester R2DevOps.

r2devops générateur pipeline

Mon dépôt a bien un point d'exclamation orange indiquant qu'il n'y a déjà un fichier .gitlab-ci.yml mais non pris en charge par R2DevOps. En rouge ceux ne possédant pas du tout de pipeline. Je clique sur les ... puis [Generate My Pipeline] : une fenêtre s'affiche où on me demande de modifier si besoin l'URL, la banche qui servira de source et celle qui recevra celle avec le fichier de pipeline. Pas mal du tout.

r2devops générateur pipeline

Au bout d'un moment un écran apparaît avec le pipeline généré. On retrouve aussi un lien permettant de se rendre sur la page pipeline du projet et un autre sur le fichier de pipeline. Un petit clic et on constate que nous avons bien une branche r2devops avec un pipeline qui a été exécuté avec le status passed. Cela veut dire qu'un des jobs a planté. Pour rappel, j'ai laissé, les options permettant de by-passer les taches trivy et gitleaks en échec.

D'ailleurs je vais modifier celle de trivy pour la rendre obligatoire.

Je n'ai pas réussi à faire les modifications dans l'interface R2Devops, donc je les ai faites sur le dépôt ! Cela est peut-être prévu dans une future version. J'en profite pour prendre la dernière version de trivy et changer le niveau d'erreur à CRITICAL.

trivy_image:
stage: security
variables:
TRIVY_VERSION: "0.32.1"
TRIVY_EXIT_ON_SEVERITY: "CRITICAL"

Bon il n'a pas aimé. Trivy indique que l'option --template n'est pas connue. Je retourne sur la documentation à la recherche de la dernière version supportée, pas de trace de l'information.

Donc, je vais devoir proposer une nouvelle version. Idem, je ne trouve pas les informations nécessaires. Donc, je vais forker le job dans un dépôt personnel et l'utiliser en private le temps de le mettre au point.

Création de Jobs

Je reprends je job trivy, en analysant son contenu, il utilise une installation via un script dans gitlab plutôt qu'une image pointant sur une version pré-installée. Aie, c'est le plus performant. Le script gitlab devrait-il pas simplement gérer les différences aux niveaux des versions non ? Vous allez me dire c'est un projet communautaire, donc apporte ta pierre à l'édifice. Oui, je le ferai.

Je vais simplifier en changeant les options pour corriger --template. Je crée dans le même dépôt que celui du projet un répertoire jobs dans lequel je viens déposer la copie de l'existant. Je modifie juste les lignes de commandes pour fixer les problèmes d'option et le nom du job :

# Job from R2Devops hub --> r2devops.io

stages:
- tests

# Run trivy on any commit
trivy_image2:
stage: tests
...

# Build report
- ./trivy image --format template --template "@contrib/junit.tpl" --cache-dir ${TRIVY_CACHE_DIR} --output ${TRIVY_OUTPUT} ${TRIVY_OPTIONS} $IMAGE
# Fail on severe vulnerabilities
- if [ ! -z ${TRIVY_EXIT_ON_SEVERITY} ]; then
- ./trivy image --exit-code 1 --severity ${TRIVY_EXIT_ON_SEVERITY} --format template --template "@contrib/junit.tpl" --cache-dir ${TRIVY_CACHE_DIR} --output failed.${TRIVY_OUTPUT} ${TRIVY_OPTIONS} $IMAGE
- fi

Je me rends dans le menu jobs de r2devops. Je clique sur [Link your job] et je rentre les informations comme ceci :

  • le bout de l'url de mon Projet : Bob74/test-r2devops
  • le dossier jobs pour le répertoire où se trouve les jobs
  • le nom du job : trivy_image2 c'est pas le nom du fichier yaml mais celui du job.
  • La visibilité : je mets Private car pour le moment c'est un test.

Je valide en cliquant sur [Import my Job] puis [Save Details] sans rien modifier. Si je retourne dans jobs/private je le retrouve bien.

Je relance la génération pour voir quels jobs il va prendre. En espérant qu'il prenne le mien plutôt que l'existant. Perdu !

En plus il accumule les options. Grrr Je le corrige sur l'éditeur de Pipeline qui permet de le valider directement. (Ca devrait corrigé)

Je récupère le lien sur l'interface Jobs et je remplace l'include avec cette url :

    - remote: https://api.r2devops.io/job/r/stephrobert/trivy_image2/latest.yaml?token=r2-xxxxxxxx.yml
...

trivy_image2:
allow_failure: true
variables:
TRIVY_VERSION: "0.32.1"
TRIVY_SEVERITY: "CRITICAL"

r2devops générateur pipeline

Je corrige les options. Je valide. C'est bon, je "commit" sur la branche r2devops. Le pipeline se relance et ça passe cette fois.

Je finis par merger avec la branche main. Le lien du dépot

Conclusion

À la date de l'écriture de ce billet (octobre 2022), je trouve le projet très intéressant et très prometteur, mais j'ai quelques remarques :

  • Pourquoi la documentation n'existe pas en français ? C'est un projet Français non ? J'ai posé la question et ça sera fait prochainement.
  • La documentation est incomplète et on se retrouve à tâtonner et à farfouiller. On excusera, c'est un produit récent. Idem, ils ont entendu ma remarque.
  • Même si cela donne un coup de main, la personne qui n'est pas formé un minimum à Gitlab-CI sera perdu. Ça manque d'un tutoriel plus complet, pas de trace sur youtube.

Je me pose aussi des questions sur le public visé. Je ne veux pas dire que les devs sont "incompétents", mais le fait de générer des pipelines automatiquement sur vos projets ne leur donneront pas le "label" DevOps. Le simple fait d'utiliser des applications sans les maîtriser un tant soit peu, enlève toute viabilité. On le voit juste dans l'exemple ci-dessus. Le fait d'utiliser une version de trivy datant de 2 ans soulève des questions. En effet, dans la démarche Devops on doit aussi faire de l'amélioration continue, y compris sur les pipelines. On doit par exemple chercher à limiter les temps de calculs de ceux-ci. Assurer le support.

Pas de conclusion hâtive la peinture est très fraiche. Si on jette un regard dans la liste des issues, elle semble déjà longue (139 ouvertes et 434 closes) comme le bras. On trouve 343 releases, mais attention chaque job est livré dans une release. Donc cela veut dire que ce projet ne laisse pas indifférent.

J'ai posé un rendez-vous avec les concepteurs où je poserais ces questions. Je reviendrai publier les réponses.

Maj du 10/10/22

J'ai eu un entretien avec Thomas Boni qui a été très à l'écoute de mes remarques :

Par exemple, ils vont regarder à intégrer Renovate pour améliorer la prise en charge rapide de nouvelles versions d'images et d'outils, afin améliorer le support des jobs existants. Pour que mon expérience sur Trivy soit du passé. D'ailleurs le bot vient de me prévenir que la version de Trivy désormais utilisée est la 1.2.0. Cool

Pour la partie sécurité toutes les images utilisées dans les jobs fournis sont régulièrement soumises à des scans pour détecter la moindre vulnérabilité. A noter qu'elles sont màj à chaque sortie d'une nouvelle version de l'image de base. Par contre, les images de la communauté, elles ne subissent aucun contrôle.

Pour le problème de reprise de l'existant ça devrait être corrigé dans une future version.

Pour le positionnement de l'outil, ils se font la même remarque et se focalisent plutôt sur le fait de fournir un système de catalogue de jobs privés à des organisations. Le générateur de pipeline évoluera donc avec la prise en charge des jobs 'privés', via certainement un système de TAGS.

Donc je réitère mon intérêt pour cet outil.