Aller au contenu

Mise à jour des collections Ansible avec Renovate

logo devops

Dans la démarche DevOps, on parle bien d’automatisation pour éliminer les tâches chronophages et sans valeurs ajoutées pour pouvoir se concentrer sur celles qui donnent de la valeur à notre produit.

C’est dans cette optique que j’ai mis en place l’automatisation des tests de mise à jour des rôles et des dépendances de type python (ansible, ansible-lint, molecule, …) dans mes collections Ansible. Pourquoi j’utilise des collections Ansible ? Tout simplement pour rationaliser le code (éviter la répétition de code), mais aussi pour gérer efficacement les versions de toutes mes dépendances. J’utilise de multiples collections en les limitant à de simples objectifs :

  • Faire la configuration de base des serveurs qui viennent d’être provisionné que ce soit avec Packer ou appliqué directement sur les serveurs.
  • Faire l’installation d’un composant : nginx, varnish, apache2, java, python…
  • Monter un projet en utilisant au maximum les collections plutôt que des rôles

Ces collections utilisent toutes des rôles réalisant des tâches assez basiques et qui sont correctement versionnés. Je déconseille fortement d’encapsuler des rôles dans d’autres rôles et puis dans d’autres… A moins d’adorer passer des heures à chercher la source de l’erreur qui vous tombe dessus.

Structure des Groupes dans Gitlab

Je suis hyper maniaque et je passe mon temps à ranger mes affaires. Et c’est vrai aussi sous Gitlab. J’ai créé une arborescence Ansible me permettant de retrouver rapidement un rôle, une collection, un projet contenant un inventaire et quelques playbooks …

ansible
├── collections
│ └── base
├── images-docker
│ └── molecule-collections
├── projets
│ ├── projet1-preprod
│ └── projet1-prod
└── roles
├── bootstrap
└── motd

J’utilise la même arborescence sur mon pc, la seule différence se fait au niveau des collections ou le dossier se nomme ansible_collections et contenant un sous-dossier du nom de votre namespace. Cela afin que les commandes ansible-galaxy fonctionnent. Je vous renvoie à mon explication sur les collections Ansible

ansible
├── ansible_collections
│ └── stephrobert
│ └── base

Écriture de notre collection Ansible

Pour mon exemple, je vais créer une collection ansible permettant de configurer un serveur avec tout ce qu’il faut.

Création de la structure de la collection

Créons notre collection base qui doit se trouver dans le répertoire ansible_collections/<namespace>:

Terminal window
mkdir -p ansible/ansible_collections
cd ansible/ansible_collections
ansible-galaxy collection init stephrobert.base
cd stephrobert/base
ls
total 20K
drwxrwxr-x 2 vagrant vagrant 4,0K nov. 5 14:36 docs
-rw-rw-r-- 1 vagrant vagrant 2,6K nov. 5 14:36 galaxy.yml
drwxrwxr-x 2 vagrant vagrant 4,0K nov. 5 14:36 plugins
-rw-rw-r-- 1 vagrant vagrant 84 nov. 5 14:36 README.md
drwxrwxr-x 2 vagrant vagrant 4,0K nov. 5 14:36 roles

Maintenant initialisons la structure de molecule

Terminal window
molecule init scenario -d docker --provisioner-name ansible --verifier-name testinfra

Vous devriez obtenir cette structure :

molecule
└── default
├── converge.yml
├── molecule.yml
└── tests
├── conftest.py
├── __pycache__
│ ├── conftest.cpython-310.pyc
│ └── test_default.cpython-310.pyc
└── test_default.py

Créons quelques répertoires pour stocker nos playbooks, templates et nos fichiers :

Terminal window
mkdir {playbooks,files,templates}

Configuration de la collection Ansible

La configuration se fait via le fichier galaxy.yml :

namespace: stephrobert
name: base
version: 1.0.1
readme: README.md
authors:
- Stéphane ROBERT robert.stephane.28@gmail.com
description: Install and configure Gitlab Runner
license:
- GPL-2.0-or-later
license_file: ''
dependencies:
community.general: ">=5.5.0"
repository: https://gitlab.com/ansible-stephrobert/collections/gitlab-runner.git
documentation: /post/ansible-collection-molecule/
homepage: /
issues: https://gitlab.com/ansible-stephrobert/collections/gitlab-runner/-/issues
build_ignore:
- galaxy.yml
- .gitignore

