Skip to content

Prédire les pull requests qui vont bloquer — avec la baseline de votre équipe

Aliaume Caplat Fondateur, DevPrism LinkedIn
pull-requests engineering-metrics dora engineering-management

Toutes les équipes finissent par mettre en place la même automatisation : « préviens-moi quand une pull request est ouverte depuis plus de 48 heures ».

Et toutes finissent par la désactiver.

Non pas parce que les PR qui traînent auraient cessé d’être un problème. Parce que 48 heures est le chiffre de quelqu’un d’autre. Dans une équipe qui relit en deux heures, l’alerte arrive bien trop tard pour servir. Dans une équipe qui relit deux fois par semaine, elle se déclenche sur tout, tous les jours, jusqu’à ce que le canal soit mis en sourdine.

Un seuil doit bien venir de quelque part. L’erreur est de le choisir à la main.

Le changement de point de vue : comparer une PR à votre équipe, pas à une constante

La question « cette PR est-elle en retard ? » n’a pas de réponse absolue. Elle n’en a qu’une relative : en retard par rapport à ce que fait habituellement cette équipe.

Ce recadrage transforme une opinion en calcul. Vous avez déjà la donnée : chaque PR mergée est une observation du temps que prend réellement une review chez vous. Transformez ces observations en distribution, et le seuil se choisit tout seul.

Deux mesures comptent, et ce ne sont pas les mêmes :

Mesure Définition Ce qu’elle dit
Pickup time Ouverture de la PR → première review Combien de temps le code attend un humain
Cycle time Ouverture de la PR → clôture / merge Tout le parcours, travail de l’auteur compris

Le pickup time est celui sur lequel il faut alerter. Le cycle time englobe les réponses de l’auteur aux commentaires, les rebases, l’attente de la CI — du travail en cours, légitime. Le pickup time mesure autre chose : personne n’a encore regardé. C’est du temps de file d’attente, c’est du gaspillage pur, et contrairement au cycle time, quelqu’un d’autre que l’auteur peut agir dessus.

Étape 1 — Construire la baseline

Prenez vos PR mergées sur une fenêtre glissante et calculez les 50e, 75e et 90e centiles du pickup time.

Cette seule phrase cache quatre décisions, et chacune fait la différence entre un signal et du bruit.

Utiliser percentile_disc, pas percentile_cont

percentile_cont interpole entre deux observations. Sur un échantillon de douze PR, cela fabrique une durée qui n’a jamais existé — un P75 à « 26,4 heures » alors que votre équipe n’a jamais mis 26,4 heures. percentile_disc renvoie une observation réelle. Quand vous direz à un ingénieur « cette PR dépasse le P75 de votre équipe », il vaut mieux que ce chiffre soit une chose qui s’est réellement produite.

Exclure les bots de maintenance

Les bots de mise à jour de dépendances ouvrent beaucoup de PR et en abandonnent beaucoup. Laissés dans l’échantillon, ils dominent la distribution et faussent le signal humain que vous cherchez à mesurer. Imaginez un bot de dépendances qui ouvre quelques montées de version par semaine, dont la plupart sont mergées automatiquement, remplacées par la version suivante ou refermées sans un mot. Ses durées décrivent un processus qu’aucun humain n’a joué — et comme il ouvre bien plus de PR que n’importe quelle personne, un seul compte de bot peut peser plus lourd que toute votre équipe dans l’échantillon. Personne n’allait relire ces PR. Ce n’est pas de la dette de review.

Refuser de répondre en dessous d’un échantillon minimal

En dessous d’une dizaine de PR mergées sur la fenêtre, les centiles sont du bruit déguisé en précision. Un P90 calculé sur quatre observations, c’est simplement « la plus lente des quatre ». Le bon comportement est de n’émettre rien : pas de baseline, pas de prédiction, pas d’alerte.

Cela mérite d’insister, parce que c’est l’inverse de ce que font la plupart des tableaux de bord. Un outil qui produit toujours un chiffre apprend à ses lecteurs que ses chiffres ne veulent rien dire. Refuser de répondre est une fonctionnalité, et c’est la crédibilité la moins chère que vous achèterez jamais.

Calculer la baseline par équipe

Une équipe plateforme et une équipe mobile ne partagent ni culture de review, ni fuseau horaire, ni définition de l’urgence. Un centile global écrase les deux dans un chiffre qui ne décrit ni l’une ni l’autre.

La requête, si vous voulez la refaire

Rien de ce qui précède n’exige un outil. Si votre historique de pull requests est dans un entrepôt de données, toute la baseline tient en une requête — passez-la si ce n’est pas le cas, la suite de l’article se lit sans elle.

SELECT
  percentile_disc(0.50) WITHIN GROUP (ORDER BY pickup_hours) AS p50,
  percentile_disc(0.75) WITHIN GROUP (ORDER BY pickup_hours) AS p75,
  percentile_disc(0.90) WITHIN GROUP (ORDER BY pickup_hours) AS p90,
  count(*)                                                   AS sample_size
