O kadu.yaml
O que é da organização inteira, e não de uma tarefa, mora num kadu.yaml
opcional na raiz do repositório: ambientes, webhooks e o metadata de
workspaces e atividades. O que é de uma tarefa (agendamento, endpoint,
executor) fica no bloco task:.
As regras que valem para todas as seções
- Posse. A sincronização cria e atualiza o que está declarado e só apaga o que ela mesma criou. O que foi criado no console e aparece no arquivo é atualizado, nunca apagado.
- Seção ausente não toca em nada. Uma lista vazia (
[]) remove só o que o repositório criou. - O arquivo é validado inteiro. YAML quebrado, campo com tipo errado,
chave desconhecida (
colour:,bearer_token:), evento de webhook fora da lista ou item repetido fazem a sincronização não aplicar nada do arquivo, com aviso. Uma seção desconhecida no topo é só aviso, e o resto vale.
O tudo-ou-nada é de propósito: aplicar a metade boa apagaria o item com erro de digitação.
Ambientes
environments:
- label: Produção
color: "#16a34a" # #rrggbb; ausente = cinza (#6b7280) na criação
branch: main # ausente = main na criação
secrets: # só as CHAVES — valor nunca entra no repositório
- KOBANA_ACCESS_TOKEN
- key: FINTERA_TOKEN
notes: token da entidade 34684
- label: Sandbox
color: "#f59e0b"
| Situação | O que a sincronização faz |
|---|---|
| Ambiente declarado que não existe | cria, marcado como do repositório |
| Ambiente declarado que já existe (mesmo nome) | atualiza color e branch, se declarados. O criado no console é adotado para atualização, nunca marcado como do repositório |
Chave em secrets sem valor no ambiente | aviso: a sincronização nunca cria secret |
Chave em secrets com notes | sobrescreve a nota do secret |
| Ambiente do repositório que saiu da lista | apaga, salvo se ainda tiver secret ou agendamento (fica, com aviso) |
| Ambiente do console que saiu da lista | não mexe |
O nome é a chave: renomear um ambiente no arquivo é criar outro. Os agendamentos que apontam para ele precisam mudar no frontmatter no mesmo commit. Para renomear um ambiente que já tem secrets, renomeie no console e depois no arquivo.
Webhooks
webhooks:
- label: Falhas para o PagerDuty # a chave: casado pelo nome
url: https://events.exemplo.com/kadu
events: [execution.failed, organization.cost_limit_reached]
workspace: finance # plugin do escopo; null = organização inteira; ausente = não mexe
auth: header # basic | bearer | header; ausente = bearer na criação
header_key: X-Api-Key # a parte não secreta (no basic: basic_user)
enabled: true # ausente = não mexe (na criação: ativo)
emails: [ops@exemplo.com] # avisados quando o webhook é desativado por falhas
metadata: { dono: sre }
Eventos aceitos: execution.created, execution.queued, execution.started,
execution.completed, execution.failed, execution.cancelled,
todo.created, todo.resolved, organization.cost_limit_reached,
organization.entitlement_required e os <recurso>.db.created|updated|deleted
de task, activity, workspace, execution e memory.
Credencial nunca entra no arquivo. bearer_token, senha do basic ou valor
do header no YAML são chaves desconhecidas e invalidam o arquivo inteiro.
| Situação | O que a sincronização faz |
|---|---|
| Webhook declarado que não existe | cria, marcado como do repositório, sem credencial e com um signing secret que ninguém viu, e avisa |
| Webhook existente (mesmo nome, qualquer origem) | atualiza url, events, emails (ordem não conta), escopo, basic_user/header_key e metadata |
auth diferente do gravado | não troca (apagaria a credencial) e avisa; troque no console |
enabled: true num webhook desativado por falhas | reativa e zera o contador de falhas, a cada sincronização, enquanto declarado |
URL recusada (IP privado, http), workspace inexistente, dois webhooks com o mesmo nome | pula aquele webhook, com aviso, sem apagá-lo |
| Webhook do repositório fora da lista | apaga |
| Webhook do console fora da lista | não mexe |
Depois de criar, faltam dois passos fora do repositório: cadastrar a
credencial em Configurações → Webhooks e gerar o signing secret com
POST /v1/webhooks/{id}/rotate-secret, configurando o novo valor no receptor.
Até lá, a entrega sai sem autenticação e com uma assinatura que o receptor não
consegue conferir.
Workspaces e atividades
workspaces:
- plugin: finance # o plugin = o workspace
metadata: { centro_de_custo: "42" }
activities:
- label: Baixa de Recebimentos # nome exato dentro do workspace
metadata: { sla_horas: 4 }
Só o metadata, que aparece na API v1 e no payload dos webhooks, substituído
inteiro quando declarado. O arquivo não cria workspace nem atividade (eles
nascem das tarefas), então um plugin ou nome que não existe vira aviso.
Ordem de aplicação
Tarefas → ambientes → agendamentos → metadados de workspaces e atividades → webhooks → remoção de ambientes do repositório. Ver Sincronização.