> ## Content Index
> Fetch the complete content index at: https://www.sfeir.dev/llms.txt
> Use this file to discover other available public pages before exploring further.

# Automatiser Dependabot sans perdre le contrôle de vos mises à jour
- URL: https://www.sfeir.dev/automatiser-dependabot-sans-perdre-le-controle-de-vos-mises-a-jour/
- Published: 2026-09-01T12:38:18.000Z
- Updated: 2026-09-01T12:38:18.000Z
- Description: En tant que mainteneur de plusieurs dépôts open source, je recevais une PR Dependabot par mise à jour. Voici comment j'ai standardisé la configuration pour grouper, temporiser et auto-merger les mises à jour mineures, sans jamais merger à l'aveugle.
- Author: Romain Lespinasse
- Tags: cicd, automatisation, Security, GitHub

Dix secondes. C'est ce que coûte l'approbation d'un bump patch : ouvrir la PR, jeter un œil au numéro de version, cliquer. Sur la dizaine de dépôts open source que je maintiens, avec plusieurs mises à jour par semaine sur chacun, ces dix secondes deviennent un flux continu de clics à faible valeur ajoutée. Voici comment j'ai standardisé la configuration Dependabot et branché un auto-merge conditionnel dessus, pour absorber ce bruit sans perdre le contrôle sur ce qui compte vraiment.

## Le problème : Dependabot qui spamme

Le scénario est toujours le même : `build(deps): bump X from 1.2.3 to 1.2.4`, une PR, une notification, une revue. Puis une autre, pour une dépendance différente, sur un autre dépôt, le lendemain. Le contenu de la revue tient rarement en plus d'un coup d'œil au changelog, mais le geste, lui, se répète.

Le vrai coût n'est pas le temps passé sur chaque PR individuellement, il est ailleurs :

- Le bruit dans la liste des PRs et les notifications, qui noie dans le même flot les patchs anodins et les mises à jour majeures, les seules à porter un vrai risque de breaking change
- Une revue qui devient un réflexe plutôt qu'un jugement, avec le risque de cliquer « merge » sans vraiment regarder

Sur un seul dépôt, ce bruit reste gérable. À l'échelle de plusieurs dépôts personnels maintenus en parallèle, il devient un vrai coût d'attention.