FROM (
  SELECT EXTRACT(EPOCH FROM (first_review_at - created_at)) / 3600 AS pickup_hours
  FROM pull_requests
  WHERE merged_at BETWEEN :period_start AND :period_end
    AND first_review_at IS NOT NULL
    AND author NOT IN (SELECT login FROM maintenance_bots)
) AS observed;

Étape 2 — Scorer les PR ouvertes

Parcourez maintenant les PR ouvertes. Pour chacune, prenez le temps écoulé depuis l’ouverture et placez-le dans la distribution :

écoulé < P50            → dans les clous  (ne rien émettre)
P50 ≤ écoulé < P75      → ralentit
P75 ≤ écoulé < P90      → à risque
écoulé ≥ P90            → blocage prévisible

Deux règles rendent tout cela utilisable.

Ignorer toute PR qui a déjà reçu une première review. Dès qu’un humain s’en est saisi, la PR n’est plus en file d’attente : elle avance. Alerter dessus produit exactement le faux positif qui fait couper l’intégration entière. Cette seule condition élimine l’essentiel du bruit.

Ne rien dire des PR en dessous du P50. La moitié de vos PR ouvertes sont dans les clous par construction. Les signaler ajoute du volume et retire de l’attention.

Et quand vous émettez quelque chose, nommez la comparaison :

Aucune review après 31,4 h — dépasse le P75 de l’équipe (26 h). Risque de blocage.

Pas « cette PR est à risque ». Le chiffre auquel on compare le lecteur doit figurer dans le message, sinon l’alerte est un argument d’autorité et non un argument. Cela la rend aussi réfutable : n’importe qui peut aller vérifier que 26 heures est bien son P75 — et c’est précisément le but.

Ce que ça ne dit pas

Un modèle qu’on ne peut pas critiquer est un modèle qu’on ne devrait pas livrer. Quatre limites honnêtes :

La baseline est construite sur les survivantes. Elle ne compte que les PR relues et mergées. Celles qui ont été abandonnées après avoir pourri trois semaines ne pèsent rien, donc la distribution est systématiquement plus optimiste que le vécu de l’équipe. L’alerte est donc conservatrice : quand elle se déclenche, elle veut dire quelque chose.

La baseline dérive avec l’équipe. Un trimestre de mauvaise hygiène de review fait monter le P75, et un P75 plus haut rend l’alerte plus silencieuse. La mesure s’adapte à la dégradation au lieu de la signaler. Suivez donc la baseline elle-même dans le temps, comme un indicateur à part entière : un P90 qui double en deux mois, c’est ça, le constat — et aucune alerte par PR ne vous le montrera.

Elle prédit une défaillance précise. Le blocage avant la première review, et rien d’autre. Elle ne dit rien de la justesse du code, de la taille de la PR, ni d’une CI sur le point d’échouer. C’est un signal parmi d’autres, pas un score de risque.

Les petites équipes ont des centiles bruités. Dix observations est un plancher, pas un confort. Sur un petit échantillon, préférez élargir la fenêtre plutôt que resserrer le seuil.

Pourquoi ça vaut l’effort

Un seuil fixe est une politique : quelqu’un a décidé 48 heures. Une baseline en centiles est une mesure : votre équipe a décidé, en travaillant.

Cette distinction compte plus que le gain de précision. Une alerte qui dit « cela dépasse le chiffre qu’on m’a configuré » invite à discuter la configuration. Une alerte qui dit « cela dépasse ce que votre équipe tient trois fois sur quatre » invite à parler de la file d’attente — c’est-à-dire de ce dont vous vouliez parler.

Comment DevPrism le fait

DevPrism calcule cette baseline par équipe à chaque synchronisation, et score les PR ouvertes en conséquence :

  • Centiles de pickup time et de cycle time issus de vos PR mergées, bots de maintenance exclus
  • Centiles discrets, donc chaque seuil est une durée que votre équipe a réellement enregistrée
  • Prédiction désactivée sous l’échantillon minimal, et sur les PR déjà en review
  • Chaque PR signalée porte son ratio à la baseline et un motif nommant le centile franchi
Les PR ouvertes scorées face à la baseline de l'équipe — celles qui sont signalées portent le centile franchi, pas un avertissement générique.

Le but de tout ceci n’est pas de prédire l’avenir. C’est d’arrêter de demander à chaque manager d’inventer un chiffre, et de rendre l’alerte défendable devant celui qui la reçoit.


Envie que cette baseline soit calculée pour vous, par équipe, à partir de votre historique ? Essayez DevPrism gratuitement — PR Intelligence et le risk scoring complet font partie du plan Pro, inclus dans l’essai de 14 jours, sans carte bancaire.