Vérification de la Disponibilité des PR Communautaires
Étant donné un numéro de PR ou un nom de branche, détermine si elle est prête pour examen humain et prendre la bonne action de suivi.
Arbre de décision
- Auteur bot (
n8n-cat-bot/aikido-autofix) → nettoyage uniquement, pas d'examen. Voir « PR d'automatisation interne » ci-dessous. - Correspondance des filtres de rejet automatique (correction de typo uniquement / nouveau nœud non autorisé) → chemin d'action D — fermer avec le modèle correspondant.
- Tous les contrôles passent (
readyForReview === true) → chemin d'action B — triage à l'équipe. - Un ou plusieurs contrôles échouent → chemin d'action A (si le titre est un correctif mineur uniquement) puis C — poster un commentaire.
Étape 1 — Résoudre la PR
Si un nom de branche est fourni, trouve d'abord le numéro de PR :
gh pr view <branch> --repo n8n-io/n8n --json number --jq .number
Étape 2 — Récupérer et pré-traiter
gh pr view <number> --repo n8n-io/n8n \
--json number,title,body,author,headRefName,headRefOid,files,isDraft,state,labels
PR d'automatisation interne (auteurs bot)
Si author.login est l'un des bots internes de n8n — n8n-cat-bot / app/n8n-cat-bot ou aikido-autofix / app/aikido-autofix — ignore la PR entièrement et effectue les actions de nettoyage ci-dessous. Ne produis pas de sortie JSON.
- Réétiquète la PR (les deux bots) : remplace
community→n8n team:gh pr edit <number> --repo n8n-io/n8n --remove-label community --add-label "n8n team" - Mets à jour le ticket Linear lié (extrait
GHC-XXXXpar étape 5) :n8n-cat-bot— annuler : utilise l'outil MCP Linear disponible avecstate: "Canceled", sans étiquettes.aikido-autofix— router vers Dev Platform : utilise l'outil MCP Linear disponible avecteam: "Developer Platform",state: "Triage", sans étiquettes.
Lors de l'examen d'un lot, exclut la PR ignorée de la sortie. Pour une PR unique, produis une note d'une ligne (ex. Skipped & cleaned up #30591 (n8n-cat-bot): relabeled to n8n team, cancelled GHC-8398.).
Garde de collision
Si triage:in-progress est déjà sur la PR, un autre examinateur est en cours de triage — abandonne pour éviter un double-traitement. Produis une note d'une ligne (ex. Skipped #30205: already has triage:in-progress) et passe à la PR suivante. Ne lance pas les contrôles, ne modifie pas les étiquettes, ne touche pas à Linear.
Si l'utilisateur demande explicitement de retraiter une PR bloquée sur triage:in-progress (ex. une exécution précédente a planté), il peut effacer manuellement l'étiquette et réinvoquer.
Sinon — marquer en cours
Supprime toute étiquette d'état triage:* existante avant d'ajouter triage:in-progress, de sorte que l'invariant à état unique tient même lors du réexamen d'une PR précédemment renvoyée avec triage:needs-info ou triage:tests-needed :
gh pr edit <number> --repo n8n-io/n8n \
--remove-label "triage:pending" \
--remove-label "triage:needs-info" \
--remove-label "triage:tests-needed" \
--remove-label "triage:complete" \
--add-label "triage:in-progress"
Un seul de ces libellés triage:* sera réellement présent ; --remove-label génère une erreur quand une étiquette est manquante, donc lance chaque suppression en tant qu'appel distinct (ou traite par lot et ignore les erreurs) puis effectue l'ajout. Une PR porte exactement un libellé triage:<state> à la fois ; la compétence remplace triage:in-progress par un état terminal avant la sortie (voir reference/label-flow.md).
Récupère aussi (en parallèle)
# cubic-dev-ai PR review comments (for check E)
gh api --paginate "repos/n8n-io/n8n/pulls/<number>/comments" \
--jq '.[] | select(.user.login == "cubic-dev-ai[bot]") | {body: .body, path: .path}'
# n8n-assistant issue comments (for the Linear ticket reference)
gh api --paginate "repos/n8n-io/n8n/issues/<number>/comments" \
--jq '[.[] | select(.user.login == "n8n-assistant[bot]" or .user.login == "n8n-assistant") | .body] | join("\n")'
Étape 2.5 — Filtre de rejet automatique
Selon CONTRIBUTING.md, deux modèles de PR doivent être fermés directement plutôt que révisés :
- PR correction de typo uniquement — le diff contient uniquement des corrections d'orthographe/grammaire sans logique ni tests.
- PR nouveau nœud — ajoute un tout nouveau nœud, sauf si l'équipe n8n a explicitement accepté de l'inclure dans la portée.
Si l'un des deux correspond, définis checks.AutoReject et passe directement à l'action D. Règles complètes et comment vérifier chaque modèle : voir reference/checks.md.
Étape 3 — Lancer les cinq contrôles
Lance quand AutoReject est null. Règles complètes pour chacun dans reference/checks.md :
- A. CLA — libellé
cla-signedprésent. - B. Titre — correspond à la regex conventional-commit. Règles faisant autorité dans
.github/pull_request_title_conventions.md. - C. Description — chaque en-tête de section et élément de checklist du
.github/pull_request_template.mdest présent dans le corps de la PR. Le modèle est lu au moment du contrôle, donc les changements se propagent automatiquement. - D. Tests — les changements de logique source ont des fichiers de test correspondants. À ignorer pour les PR
docs/ci/chore/build. - E. cubic-dev-ai — aucun commentaire non résolu (résolu = marqueur « Addressed in commit »).
Étape 4 — Identifier l'équipe responsable
Lance node .github/scripts/owners.mjs sur la liste des fichiers modifiés et mappe l'équipe GitHub gagnante à une équipe Linear. Tableau de mapping complet, procédure de fallback du sous-agent et règles d'étiquettes : voir reference/teams.md.
Étape 5 — Extraire le ticket Linear
n8n-assistant laisse un commentaire sur chaque PR communautaire contenant This PR has been added to our internal tracker as "GHC-XXXX". Cherche dans le corps du commentaire n8n-assistant concaténé \bGHC-\d+\b, prends la première correspondance.
Si aucun commentaire n8n-assistant n'existe (PRs plus anciennes antérieures à l'automatisation), linearTicket est null.
Étape 5b — Trouver des tickets Linear pour les problèmes que cette PR prétend corriger
Le corps de la PR dit souvent Fixes #NNNN / Closes #NNNN / Resolves #NNNN (ou lie à https://github.com/n8n-io/n8n/issues/NNNN). Chacun de ces problèmes a habituellement son propre ticket GHC (ou a déjà été trié à une équipe). Mets en avant ceux-ci pour que l'action d'assignation puisse les croiser.
- Extrais chaque numéro de problème du corps de la PR correspondant à
\b(?:fix(?:es)?|close[sd]?|resolve[sd]?)\s+#?(\d+)\b(insensible à la casse) ou URLs correspondant àgithub\.com/n8n-io/n8n/issues/(\d+). Déduplique. - Pour chaque numéro de problème, recherche dans Linear avec l'outil MCP Linear disponible (requête
github.com/n8n-io/n8n/issues/<num>, limite 50) et filtre le résultat aux problèmes dont ladescriptioncontient l'URL exactehttps://github.com/n8n-io/n8n/issues/<num>. Le bot n8n-assistant intègre cette URL dans la description de chaque ticket de problème communautaire qu'il crée, donc la correspondance est fiable. Utilise la limite par défaut de 50 (pas une valeur plus petite) : laqueryest une recherche de sous-chaîne ordonnée parupdatedAt, doncissues/<num>correspond aussi aux numéros de problème plus longs (ex. la recherche123correspond à1234) et le ticket exact peut être n'importe où dans l'ensemble de résultats — une limite serrée le laisserait silencieusement tomber. Si 50 résultats arrivent au complet, pagine aveccursorjusqu'à ce que la correspondance exacte soit trouvée ou les résultats épuisés. - Collecte les ID de tickets correspondants (ex.
GHC-1234, ou là où ils ont été routés depuis —NODE-5678,CAT-3338). Inclus aussi les tickets annulés/dupliqués — le commentaire est toujours utile pour la traçabilité.
Produis le résultat sous relatedIssueTickets en JSON. Lors de l'action assign, la référence croisée est affichée dans les deux sens pour que les deux extrémités portent le lien :
- Sur chaque ticket de problème associé — « FYI, community PR #<pr> claims to fix the issue tracked here; routed to <team> as <linearTicket>. »
- Sur le ticket propre de la PR (
linearTicket), quand il est non-null — une note pointant vers chaque ticket de problème associé.
S'il n'y a pas de références Fixes/Closes/Resolves, retourne relatedIssueTickets: [].
Étape 6 — Sortie JSON
{
"readyForReview": <true if all passing checks allow merge, false otherwise>,
"messageForUser": "<Short message to the contributor listing what they need to address. 'N/A' if ready.>",
"team": "<Linear team name (from reference/teams.md), or 'Engineering' as fallback>",
"linearTicket": "<GHC-XXXX or null>",
"relatedIssueTickets": [<"GHC-1234" | "NODE-5678" | ...>],
"checks": {
"AutoReject": <"typo-only" | "new-node" | null>,
"CLA": <bool>,
"Title": <bool>,
"Description": <bool>,
"TestsNeeded": <bool>,
"TestsIncluded": <bool>,
"CubicIssues": <true if unresolved cubic issues exist, false otherwise>
}
}
readyForReview est true seulement quand : AutoReject est null ; CLA, Title et Description sont tous true ; CubicIssues est false ; et soit TestsNeeded est false soit TestsIncluded est true. Si AutoReject est défini, readyForReview est toujours false.
Produis le JSON en premier, puis prends le chemin d'action approprié ci-dessous.
Étape 7 — Chemins d'action
Demande à l'utilisateur pour chaque prompt (présentés comme les options listées). Les sous-agents appelés pour analyse uniquement doivent s'arrêter après l'étape 6 et laisser l'appelant conduire l'étape 7.
A — Correction de titre mineur
Un problème de titre est mineur s'il peut être réparé par une transformation déterministe :
- Espace blanc au début ou à la fin.
- Première lettre du résumé dans la mauvaise casse.
- Point final.
- Casse mixte
revert:nécessitant minuscules (aucun changement requis, juste signaler).
Si le seul contrôle échouant est Title (ou Title + CubicIssues) et le problème est mineur, propose la correction et demande Apply proposed / Edit before applying / Skip. Applique avec :
gh pr edit <number> --repo n8n-io/n8n --title "<new title>"
Puis réévalue Title (maintenant approuvé) et continue vers B ou C. Les problèmes de titre non mineurs (type faux/manquant, pas de deux-points, portée avec trait d'union) ont besoin d'une entrée du contributeur — ignore A et va à C.
B — Triage à l'équipe (readyForReview === true)
Demande : « La PR est prête pour examen. Assigner le ticket Linear <linearTicket> à l'équipe <team> et déplacer vers <destination state>? » Options : Yes, assign and triage / No, leave as-is.
État de destination : Review pour NODES, Triage pour chaque autre équipe. Composition des étiquettes : voir reference/teams.md.
Sur Yes :
# 1. Linear — appelle l'outil MCP Linear disponible avec :
# id = linearTicket
# team = <team>
# state = <destination>
# labels = <computed labels>
# 2. GitHub (seulement si Linear a réussi) — voir reference/label-flow.md
gh pr edit <number> --repo n8n-io/n8n \
--remove-label "triage:in-progress" \
--remove-label "status:pending-assignment" \
--add-label "team:<slug>" \
--add-label "status:team-assigned" \
--add-label "triage:complete"
Si linearTicket est null, demande s'il faut créer un nouveau ticket Linear avant de trier (PRs plus anciennes antérieures à n8n-assistant). Sinon ignore B et demande à l'utilisateur.
C — Poster un commentaire contributeur (readyForReview === false, pas de rejet automatique)
Affiche messageForUser et demande Post as-is / Edit before posting / Skip. Sur post :
gh pr comment <number> --repo n8n-io/n8n --body "<final message>"
Puis applique le bon libellé de triage terminal — exactement un, priorité triage:tests-needed > triage:needs-info. Voir reference/label-flow.md. Sur Skip, laisse la PR sur triage:in-progress pour que la boucle suivante la reprenne.
Ignore C entièrement si A a déjà géré le seul contrôle échouant et la PR est maintenant prête — lance B à la place.
D — Fermer la PR
Utilisé quand la PR doit être fermée plutôt que révisée. Trois déclencheurs courants :
- Rejet automatique (
AutoRejectdéfini) — correction de typo uniquement ou nouveau nœud non autorisé. - Doublon — une autre PR ouverte traite le même changement.
- Hors portée / groupé — plusieurs corrections sans rapport qui doivent être séparées, ou portée que l'équipe n8n a déclinée.
Demande Close + comment / Edit before closing / Skip. Modèles ci-dessous ; en sélectionne un et adapte au contributeur et aux spécificités.
Correction de typo uniquement :
Merci d'avoir consacré du temps à cela ! Selon notre guide de contribution, nous n'acceptons pas les PR qui ne corrigent que des typos — elles créent une surcharge d'examen sans changer les fonctionnalités, et nos règles de correcteur orthographique couvrent la plupart des cas automatiquement. Fermeture pour maintenant ; n'hésite pas à ouvrir une PR qui associe une correction de typo à un changement de logique connexe. 🙏
Nouveau nœud :
Merci pour la contribution ! n8n n'accepte plus les nouveaux nœuds directement dans le monorepo central, sauf si l'équipe a explicitement accepté d'en inclure un dans la portée. Publie ceci comme un nœud communautaire à la place — cela te donne la pleine propriété et évite la longue queue d'examen ici. Fermeture de cette PR selon notre guide de contribution.
Doublon d'une autre PR :
Merci pour la contribution ! Ce changement est déjà traité dans #<other-pr>, qui est plus avancé dans l'examen. Fermeture de ceci au profit de cette PR pour garder la queue nette — n'hésite pas à commenter là-bas s'il manque quelque chose.
Groupé / hors portée :
Merci pour la contribution ! Selon notre guide de contribution, nous demandons un changement ciblé par PR. Cette PR regroupe <N> corrections sans rapport — rouvre-les sous forme de PR séparées et ciblées, chacune avec le modèle rempli et un test unitaire qui verrouille la régression. Fermeture de celle-ci en attendant. 🙏
Action de fermeture (même pour chaque raison) :
gh pr comment <number> --repo n8n-io/n8n --body "<final message>"
gh pr close <number> --repo n8n-io/n8n
gh pr edit <number> --repo n8n-io/n8n \
--remove-label "triage:in-progress" \
--remove-label "status:pending-assignment" \
--add-label "status:internal-closed" \
--add-label "triage:complete"
Si linearTicket est défini, annule-le aussi avec l'outil MCP Linear disponible (id=linearTicket, state="Canceled"). Si gh pr close rapporte que la PR est déjà fermée (le contributeur t'a devancé), procède quand même avec le commentaire, les étiquettes et l'annulation du ticket.
Notes
- PR en brouillon — rapporte tous les résultats mais note que la PR est en brouillon.
- Déjà fusionnée ou fermée — indique-le et ignore les contrôles (n'applique pas les étiquettes de triage).
- Réexamen d'une PR sur laquelle tu as déjà commenté — utilise l'API GitHub Timeline pour détecter l'activité contributeur depuis le dernier toucher de compétence. Voir
reference/re-review.md. - Machine à états d'étiquette — un seul libellé
triage:<state>à la fois ; transitions documentées dansreference/label-flow.md.