Toute la suite repose sur une distinction : celle que [SemVer](https://semver.org/lang/fr/?ref=sfeir.dev) pose entre un bump `major`, seul autorisé à casser l'API publique, et les bumps `minor` et `patch`, censés rester compatibles. C'est cette frontière qui va servir de ligne de partage entre ce qu'on automatise et ce qu'on continue de lire.

## Le prérequis non négociable : des tests qui détectent les vrais problèmes

Avant d'aller plus loin, le point sur lequel je ne transige pas : cet auto-merge revient à laisser GitHub fusionner une PR tout seul, dès que les checks passent au vert et sans qu'un humain la relise. Il ne vaut donc que ce que vaut cette CI. Si elle se limite à un `build` ou à un lint, « CI verte » ne veut rien dire de plus que « ça compile ». Automatiser le merge dans ce contexte ne fait pas gagner du temps sur une tâche sans risque, ça fait juste merger à l'aveugle plus vite. C'est le raisonnement du [harness engineering](https://www.sfeir.dev/ia/harness-engineering-construire-la-confiance-dans-vos-agents-ia) appliqué aux dépendances : la confiance ne vient pas de la revue qu'on retire, elle vient du harnais qui la remplace.

Ce pattern est une récompense pour qui a déjà une suite de tests fiable, pas un moyen de s'en passer. Il faut donc :

- Une suite de tests qui couvre les chemins critiques du projet, pas seulement « le programme démarre sans planter ». Si le vôtre n'en est pas là, les [tests par propriété](https://www.sfeir.dev/back/decouvrir-les-tests-par-propriete-avec-java-et-jqwik) sont une piste pour couvrir des règles métier sans écrire un cas par scénario
- Une CI qui exécute réellement ces tests sur les PRs Dependabot, au même titre que sur les PRs humaines
- Un check marqué comme obligatoire via la protection de branche, pour que l'auto-merge attende un vrai signal plutôt qu'un job optionnel que personne ne regarde

Le dernier point est une contrainte technique autant qu'une bonne pratique : sans check requis, une PR Dependabot est mergeable dès son ouverture, et la commande d'auto-merge vue plus bas échoue au lieu de programmer quoi que ce soit.

Sur un dépôt sans couverture de tests fiable, je n'active pas ce pattern et je ne le recommanderais à personne. La suite part du principe que ce prérequis est rempli.

## Le pattern en trois leviers

La configuration que j'ai standardisée sur mes dépôts tient dans `.github/dependabot.yml`, à la racine du dépôt et **sur la branche par défaut**. Ailleurs, Dependabot ne la lit pas :

```yaml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    cooldown:
      default-days: 5
    commit-message:
      prefix: "build"
      include: "scope"
    groups:
      dependencies:
        patterns:
          - "*"
        update-types:
          - "minor"
          - "patch"

```

Deux clés relèvent plutôt de la configuration de base que du réglage du volume de PRs. `directory` indique où chercher le manifeste (`package.json`, `Cargo.toml`…), ici la racine. `commit-message` est ce qui produit le `build(deps): bump X…` du début de l'article : `prefix: "build"` fixe le type de commit conventionnel, `include: "scope"` ajoute le `(deps)`. Pratique quand un changelog est généré à partir des commits, mais sans effet sur le volume de PRs.

Les leviers qui comptent, eux, sont ailleurs.

### Groups : une PR au lieu de dix

La clé `groups` regroupe toutes les mises à jour minor et patch dans une seule PR nommée `dependencies`, au lieu d'une PR par dépendance. Si je ne devais garder qu'un seul de ces réglages, ce serait celui-là : c'est le seul qui attaque le volume, et dix bumps patch dans la même semaine deviennent une seule revue.

Espacer le `schedule.interval` ne remplace pas ce levier. Sans `groups`, passer de `weekly` à `monthly` laisse chaque dépendance ouvrir sa propre PR, simplement moins souvent. Le nombre de PRs à merger ne diminue pas, il s'accumule plus longtemps avant d'arriver d'un coup, avec des mises à jour plus anciennes et donc plus éloignées du code en place. Les mises à jour de sécurité, elles, échappent à ce délai : Dependabot les ouvre immédiatement.

Un détail à connaître avant de laisser tourner : Dependabot plafonne par défaut à 5 PRs de mise à jour ouvertes simultanément par écosystème (`open-pull-requests-limit`). Avec ce pattern, les majors sortent en PRs individuelles ; si vous en laissez traîner cinq sans les traiter, la PR groupée ne s'ouvre plus du tout, silencieusement. C'est une bonne incitation à vider la file des majors, mais mieux vaut savoir que le blocage vient de là.

### Cooldown : laisser une version faire ses preuves

`cooldown.default-days: 5` fait attendre Dependabot cinq jours après la sortie d'une nouvelle version avant de la proposer. La plupart des régressions introduites par une release sont signalées par la communauté dans les premiers jours ; il s'agit de ne pas être la personne qui les découvre.

À noter : ce réglage ne crée pas ce délai, il le durcit. [Dependabot applique désormais un cooldown de 3 jours par défaut](https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference?ref=sfeir.dev) aux mises à jour de version, sans rien configurer. Passer à 5 jours est donc un ajustement, pas un changement de nature, et je ne le défendrais pas sur un dépôt suivi au quotidien. Sur ceux que je n'ouvre qu'une fois par mois, en revanche, ces deux jours de plus valent leur prix.

Ce délai a un revers : il retarde de la même façon un correctif que vous attendez activement. Une version qui corrige un bug qui vous bloque met, elle aussi, ces quelques jours à vous parvenir. Sur un projet où un fix précis est urgent, rien n'empêche de forcer manuellement la mise à jour en attendant que Dependabot la propose de lui-même.

En revanche, la crainte la plus naturelle (« est-ce que je viens de retarder de cinq jours un correctif de faille ? ») n'a pas lieu d'être : le cooldown ne s'applique qu'aux mises à jour de version. Les mises à jour de sécurité déclenchées par une alerte Dependabot y échappent complètement, exactement comme elles échappent au `schedule.interval`.

### Le tri implicite entre minor/patch et major

Le champ `update-types` du groupe ne retient que `minor` et `patch`. Les mises à jour majeures restent en dehors du groupe : chacune ouvre sa propre PR, individuelle, qui ne sera jamais auto-mergée. C'est ce tri qui permet d'automatiser sans perdre le contrôle sur les changements qui portent un vrai risque de rupture.

## L'auto-merge conditionnel

La configuration Dependabot regroupe et espace les mises à jour, mais ne les merge pas. Ce rôle revient à un workflow GitHub Actions, `.github/workflows/dependabot-auto-merge.yml`, lui aussi à placer sur la branche par défaut :

![Schéma du workflow d'auto-merge : une PR Dependabot passe le test du type de mise à jour puis celui de la CI avant d'être fusionnée automatiquement ou envoyée en revue humaine.](https://storage.ghost.io/c/0b/31/0b31478e-a66a-46f1-8c34-d44388e21192/content/images/2026/09/auto-merge-flow-image.webp)

Deux filtres avant le merge : le type de mise à jour, puis l'état de la CI.

```yaml
name: Dependabot auto-merge

on: pull_request

permissions:
  contents: write
  pull-requests: write

jobs:
  auto-merge:
    if: github.event.pull_request.user.login == 'dependabot[bot]'
    runs-on: ubuntu-latest
    steps:
      - name: Dependabot metadata
        id: metadata
        uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}

      - name: Enable auto-merge for minor/patch updates
        if: steps.metadata.outputs.update-type != 'version-update:semver-major'
        run: gh pr merge --auto --squash "$PR_URL"
        env:
          PR_URL: ${{ github.event.pull_request.html_url }}
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

```

Ce workflow reprend la structure de [l'exemple officiel GitHub](https://docs.github.com/en/code-security/tutorials/secure-your-dependencies/automate-dependabot-with-actions?ref=sfeir.dev), avec deux écarts. La condition est une liste noire (`!= semver-major`) là où la doc propose une liste blanche, dépendance par dépendance. J'assume cet élargissement, mais uniquement parce que le prérequis sur les tests est tenu : sans lui, la liste blanche de la doc reste le bon choix. Et surtout, il ne vaut qu'adossé à la configuration `dependabot.yml` décrite plus haut. La doc ne traite que la moitié Actions du problème, celle du merge, jamais celle du volume de PRs.

Quatre choses à noter :

- Le job ne s'exécute que sur les PRs ouvertes par `dependabot[bot]` : aucune PR humaine ne passe par ce chemin. Le test porte sur l'auteur de la PR (`github.event.pull_request.user.login`) et non sur `github.actor`, qui devient le login de la personne ayant relancé le workflow lors d'un re-run manuel
- Le bloc `permissions` n'est pas décoratif. GitHub traite les workflows déclenchés par Dependabot comme s'ils venaient d'un fork : le `GITHUB_TOKEN` y est en lecture seule par défaut. Sans cette élévation explicite, le workflow n'a pas le droit d'activer l'auto-merge
- L'action [dependabot/fetch-metadata](https://github.com/dependabot/fetch-metadata?ref=sfeir.dev) expose le type de mise à jour sous la forme `version-update:semver-major`, `version-update:semver-minor` ou `version-update:semver-patch`, ce qui évite de parser le titre de la PR. Sur une PR groupée, elle retourne le bump le plus élevé du lot, ce qui rend le test ci-dessus correct malgré le regroupement
- `gh pr merge --auto` n'effectue pas un merge immédiat : il active l'auto-merge natif de GitHub, qui attend que les checks requis passent avant d'agir. Le workflow ne court-circuite donc jamais la CI

Le filtre sur `update-type` fait le reste : dès qu'une mise à jour est majeure, l'étape est sautée et la PR attend une revue humaine comme n'importe quelle autre.

### Les réglages GitHub à vérifier avant de copier ce workflow

Ce workflow ne fonctionne que si le dépôt est configuré pour l'accepter. Les réglages concernés sont dans les paramètres du dépôt, et les manquer fait échouer `gh pr merge --auto` ou le laisse sans effet :

- **Allow auto-merge** doit être activé dans *Settings → General → Pull Requests*. Il ne l'est pas par défaut, et sans lui `gh pr merge --auto` échoue directement
- Le mode de merge utilisé par le workflow (ici `--squash`) doit être autorisé dans ces mêmes paramètres. Si seul le merge simple ou le rebase est permis, l'option échoue
- Si la protection de branche exige des approbations, l'auto-merge ne les remplace pas : il programme le merge, qui reste bloqué tant qu'elles manquent. Dependabot ne s'auto-approuve pas, il faut donc soit exempter ses PRs, soit garder une approbation manuelle même pour les mises à jour groupées

### Quand rien ne se passe : où regarder

Le mode d'échec le plus déroutant de ce pattern, c'est le silence. Les endroits à consulter, dans l'ordre :

- *Insights → Dependency graph → Dependabot* liste chaque écosystème configuré, la date du dernier check et, surtout, les erreurs de parsing du `dependabot.yml`. Un fichier invalide n'y produit aucune PR et aucune notification, juste une ligne d'erreur ici
- L'onglet *Actions* de la PR concernée : si le job `auto-merge` n'apparaît pas du tout, c'est la condition `if` du job qui a filtré ; s'il apparaît en échec, le message de `gh` est explicite
- La PR elle-même, qui affiche un bandeau *Auto-merge enabled* quand la programmation a réussi. En son absence, le merge n'est pas planifié, même si la CI passe au vert ensuite

Le message le plus fréquent à ce stade est un `Pull request is in clean status` retourné par `gh` : la PR est déjà mergeable, il n'y a rien à programmer. Autrement dit, aucun check n'est réellement requis sur la branche, ce qui ramène au prérequis du début. Une fois la configuration corrigée, les commentaires `@dependabot rebase` et `@dependabot recreate` relancent le cycle depuis la PR.

## Pourquoi le risque reste maîtrisé

Une fois le prérequis sur les tests posé, le dispositif repose sur des garde-fous qui se cumulent :

- L'auto-merge attend que les checks CI passent, il ne les remplace pas
- Le cooldown limite le risque de récupérer une version fraîchement publiée et pas encore éprouvée par la communauté
- Les mises à jour majeures, qui portent le vrai risque de rupture, ne sont jamais auto-mergées : elles restent sous revue manuelle

S'y ajoute une précaution qui relève de la chaîne d'approvisionnement : `fetch-metadata` est épinglée sur son SHA de commit (`@25dd0e3...`, avec `# v3.1.0` en commentaire pour la lisibilité), pas sur un tag mutable. Un tag comme `v3` peut être déplacé sans prévenir ; un SHA, non. Sur un workflow qui tourne tout seul avec la permission `contents: write`, je considère ça comme non négociable.

Reste que ces garde-fous couvrent la sécurité et le versionnage, pas le comportement du code. Un bump patch qui casse silencieusement une fonctionnalité passera tous ces filtres sans encombre : seule une suite de tests capable de le détecter l'arrêtera. Et une suite peut très bien être verte sans rien vérifier, comme le rappellent les [tests qui se mockent eux-mêmes](https://www.sfeir.dev/jai-diagnostique-30-prs-vibe-codees-par-semaine-voici-les-5-red-flags-qui-reviennent) repérés en revue de PRs, un travers du même ordre que ceux décrits dans [notre méthode pour gérer 30 PRs par semaine](https://www.sfeir.dev/ia/cadrer-avant-de-prompter-notre-methode-pour-gerer-30-prs-par-semaine/).

## Retour d'expérience : déployer le pattern sur plusieurs dépôts

J'ai appliqué cette configuration sur tous mes dépôts open source personnels, sans distinction de langage ni d'écosystème : [drawio-export](https://github.com/rlespinasse/drawio-export?ref=sfeir.dev) suit une image Docker et ses actions, [agent-skills](https://github.com/rlespinasse/agent-skills?ref=sfeir.dev) ne surveille que ses GitHub Actions. Une série de commits reproduisant le même changement (`build: standardize dependabot config and enable auto-merge for minor/patch updates`) a suffi. Sa brièveté a beaucoup aidé : pas besoin de la repenser dépôt par dépôt.

En pratique, seules les deux premières lignes du bloc bougent d'un dépôt à l'autre :

```yaml
  - package-ecosystem: "cargo"   # ou "gomod", "github-actions", "gitsubmodule"…
    directory: "/"

```

Le reste du bloc est identique partout, et `cooldown.default-days` est supporté par tous les écosystèmes que Dependabot gère. Il existe bien des réglages plus fins par type de version, `semver-major-days`, `semver-minor-days` et `semver-patch-days`, mais ils ne sont disponibles que sur une partie d'entre eux : `github-actions`, `docker` ou `terraform` n'en bénéficient pas. `default-days` seul suffit. Le workflow d'auto-merge, lui, ne regarde que le type de mise à jour, donc il se copie sans la moindre adaptation.

La seule variation que je me suis autorisée concerne [github-slug-action](https://github.com/rlespinasse/github-slug-action?ref=sfeir.dev) ([5 ans de maintenance racontés ici](https://www.sfeir.dev/5-ans-de-github-slug-action-une-aventure-open-source/)), qui expose ses propres actions : j'y ai ajouté un second bloc `github-actions` ciblant mes actions internes, pour les traiter séparément du reste.

L'effet le plus net porte sur le volume, pas sur le temps gagné PR par PR : les mises à jour mineures et patch, l'essentiel du flot, ne demandent quasiment plus d'intervention. Ce qui reste dans ma liste de revues, ce sont les majeures, les seules qui méritent une lecture attentive.

## Conclusion

La configuration tient en quelques lignes et se copie d'un dépôt à l'autre. C'est le morceau facile. Rien là-dedans ne remplace une suite de tests qui détecte réellement les problèmes : c'est elle qui décide si chaque merge automatique est un gain de temps ou un pari. Automatiser Dependabot déplace le travail, de la revue des PRs vers l'entretien des tests.

## Pour aller plus loin

- [Référence des options dependabot.yml](https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference?ref=sfeir.dev) : `cooldown`, `groups`, `open-pull-requests-limit` et le support par écosystème
- [Automatiser Dependabot avec GitHub Actions](https://docs.github.com/en/code-security/tutorials/secure-your-dependencies/automate-dependabot-with-actions?ref=sfeir.dev) : le tutoriel officiel dont ce workflow reprend la structure
- [dependabot/fetch-metadata](https://github.com/dependabot/fetch-metadata?ref=sfeir.dev) : la liste complète des sorties exposées par l'action
- [Dépanner Dependabot sur GitHub Actions](https://docs.github.com/en/code-security/dependabot/troubleshooting-dependabot/troubleshooting-dependabot-on-github-actions?ref=sfeir.dev) : le `GITHUB_TOKEN` en lecture seule et les autres pièges de permissions