Pipelines et automatisation
Les pipelines sont la moitié déterministe de Control Center. Un agent décide quoi dire ; un pipeline décide ce qui se passe ensuite, toujours de la même façon. Un pipeline est un DAG d’étapes qui peuvent lancer des agents, exécuter des scripts, créer une branche selon une condition, parcourir une collection en parallèle et transmettre des données entre les étapes — avec persistance, reprise possible et suivi des coûts.
Ils existent pour trois raisons : enchaîner un processus répétitif à plusieurs étapes, coordonner plusieurs agents en séquence ou en parallèle et réagir à quelque chose qui s’est produit sans qu’un humain soit présent.
Modèles et exécutions
Section intitulée « Modèles et exécutions »Un modèle (PipelineDefinition) est le DAG déclaratif : étapes, entrées
déclarées et configuration. Il vit dans la base de données propre à l’espace de
travail. Une exécution (PipelineRun) est un passage de ce modèle, qui porte
un conteneur d’état modifiable, les totaux de coût et de jetons ainsi que le
statut de chaque étape.
Un modèle compte de nombreuses exécutions. Les exécutions survivent à un redémarrage : le moteur recharge les exécutions en cours et les reprend là où elles se sont arrêtées.
Deux filets de sécurité font délibérément échouer toute l’exécution plutôt que de reprendre une étape, car reprendre serait pire que s’arrêter :
- Une étape
suspendeddepuis plus longtemps quesuspendedStepTimeout(24 heures par défaut) attend des tickets qui n’atteindront jamais un état terminal : elle est donc mise en échec pour libérer l’exécution. L’exception estextras['awaitApproval'] == true— c’est le portail d’approbation partielleorchestration.awaitApproval.human.gaten’en bénéficie pas. - Une étape déclarée
extras: {'idempotent': false}qui était en cours lorsque le serveur s’est arrêté peut avoir déjà appliqué son effet de bord (un squash merge, un nettoyage d’arbre de travail). La relancer pourrait l’appliquer deux fois : le moteur la met donc en échec et vous laisse décider d’une nouvelle tentative.
Le type ordonnance, le corps travaille
Section intitulée « Le type ordonnance, le corps travaille »Une étape a deux parties orthogonales, et c’est en les gardant séparées que le moteur reste petit.
Le type (StepKind) indique au moteur quand une étape devient exécutable
par rapport à ses étapes amont — c’est la seule chose que l’ordonnanceur ait
besoin de savoir. Il en existe six : trigger, listen, join, router,
forEach et terminal. Le corps (bodyKey) est le travail que l’étape
accomplit une fois ordonnancée. Les corps sont des closures enregistrées par clé
au démarrage du serveur, si bien que de nombreuses étapes de types différents
peuvent partager un même corps : plusieurs étapes listen exécutant toutes
conversation.promptAgent, par exemple.
Comme la sémantique d’ordonnancement tient dans six types, le catalogue des comportements peut s’enrichir sans que personne ne touche à l’ordonnanceur. Voir Étapes de pipeline pour le catalogue complet des types, des corps et de leur configuration.
Deux conséquences de la conception par registre méritent d’être connues avant d’écrire un modèle à la main :
- Une étape dont le
bodyKeyn’est pas enregistré produit un avertissement au chargement du modèle puis ne s’exécute jamais. Rien n’échoue bruyamment à l’exécution. Les étapestriggeretterminalsont exemptées de cet avertissement : le déclencheur exécute quand même le corpspipeline.triggerqui ne fait rien, afin que les écouteurs en aval se déclenchent ; une étapeterminaln’a pas de corps et sert de sentinelle à l’ordonnanceur. - Les clés de la table
extrasd’un nœud sont à correspondance exacte et silencieusement ignorées dans le cas contraire. Seulextras['spaceId']place le travail d’une étape d’agent dans une conversation existante.extras['mode'](chat/plan/review) est lu sur le nœud qui ouvre l’espace (messaging.createSpace,reviewpar défaut) — une étape d’agent ultérieure ne peut pas modifier les permissions d’une conversation qu’elle a rejointe. Toute autre orthographe de l’une ou l’autre clé est ignorée.
État et flux de données
Section intitulée « État et flux de données »Les étapes ne s’appellent pas entre elles. Elles lisent et écrivent dans un
conteneur d’état partagé au niveau de l’exécution : une étape lit ses entrées par
clé, s’exécute et réécrit sa sortie sous sa propre clé outputKey. Un
StateReducer fusionne les écritures concurrentes lorsque des branches parallèles
visent la même clé, et un TemplateRenderer remplace les espaces réservés
{{...}} dans les prompts et les scripts à partir de ce même état.
C’est pourquoi un pipeline est inspectable après coup — le conteneur d’état raconte toute l’exécution.
Ce qui démarre une exécution
Section intitulée « Ce qui démarre une exécution »Les lignes PipelineTrigger déclarent quand un modèle démarre automatiquement.
Il en existe quatre types :
| Déclencheur | Démarre une exécution quand |
|---|---|
| Événement de domaine | Un événement de domaine correspondant se produit — par exemple PullRequestPublished ou TicketAssigned |
| Planification | Une expression cron/intervalle arrive à échéance |
| Manuel | Vous le lancez à la main ; c’est la présence d’un déclencheur manuel activé qui fait figurer le modèle dans le sélecteur d’exécution |
| Webhook | Un système externe envoie une requête POST à /webhooks/<token> sur le port HTTP du serveur |
Les déclencheurs d’événement forment un ensemble fermé : 16 types d’événements
sont connus du répartiteur et proposés dans le sélecteur
(EventPayloadMapper.knownEventTypes), et rien d’autre ne peut démarrer un
pipeline. Quatorze de ces 16 disposent d’une correspondance de charge utile.
Deux — TicketCreated et TicketStatusChanged — n’en ont aucune : un
déclencheur sur l’un ou l’autre reste donc activé sans jamais se déclencher. Voir
Événements de domaine pour la liste complète.
Le jeton du webhook sert aussi de secret HMAC : l’en-tête
X-Hub-Signature-256: sha256=<hex> de la requête est vérifié par rapport à
HMAC-SHA256(body, token), les livraisons non vérifiées sont rejetées et ne
peuvent pas être rejouées, et les doublons sont écartés par dedupe_key. Comme
les lignes de déclencheur sont uniques sur (espace de travail, type d’événement,
modèle), un modèle peut contenir au plus un déclencheur webhook et un déclencheur
par type d’événement de domaine.
Les modèles intégrés sont initialisés avec leurs déclencheurs manuels et d’événement activés ; les déclencheurs planifiés sont initialisés désactivés, si bien qu’un balayage récurrent est toujours à activer explicitement.
Les modèles livrés désactivés
Section intitulée « Les modèles livrés désactivés »Treize modèles de pipeline sont initialisés dans chaque espace de travail et
huit d’entre eux sont livrés désactivés : external_pr_welcome,
cross_review, ticket_to_pr, pr_triage, pre_merge_gate, release_notes,
dep_audit et pr_digest.
C’est le point qui surprend. Leurs déclencheurs sont initialisés activés, mais
PipelineEngine.start refuse un modèle désactivé et renvoie null — le
déclencheur se déclenche donc dans le vide et aucune exécution n’apparaît. C’est
le modèle, et non le déclencheur, qui fait office d’interrupteur. Activez-le
dans Paramètres → Espace de travail → Modèles de pipeline avant d’attendre que
l’un de ces huit fasse quoi que ce soit.
Réinitialiser un espace de travail préserve ce que vous avez choisi : votre
réglage isEnabled et vos lignes de déclencheur existantes sont conservés. Il
existe exactement une exception délibérée — la planification quotidienne de
pr_merged_cleanup est activée de force, même si elle était auparavant
désactivée, car elle fait office de ramasse-miettes. Sans elle, les lignes
d’arbre de travail, les partitions du graphe de code et les copies sur écriture
s’accumulent, et cela n’a jamais été prévu comme un choix de l’utilisateur.
Une autre asymétrie mérite d’être connue : le modèle intégré pr_review ne
publie délibérément plus sur GitHub. Publier une revue est une étape distincte,
soumise à validation par l’utilisateur, et un pipeline qui publierait directement
entraînerait une double publication. cross_review, ticket_to_pr et
pr_triage, eux, publient toujours un commentaire directement sur GitHub
lorsqu’ils s’exécutent.
Ce que le moteur sait
Section intitulée « Ce que le moteur sait »PipelineEngine crée l’enregistrement d’exécution, ordonnance le nœud de départ
correspondant au type d’événement de l’exécution, puis parcourt le DAG : à mesure
que les étapes se terminent, il évalue les déclencheurs en aval, résout les
branches des routeurs, attend les jointures, applique les politiques de nouvelle
tentative et le continue-on-fail, et persiste l’état, le coût et les erreurs à
chaque étape. Les arêtes issues d’un autre point de départ sont ignorées pour
cette exécution : un déclenchement planifié n’attend donc pas une condition
réservée au mode manuel.
Ce qu’il ne connaît pas, c’est tout ce qui touche aux tickets, au lancement
d’agents, à GitHub ou à la messagerie. Son seul point d’extension est le
PipelineBodyRegistry. Ce sont les corps qui y sont enregistrés qui détiennent
AgentDispatchPort, MessagingPort et leurs homologues — c’est pourquoi ajouter
une capacité aux pipelines n’oblige jamais à modifier l’ordonnanceur.
Gestion des erreurs
Section intitulée « Gestion des erreurs »Une étape qui échoue enregistre son message d’erreur et passe à failed. Si
l’étape déclare continueOnFail, les étapes en aval se poursuivent et l’erreur
est rangée dans l’état de l’exécution ; sinon, l’exécution échoue. Une étape
dotée d’une StepRetryPolicy est d’abord relancée, avec un délai d’attente
linéaire ou exponentiel, avant que l’un ou l’autre de ces cas ne s’applique.
Voir aussi
Section intitulée « Voir aussi »- Événements de domaine : ce qu’écoute un déclencheur d’événement
- Orchestration : un plan que vous approuvez, compilé en l’un de ces pipelines
- Tickets et délégation : ce que les étapes de pipeline créent et terminent
- Étapes de pipeline : le catalogue complet des types, des corps et de la configuration
- Créer votre premier pipeline
- Créer un modèle de pipeline
- Exécuter un pipeline manuellement
- Surveiller les exécutions de pipeline
- Configurer des déclencheurs de pipeline