Pipelines e automação
Os pipelines são a metade determinística do Control Center. Um agente decide o que dizer; um pipeline decide o que acontece em seguida, sempre da mesma forma. Um pipeline é um DAG de etapas que podem despachar agentes, executar scripts, ramificar com base em uma condição, distribuir em paralelo por uma coleção e passar dados entre etapas — com persistência, retomável e com o custo contabilizado.
Eles existem por três motivos: encadear um processo repetitivo de várias etapas, coordenar vários agentes em sequência ou em paralelo e reagir a algo que aconteceu sem que houvesse uma pessoa presente.
Modelos e execuções
Seção intitulada “Modelos e execuções”Um modelo (PipelineDefinition) é o DAG declarativo: etapas, entradas
declaradas e configuração. Ele fica no banco de dados do próprio espaço de
trabalho. Uma execução (PipelineRun) é uma instância de execução desse
modelo, que carrega um contêiner de estado mutável, totais de custo e de tokens
e o status de cada etapa.
Um modelo tem muitas execuções. As execuções sobrevivem a uma reinicialização: o motor recarrega as execuções em andamento e as retoma de onde pararam.
Duas salvaguardas fazem a execução inteira falhar de propósito em vez de retomar uma etapa, porque retomar seria pior do que parar:
- Uma etapa que está
suspendedhá mais tempo quesuspendedStepTimeout(24 horas por padrão) está esperando tickets que nunca chegarão a um estado terminal, então ela é marcada como falha para liberar a execução. A isenção éextras['awaitApproval'] == true— esse é o portão de aprovação parcialorchestration.awaitApproval.human.gatenão tem isenção. - Uma etapa declarada com
extras: {'idempotent': false}que estava em andamento quando o servidor parou pode já ter aplicado seu efeito colateral (um squash merge, uma limpeza de worktree). Executá-la de novo poderia aplicar o efeito em duplicidade, então o motor a marca como falha e deixa a nova tentativa para você.
O tipo agenda, o corpo trabalha
Seção intitulada “O tipo agenda, o corpo trabalha”Uma etapa tem duas partes ortogonais, e mantê-las separadas é o que permite que o motor continue pequeno.
O tipo (StepKind) informa ao motor quando uma etapa se torna executável
em relação às suas etapas a montante — isso é a única coisa que o agendador
precisa saber. São seis: trigger, listen, join, router, forEach e
terminal. O corpo (bodyKey) é o trabalho que a etapa realiza depois de
agendada. Os corpos são closures registradas por chave na inicialização do
servidor, então muitas etapas de tipos diferentes podem compartilhar um mesmo
corpo: várias etapas listen executando todas conversation.promptAgent, por
exemplo.
Como a semântica de agendamento vive em seis tipos, o catálogo de comportamentos pode crescer sem que ninguém precise mexer no agendador. Consulte Tipos de etapa de pipeline para ver o catálogo completo de tipos, corpos e sua configuração.
Vale conhecer duas consequências do design de registro antes de escrever um modelo à mão:
- Uma etapa cujo
bodyKeynão está registrado produz um aviso no carregamento do modelo e depois nunca é executada. Nada falha de forma ruidosa em tempo de execução. As etapastriggereterminalsão isentas desse aviso: o gatilho ainda executa o corpopipeline.trigger, que não faz nada, para que as etapas de escuta a jusante sejam disparadas; uma etapaterminalnão tem corpo e é uma sentinela do agendador. - As chaves do mapa
extrasde um nó exigem correspondência exata e, caso contrário, são ignoradas em silêncio. Somenteextras['spaceId']coloca o trabalho de uma etapa de agente em uma conversa existente.extras['mode'](chat/plan/review) é lido no nó que abre a sala (messaging.createSpace, padrãoreview) — uma etapa de agente posterior não pode alterar as permissões de uma conversa à qual entrou. Qualquer outra grafia de qualquer uma das chaves é ignorada.
Estado e fluxo de dados
Seção intitulada “Estado e fluxo de dados”As etapas não chamam umas às outras. Elas leem e gravam em um contêiner de
estado compartilhado da execução: uma etapa lê suas entradas por chave, executa
e grava sua saída de volta sob sua própria outputKey. Um StateReducer mescla
gravações simultâneas quando ramos paralelos miram a mesma chave, e um
TemplateRenderer substitui os marcadores {{...}} em prompts e scripts a
partir desse mesmo estado.
É por isso que um pipeline pode ser inspecionado depois do ocorrido — o contêiner de estado é toda a história da execução.
O que inicia uma execução
Seção intitulada “O que inicia uma execução”As linhas de PipelineTrigger declaram quando um modelo é iniciado
automaticamente. Há quatro tipos:
| Gatilho | Inicia uma execução quando |
|---|---|
| Evento de domínio | Um evento de domínio correspondente é disparado — por exemplo PullRequestPublished ou TicketAssigned |
| Agendamento | Uma expressão cron/intervalo vence |
| Manual | Você o executa à mão; a presença de um gatilho manual habilitado é o que coloca o modelo no seletor de execuções |
| Webhook | Um sistema externo faz POST em /webhooks/<token> na porta HTTP do servidor |
Os gatilhos de evento formam um conjunto fechado: 16 tipos de evento são
conhecidos pelo despachante e oferecidos no seletor
(EventPayloadMapper.knownEventTypes), e nada mais pode iniciar um pipeline.
Quatorze desses 16 têm mapeamento de payload. Dois — TicketCreated e
TicketStatusChanged — não têm nenhum, então um gatilho sobre qualquer um deles
fica habilitado e nunca dispara. Consulte
Eventos de domínio para ver a
lista completa.
O token do webhook também funciona como o segredo HMAC: o cabeçalho
X-Hub-Signature-256: sha256=<hex> da requisição é verificado com
HMAC-SHA256(body, token), entregas não verificadas são rejeitadas e não podem
ser reproduzidas, e as duplicatas são descartadas por dedupe_key. Como as
linhas de gatilho são únicas em (espaço de trabalho, tipo de evento, modelo), um
modelo pode ter no máximo um gatilho de webhook e um gatilho por tipo de evento
de domínio.
Os modelos integrados semeiam seus gatilhos manuais e de evento habilitados; os gatilhos agendados são semeados desabilitados, então uma varredura recorrente é sempre opcional.
Os modelos que vêm desabilitados
Seção intitulada “Os modelos que vêm desabilitados”Treze modelos de pipeline são semeados em cada espaço de trabalho e oito deles
vêm desabilitados: external_pr_welcome, cross_review, ticket_to_pr,
pr_triage, pre_merge_gate, release_notes, dep_audit e pr_digest.
É esta a parte que surpreende as pessoas. Seus gatilhos são semeados
habilitados, mas PipelineEngine.start recusa um modelo desabilitado e
retorna null — então o gatilho dispara no vazio e nenhuma execução aparece. O
interruptor é o modelo, não o gatilho. Habilite-o em
Configurações → Espaço de trabalho → Modelos de pipeline antes de esperar que
qualquer um desses oito faça alguma coisa.
Semear novamente um espaço de trabalho preserva o que você escolheu: sua
configuração isEnabled e suas linhas de gatilho existentes sobrevivem. Há
exatamente uma exceção deliberada — o agendamento diário do pr_merged_cleanup
é habilitado à força mesmo que estivesse desativado antes, porque se trata de
coleta de lixo. Linhas de worktree, partições do grafo de código e cópias
copy-on-write se acumulam sem ele, e isso nunca foi pensado para ser uma escolha
do usuário.
Mais uma assimetria que vale conhecer: o modelo integrado pr_review
deliberadamente não publica mais no GitHub. Publicar uma revisão é uma etapa
separada, sujeita à aprovação do usuário, e um pipeline que publicasse
diretamente publicaria em duplicidade. Já cross_review, ticket_to_pr e
pr_triage continuam publicando um comentário diretamente no GitHub quando são
executados.
O que o motor sabe
Seção intitulada “O que o motor sabe”O PipelineEngine cria o registro da execução, agenda o nó inicial que
corresponde ao tipo de evento da execução e então percorre o DAG: conforme as
etapas são concluídas, ele avalia os gatilhos a jusante, resolve os ramos do
roteador, espera nas junções, aplica políticas de nova tentativa e
continue-on-fail, e persiste estado, custo e erros em cada etapa. As arestas que
saem de outro início são ignoradas nessa execução, então um disparo por
agendamento não espera por uma condição exclusiva do modo manual.
O que ele não sabe é nada sobre tickets, despacho, GitHub ou mensagens. Seu
único ponto de extensão é o PipelineBodyRegistry. Os corpos registrados ali
são o que contém AgentDispatchPort, MessagingPort e seus semelhantes — e é
por isso que adicionar uma capacidade aos pipelines nunca significa mudar o
agendador.
Tratamento de erros
Seção intitulada “Tratamento de erros”Uma etapa que falha registra sua mensagem de erro e passa para failed. Se a
etapa declarar continueOnFail, as etapas a jusante prosseguem e o erro é
guardado no estado da execução; caso contrário, a execução falha. Uma etapa com
uma StepRetryPolicy é repetida primeiro, com espera linear ou exponencial,
antes que qualquer um dos dois casos se aplique.
Veja também
Seção intitulada “Veja também”- Eventos de domínio: a que um gatilho de evento escuta
- Orquestração: um plano que você aprova, compilado em um destes pipelines
- Tickets e delegação: o que as etapas de pipeline criam e concluem
- Tipos de etapa de pipeline: o catálogo completo de tipos, corpos e configuração
- Crie seu primeiro pipeline
- Criar um modelo de pipeline
- Executar um pipeline manualmente
- Monitorar execuções de pipeline
- Configurar gatilhos de pipeline