La première partie est déjà configurée, il faut juste éditer les champs du dépôt, les collections en dépendances, de la documentation, des issues et des fichiers qui devront être exclues de l’archive de la collection.

Vous pouvez déjà lancer la commande de build de la collection pour en vérifier le contenu.

Terminal window
tar tvfz stephrobert-base-1.0.0.tar.gz
-rw-r--r-- 0/0 985 2022-11-05 15:21 MANIFEST.json
-rw-r--r-- 0/0 2778 2022-11-05 15:21 FILES.json
-rw-r--r-- 0/0 598 2022-11-05 14:42 .yamllint
drwxr-xr-x 0/0 0 2022-11-05 14:36 plugins/
-rw-r--r-- 0/0 963 2022-11-05 14:36 plugins/README.md
drwxr-xr-x 0/0 0 2022-11-05 14:36 roles/
drwxr-xr-x 0/0 0 2022-11-05 14:36 docs/
drwxr-xr-x 0/0 0 2022-11-05 14:48 templates/
drwxr-xr-x 0/0 0 2022-11-05 14:48 files/
drwxr-xr-x 0/0 0 2022-11-05 14:42 molecule/
drwxr-xr-x 0/0 0 2022-11-05 14:42 molecule/default/
-rw-r--r-- 0/0 208 2022-11-05 14:42 molecule/default/molecule.yml
drwxr-xr-x 0/0 0 2022-11-05 14:42 molecule/default/tests/
-rw-r--r-- 0/0 650 2022-11-05 14:42 molecule/default/tests/conftest.py
-rw-r--r-- 0/0 217 2022-11-05 14:42 molecule/default/tests/test_default.py
-rw-r--r-- 0/0 129 2022-11-05 14:42 molecule/default/converge.yml
-rw-r--r-- 0/0 0 2022-11-05 15:16 requirements.yml
drwxr-xr-x 0/0 0 2022-11-05 14:48 playbooks/
-rw-r--r-- 0/0 84 2022-11-05 14:36 README.md

Configuration de molecule avec une image systemd

Nous allons utiliser un conteneur à base de debian11 permettant d’utiliser systemd. Pourquoi ? Pour tout simplement permettre de démarrer des services comme sur des VM. Copier ce contenu dans votre fichier molecule/default/molecule.yml :

dependency:
name: galaxy
driver:
name: docker
platforms:
- name: debian11_base
image: debian:11
dockerfile: Dockerfile
privileged: True
pre_build_image: False
volumes:
- "/sys/fs/cgroup:/sys/fs/cgroup:rw"
- "/var/run/docker.sock:/var/run/docker.sock:rw"
stop_signal: "SIGRTMIN+3"
capabilities:
- SYS_ADMIN
- SYS_TIME
- LINUX_IMMUTABLE
- CAP_NET_BIND_SERVICE
command: "/lib/systemd/systemd"
provisioner:
name: ansible
env:
ANSIBLE_CONFIG: ../../ansible.cfg
ANSIBLE_FORCE_COLOR: "True"
options:
v: True
verifier:
name: testinfra
options:
v: True
s: True
lint: |
set -e
yamllint .
ansible-lint
...

Pour éviter de multiplier les fichiers indiquant les rôles en dépendances, je le place à la racine de ma collection. Je crée ensuite dans le répertoire molecule/default un lien pointant dessus :

/requirements.yml
---
roles:
- name: bootstrap
src: https://github.com/stephrobert/ansible-role-bootstrap.git
scm: git
version: 1.0.0

Vous remarquerez que j’utilise le scm de type git. Tout simplement pour pouvoir renommer mon rôle en bootstrap plutôt qu’en stephrobert.bootstrap. Sinon le rôle sera inaccessible depuis l’extérieur. Là pour y accéder, il faudra indiquer steprobert.base.bootsrap dans votre playbook.

Terminal window
cd molecule/default
ln -s ../../requirements.yml

Notre image est construite avec ce Dockerfile qui doit se trouver aussi dans le répertoire molecule/default :

