Gitlab propose une fonctionnalité d’intégration continue qui utilise des “Gitlab Runners”.

Il s’agit en fait de process qui vont s’occuper de faire tourner toutes les tâches utiles pour la CI tout en étant détachés de la plateforme Gitlab elle-même.

De cette manière, la charge n’est pas portée par la forge logicielle elle-même et peut même être mise en place sur un serveur dédié (ce qui est recommandé).

Un même serveur peut héberger plusieurs runners, chacun pouvant avoir une tâche particulière (un runner pour les projets Java, un pour les projets Ruby, etc).

Il est intéressant de noter que même si on se cache derrière un firewall, on n’a pas grand chose à configurer vu que c’est le funner qui contacte Gitlab et non l’inverse. (Merci à Guillaume pour ce point que j’avais oublié de mentionner)

Le fonctionnement le plus simple pour un runner est de fonctionner à partir d’une image Docker qu’il va récupérer, déployer, utiliser pour exécuter les commandes définies dans le fichier .gitlab-ci.yml puis détruire.

Par défaut, quand on prend un compte Gitlab.com en version “free”, on a droit à 400 minutes de CI/CD par mois. Soit 6h40.

Dans ce cas, on utilise des runner partagés (shared).

Très utile pour commencer, cette solution a pour moi deux inconvénients majeurs :

  • Suivant comment on travaille, 400 minutes, on peut vite y arriver

  • Il arrive qu’il n’y ait pas de runners disponibles quand on en a besoin. Et dans ce cas, il faut attendre. Pour être tout à fait honnête, je n’ai jamais attendu plus de 15 minutes

Et donc, pour ces raisons (et le plaisir de bidouiller un peu, faut pas se cacher), pourquoi ne pas héberger son propre runner chez soi ?

Vérifier la configuration du projet

Si dans le projet Gitlab on se rend dans Settings > CI/CD > Runners on peut voir qu’aucun runner spécifique n’existe pour le moment et que plusieurs runners partagés sont présents (ainsi que leur disponibilité).

Paramétrage des runners dans le projet

Installation d’un runner en local

Pour héberger un runner il y a plusieurs possibilités : on peut l’installer comme un service sur son OS, dans un conteneur Docker, dans Kubernetes…

Toutes ces méthodes sont détaillées sur le [site officiel](Install GitLab Runner | GitLab).

Etant sous Mint, j’ai choisi d’ajouter le repository officiel Gitlab à a machine avec la commande

curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash

Et ensuite, tout simplement :

sudo apt-get install gitlab-runner

Ensuite, comme je n’ai pas envie que le runner démarre à chaque fois que je lance ma machine, je désactive le service pour pouvoir le lancer à la main

sudo systemctl stop gitlab-runner

sudo systemctl disable gitlab-runner

sudo systemctl start gitlab-runner

De cette manière, je peux facilement le lancer manuellement sans qu’il ne consomme en permanence de la ressource.

Inscription du runner

Pour que le runner fonctionne, il faut maintenant signaler à Gitlab qu’il existe et lui dire qu’il peut l’utiliser.

On lance alors la commande suivante qui va nous poser quelques questions :

➜  cicd-sample git:(update-vaadin-version) ✗ sudo gitlab-runner register
Runtime platform                                    arch=amd64 os=linux pid=8775 revision=bbcb5aba version=15.3.0
Running in system-mode.                            

Enter the GitLab instance URL (for example, https://gitlab.com/):
https://gitlab.com/
Enter the registration token:
xxxxxxxxxxx
Enter a description for the runner:
[benjamin-perso]: benjamin-perso
Enter tags for the runner (comma-separated):
perso,java       
Enter optional maintenance note for the runner:

Registering runner... succeeded                     runner=GR1348941UVHTocJy
Enter an executor: shell, virtualbox, docker+machine, custom, docker, docker-ssh, parallels, ssh, docker-ssh+machine, kubernetes:
docker
Enter the default Docker image (for example, ruby:2.7):
alpine:latest
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

Configuration (with the authentication token) was saved in "/etc/gitlab-runner/config.toml" 

Les deux premières informations sont disponibles sur le page de paramétrage des runners, il suffit de copier coller.

La description est totalement libre.

La liste de tags aura son importance, on le verra par la suite. Elle permet de qualifier les compétences du runner et l’usage qui va en être fait.

On peut voir qu’il existe plusieurs types d’exécuteurs, j’ai choisi Docker car relativement simple à gérer.

Comme mon projet est en Java et que mon runner va servir à plusieurs choses, je prends une image de base : alpine

Paramétrage du runner

Une fois fait, on peut voir que le runner a bien été enregistré.

Et donc, si on retourne dans la page de paramétrage des runners, on peut alors voir notre runner rien qu’à nous !

Présence du runner spécifique dans le paramétrage du projet

Pour être sûr de ne pas utiliser de runner partagé, on peut alors désactiver l’option Enable shared runners for this project

Comme on l’a vu plus haut, quand on a créé le runner, on lui a donné une série de tags.

Cela veut donc dire qu’il ne va faire tourner que les jobs qui portent un de ces tags.

Dans le cas où on ait un job qui ne soit pas taggué et que l’on souhaite qu’il soit lancé par le runner il faut alors éditer sa configuration en cliquant sur le petit crayon et en cochant la case Run untagged jobs

Modification du paramétrage pour autoriser le lancement de jobs non taggués

Utilisation du runner

Une fois le runner en place et un projet avec une CI bien paramétrée modifié, dès le premier push, on pourra alors voir que nos jobs tournent bien sur le runner installé sur la machine.

Les jobs tournent sur le runner local !

Dans le cas où vous avez installé plusieurs runners en fonction du travail à effectuer, il est tout à fait possible de tagger vos jobs pour spécifier à quel endroit chacun doit être exécuté.

Dans le cas de jobs indépendants, celà permet également de les lancer en parallèle.

En terme de ressources, je travaille sur un vieux laptop avec un Intel i7 7ème génération avec 16 Go de RAM.

Au moment de l’exécution des tests Maven (compilation + TU), la conso mémoire est passée de 8 à 9 Go et le CP n’a jamais dépassé les 50% alors que j’avais IntelliJ de lancé ainsi que mon navigateur avec une quinzaine d’onglets et Spotify.

Toute la documentation sur le sujet est très claire sur le site Gitlab

Dans cet article, je n’ai volontairement pas abordé le reste de l’administration des runners (gestion des caches, etc.). Cela viendra plus tard.

Si vous avez des questions ou des remarques, n’hésitez pas à les poser sur Twitter !