FROM debian:11
RUN apt update -y && \
apt install -y --no-install-recommends systemd systemd-cron python3 python3-pip sudo bash vim ca-certificates && \
rm -Rf /usr/share/doc && \
rm -Rf /usr/share/man && \
apt clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN rm -f /lib/systemd/system/multi-user.target.wants/* \
/etc/systemd/system/*.wants/* \
/lib/systemd/system/local-fs.target.wants/* \
/lib/systemd/system/sockets.target.wants/*udev* \
/lib/systemd/system/sockets.target.wants/*initctl* \
/lib/systemd/system/sysinit.target.wants/systemd-tmpfiles-setup* \
/lib/systemd/system/systemd-update-utmp*
# Disable requiretty.
RUN sed -i -e 's/^\(Defaults\s*requiretty\)/#--- \1/' /etc/sudoers
# Create `ansible` user with sudo permissions
ENV ANSIBLE_USER=ansible SUDO_GROUP=sudo
RUN set -xe && \
groupadd -r ${ANSIBLE_USER} && \
useradd -m -g ${ANSIBLE_USER} ${ANSIBLE_USER} && \
usermod -aG ${SUDO_GROUP} ${ANSIBLE_USER} && \
sed -i "/^%${SUDO_GROUP}/s/ALL\$/NOPASSWD:ALL/g" /etc/sudoers
# Custom bashrc
RUN printf "# .bashrc \n\n\
alias pip=pip3 \n\
alias python=python3 \n\
alias ll='ls -l --color=auto' \n\
alias rm='rm -i' \n\
alias cp='cp -i' \n\
alias mv='mv -i' \n\n\
if [ -f /etc/bashrc ]; then \n\
. /etc/bashrc \n\
fi \n\
" > /root/.bashrc
VOLUME [ "/sys/fs/cgroup", "/tmp", "/run" ]
ADD https://raw.githubusercontent.com/gdraheim/docker-systemctl-replacement/master/files/docker/systemctl3.py /usr/bin/systemctl
RUN chmod +x /usr/bin/systemctl
CMD [ "/lib/systemd/systemd" ]

Vérifions que tout fonctionne :

Terminal window
molecule destroy # pour nettoyer les lancements précédents
molecule converge

Vous devriez au bout de quelques minutes obtenir un conteneur tournant en tache de fond :

Terminal window
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
12b1ebbb23df molecule_local/debian:11 "/lib/systemd/systemd" 7 minutes ago Up 7 minutes debian11_base

Pour vous connecter dessus, il suffit de taper une des commandes suivantes :

Terminal window
molecule login
# ou
docker exec -it debian11_base bash
root@debian11base:/#

Pour le moment le rôle ne s’est pas lancé puisque je n’ai pas encore créé mon playbook.

Ecriture du playbook

Nous allons écrire un playbook qui sera utilisé par molecule mais aussi lors de l’utilisation de la collection.

Dans le dossier playbooks créer un fichier bootstrap.yml et déposer ce contenu :

---
- name: Bootstrap de notre machine
hosts: all
roles:
- role: bootstrap
vars:
bootstrap_timeout: 10

Pour que molecule fasse appel à notre playbook, il faut éditer le fichier converge.yml et remplacer le contenu par ceci

---
- name: Import du playbook bootstrap
ansible.builtin.import_playbook: ../../playbooks/bootstrap.yml

Relancez molecule et vous devriez voir l’installation des packages nécessaires au bon fonctionnement d’Ansible sur ma machine cible.

Ajoutons un autre rôle permettant de créer notre user admuser. Pour cela, je vais utiliser un rôle en provenance de ma boutique claranet.users. Editez le fichier requirements.yml et remplacez avec ceci :

---
roles:
- name: stephrobert.bootstrap
version: 1.0.0
- name: claranet.users
version: 2.0.0

Modifions le playbook bootstrap.yml pour utiliser ce role :

---
- name: Bootstrap de notre machine
hosts: all
roles:
- role: bootstrap
vars:
bootstrap_timeout: 10
- role: claranet.users
vars:
users_lang: "en_US.UTF-8"
users_packages: ["bash", "bash-completion", "vim", "sudo", "procps", "htop"]
users:
admuser:
bashrc:
- export PATH="$HOME/.local/bin:/sbin:/usr/sbin:$PATH"
groups:
- adm
- sudo
- root
password: '{{ omit }}'

Je vais en rester là, mais vous pourriez ajouter l’installation de sshd, de motd, de faire un peu d’hardening…

Ecriture des tests avec testinfra

On m’a demandé pourquoi j’utilise testinfra et pas Ansible pour faire mes tests ? Pour deux raisons :

  • Je préfère utiliser un autre système que celui qui fait la configuration
  • Je trouve plus simple d’écrire des tests en python qu’en Ansible.

Dans le dossier molecule/default/tests éditez le fichier test_default.py et déposez-y ce contenu :

"""Role testing files using testinfra."""
def test_root_user(host):
user = host.user("root")
assert user.exists
assert user.shell == "/bin/bash"
assert user.home == f"/{user.name}"
assert user.group == "root"
def test_root_profile_file(host):
user_name = "root"
file_name = f"/{user_name}/.profile"
file = host.file(file_name)
assert file.exists
assert file.is_file
assert file.user == "root"
assert file.group == "root"
assert file.mode == 0o644
assert file.contains("\nreadonly HISTFILE\n")
assert file.contains("\nexport SHELL=/bin/bash\n")
assert file.contains("\nexport LANG=fr_FR.UTF8\n")
def test_admuser_user(host):
user = host.user("admuser")
assert user.exists
assert user.shell == "/bin/bash"
assert user.home == f"/home/{user.name}"
assert user.group == "admuser"
assert "adm" in user.groups
def test_admuser_profile_file(host):
user_name = "admuser"
file_name = f"/home/{user_name}/.profile"
file = host.file(file_name)
assert file.exists
assert file.is_file
assert file.user == "root"
assert file.group == "root"
assert file.mode == 0o644
assert file.contains("\nreadonly HISTFILE\n")
assert file.contains("\nexport SHELL=/bin/bash\n")
def test_installed_packages(host):
assert host.package("bash").is_installed
assert host.package("bash-completion").is_installed
if str(host.system_info.distribution).lower() in ("centos", "redhat", "amzn"):
assert host.package("vim-enhanced").is_installed
else:
assert host.package("vim").is_installed
assert host.package("e2fsprogs").is_installed
def test_ssh_admuser(host):
file_name = f"/home/admuser/.ssh"
file = host.file(file_name)
assert file.exists
assert file.is_directory
assert file.user == "admuser"
assert file.group == "admuser"
assert file.mode == 0o700

On lance les tests avec la commande molecule verify :

Terminal window
molecule verify
...
INFO Running default > verify
INFO Executing Testinfra tests found in /home/vagrant/Projets/personal/ansible/ansible_collections/stephrobert/base/molecule/default/tests/...
============================= test session starts ==============================
platform linux -- Python 3.10.6, pytest-7.1.3, pluggy-1.0.0 -- /usr/bin/python3
rootdir: /home/vagrant
plugins: testinfra-6.8.0
collecting ... collected 6 items
molecule/default/tests/test_default.py::test_root_user[ansible:/debian11_base] PASSED
molecule/default/tests/test_default.py::test_root_profile_file[ansible:/debian11_base] PASSED
molecule/default/tests/test_default.py::test_admuser_user[ansible:/debian11_base] PASSED
molecule/default/tests/test_default.py::test_admuser_profile_file[ansible:/debian11_base] PASSED
molecule/default/tests/test_default.py::test_installed_packages[ansible:/debian11_base] PASSED
molecule/default/tests/test_default.py::test_ssh_admuser[ansible:/debian11_base] PASSED
============================== 6 passed in 4.26s ===============================
INFO Verifier completed successfully.

Tous nos tests fonctionnent. Je rappelle que j’aurai dû faire du TDD en créant les tests puis en écrivant le code Ansible permettant de les résoudre.

Bon notre collection est prête à être envoyé sur notre dépôt, mais avant, attachons-nous à créer notre image Docker qui sera utilisé dans le Pipeline CI.

Construction de l’image Docker molecule

Dans cette image je vais mettre tout ce qui va permettre d’utiliser molecule : docker, ansible, ansible-lint, testinfra …

FROM ubuntu:22.04
WORKDIR /
COPY requirements.txt .
ADD https://raw.githubusercontent.com/fsaintjacques/semver-tool/master/src/semver /usr/local/bin/semver
RUN chmod +x /usr/local/bin/semver && \
apt update && \
DEBIAN_FRONTEND=noninteractive apt install --no-install-recommends --assume-yes \
apt-transport-https \
ca-certificates \
lsb-release \
python3-pip \
curl \
ssh \
git \
software-properties-common && \
echo "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list && \
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/trusted.gpg.d/docker.asc && \
apt update && \
DEBIAN_FRONTEND=noninteractive apt install --no-install-recommends --assume-yes docker-ce && \
pip install --no-cache-dir -r requirements.txt && \
apt autoremove --assume-yes && \
apt clean && \
rm --force --recursive /var/lib/apt/lists/* /tmp/* /var/tmp/*

Le contenu des dépendances python requirements.txt :

ansible==6.5.0
ansible-lint==6.8.2
molecule-docker==1.1.0
docker==6.0.0
molecule==4.0.2
pytest==7.2.0
testinfra==6.0.0
shyaml==0.6.2

Ecriture d’une simple CI Gitlab

Pour notre pipeline d’intégration continue, nous allons utiliser trois étapes (stages gitlab) :

  • Une étape de build
  • Une étape de test : en fait le scenario test intègre tout
  • Une étape de stockage de notre artefact (le tar.gz) sur Ansible Galaxy

En voici le contenu :

---
---
stages:
- build
- tests
- artefacts
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
services:
- docker:dind
variables:
COLLECTIONS_PATH: ${CI_PROJECT_DIR}
COLLECTION_FACTS_PATH: ${COLLECTIONS_PATH}/ansible_collections/stephrobert/base
cache: &global_cache
key: ${CI_COMMIT_REF_SLUG}
paths:
- ${COLLECTION_FACTS_PATH}
policy: pull
build:
stage: build
cache:
<<: *global_cache
policy: push
before_script: []
script:
- chmod 755 .
- ansible-galaxy role install -r ./requirements.yml -p ./roles/
- ansible-galaxy collection build -f .
- ansible-galaxy collection install *.tar.gz -p "${COLLECTIONS_PATH}"
artifacts:
paths:
- '*.tar.gz'
expire_in: 1 month
sanity_test:
stage: tests
script:
- cd ${COLLECTION_FACTS_PATH}
- ansible-test sanity
integration_tests:
stage: tests
needs:
- build
dependencies:
- build
script:
- chmod 755 .
- ansible-galaxy collection install *.tar.gz --force
- ansible-galaxy role install -r ./requirements.yml
- molecule destroy
- molecule converge
- molecule destroy
push:
rules:
- if: $CI_COMMIT_BRANCH == "main"
stage: artefacts
before_script: []
script:
- echo `cat galaxy.yml |shyaml get-value version`
...

Tout est, si vous voulez valider localement votre CI, vous pouvez utiliser gcil. C’est ce que j’ai fait pour éviter les nombreux allers/retours.

Avant de pousser notre projet, il faut installer et configurer le runner. De mon côté, je possède déjà une instance de gitlab-runner sur une de mes machines de mon homelab.

Ah oui, le stage push ne sera lancé que sur la branche main. Renovate va créer des branches sur lequel les tests seront lancés, mais ce n’est que lorsque le merge sera fait que le push s’effectuera.

Installation et Configuration du runner Gitlab

Dans un premier temps voyons comment installer un runner Gitlab-CI. Je vais utiliser un runner tournant sous Docker monté sur une machine Linux. Bien sûr, nous allons écrire et utiliser une collection ansible pour réaliser cette tâche.

Installation de Gitlab Runner

Je vais l’installer sur une Ubuntu 22.04, mais le script fonctionne pour la plupart des distributions :

Terminal window
sudo su
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | bash
apt install gitlab-runner
gitlab-runner status
Runtime platform arch=amd64 os=linux pid=1017961 revision=0d4137b8 version=15.5.0
gitlab-runner: Service is running

Ajoutons le compte gitlab-runner aux sudoers sans mot de passe :

Terminal window
sudo visudo

Ajoutez cette ligne à la fin du fichier :

Terminal window
gitlab-runner ALL=(ALL) NOPASSWD: ALL

Enregistrement du runner

Il faut se connecter avec le compte gitlab-runner .

Terminal window
sudo su gitlab-runner

Modifions la configuration pour ajouter des volumes et le passer le priviliged à true, ça se trouve dans la section runners.docker :

concurrent = 1
check_interval = 0
[session_server]
session_timeout = 1800
[[runners]]
name = "docker-runner"
url = "https://gitlab.com/"
id = 18755596
token = "K4vP7yF8tkCid7p9BAJD"
token_obtained_at = 2022-11-05T18:36:34Z
token_expires_at = 0001-01-01T00:00:00Z
executor = "docker"
[runners.custom_build_dir]
[runners.cache]
[runners.cache.s3]
[runners.cache.gcs]
[runners.cache.azure]
[runners.docker]
tls_verify = false
image = "docker:20.10.16"
privileged = true
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
shm_size = 0

Enregistrer et relancer gitlab-runner :

Terminal window
sudo gitlab-runner restart

Et finissons par ajouter le user gitlab-runner au groupe docker :

Terminal window
usermod -a -G docker gitlab-runner

Reconnectez avec ce compte et tapez la commande docker ps. Si tout est ok, vous verrez la liste des containers vide.

Premier build sur notre runner

Tout est prêt pour lancer notre premier push dans notre dépôt nouvellement créé. Adaptez les commandes avec l’url de votre dépôt :

Terminal window
git init
git config --global init.defaultBranch main
git branch -m main
git remote add origin git@gitlab.com:ansible-stephrobert/collections/base.git
git add .
git commit -m "Initial commit"\ngit push -u origin main

Nos trois stages passent avec succès !!!

Testons Renovate

J’ai déjà documenté l’utilisation dans ce billet.

Je vais simplement ajouter les projets de l’image et de la collection :

module.exports = {
hostRules: [
{
hostType: "docker",
matchHost: "registry.gitlab.com/dockerfiles6",
username: process.env.DEPLOY_USER,
password: process.env.DEPLOY_TOKEN,
},
],
endpoint: "https://gitlab.com/api/v4/",
platform: "gitlab",
gitUrl: "https",
onboardingConfig: {
extends: ["config:base"],
},
vulnerabilityAlerts: {
labels: ["security"],
schedule: "at any time",
},
repositories: [
"dockerfiles6/template/ci-build",
"dockerfiles6/images/hadolint",
"dockerfiles6/images/ansible-lint",
"dockerfiles6/images/lastversion",
"dockerfiles6/images/container-structure-test",
"dockerfiles6/images/img",
"b4288/infra-as-code-homelab",
"dockerfiles6/build-python-wheel",
"ansible-stephrobert/collections/base",
"dockerfiles6/images/molecule-collections"
],
};

Allez, on lance deux pipelines renovate ! Un pour configurer le dépôt pour renovate et un second pour lancer réellement l’analyse des dépendances et créez les branches en cas de maj disponibles.

renovate dependances ansible collection galaxy

Cool, renovate a bien détecté l’existence d’une nouvelle version du rôle base.

Fini de devoir redescendre le projet pour simplement checker si la collection fonctionne toujours après la mise à jour des dépendances. Sur des dizaines de rôles et une dizaine de collections ça en fait des heures de gagner. En cas d’erreur, il faudra tout de même apporter les corrections. Par contre, avec toutes ses heures gagnées, vous pourrez les consacrer à faire votre veille techno, travailler sur des projets à plus fortes valeurs ajoutés.

Pour éviter d’avoir trop de branches créées par renovate, donc éviter de faire trop de bruit, vous pouvez grouper toutes les mises à jour dans une seule merge request. Pour cela, il faut ajouter une règle dans le fichier renovate.json comme ceci :

{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:base"],
"packageRules": [
{
"groupName": "all dependencies",
"groupSlug": "all",
"matchPackagePatterns": ["*"]
}
]
}

Vous obtiendrez une seule merge request portant le nom chore(deps): update all dependencies.

Plus loin

Il ne reste plus qu’à écrire d’autres collections pour les midlleware en utilisant cette collection de base, des collections par projet utilisant la collection de base et celles des middlewares, à mettre en place renovate dessus. Après cela, vous pourrez gérer plus sereinement ceux-ci !

Vous pouvez retrouver tous les codes sources de ce projet dans les dépôts suivants :