ADR 0276 — A PR declara de que PR de outro repo depende, e um check do App espera o merge
- Status: aceito (o check nasce informativo; a exigência em
devemainentra depois das provas, ver a Decisão) - Data: 2026-11-07
- Tema:
git - Referencia: usa a regra de checks obrigatórios do ADR 0255, o job
anunciardo ADR 0271, que já atualiza um check-run pelo App, e a trava de SHAs do ADR 0274, que cuida dos gerados e deixa a ordem de merge sem regra. AT-787, Rodada 244.
Contexto
A dev do brabo-infra ficou vermelha entre os merges da brabo-api#56 e da brabo-infra#26 (AT-774): o spec do infra lê a dev dos irmãos, e a ordem dos merges não estava escrita em lugar nenhum. A promoção dev → main também tem ordem (ci, contracts, componentes, infra, qa e por último o brabo), e essa ordem vivia só na cabeça de quem promovia.
O GitHub não tem dependência entre repositórios. A merge queue é de um repo só, e "linked issues" não segura merge. Os checks exigidos hoje são só Política de branches e Escada de aprovação (ADR 0255), e nenhum deles olha outro repo.
O levantamento de 07/11 (AT-787) mediu o que existe: o App viralabs-dev-brabo está instalado em all, com checks:read e sem checks:write. Escrever check em outro repo exige esse checks: write, o mesmo gesto do dono que bloqueia a AT-765. Os 11 repositórios brabo* são públicos, então qualquer token autenticado lê a PR de outro repo.
Decisão
-
A declaração é uma linha no corpo da PR. Uma linha por dependência, em qualquer lugar do corpo, com ou sem
-na frente:Depende-de: viralabs-dev/brabo-api#56A regex casa linha por linha, sem flag
i. Validação, sempre com motivo:- repo fora da allowlist (os 11
brabo*do mapa da pasta-mãe, constante no script e testada contra oREPOSdoclonar-tudo.sh); - owner diferente de
viralabs-dev; - autorreferência (a própria PR);
- PR inexistente (404);
- linha que parece declaração (
Depende-deoudepende de) mas não casa a regex. Assim um erro de digitação não passa calado.
O corpo é texto de terceiro: entra por
env, nunca interpolado emrun:, como nopr-police. - repo fora da allowlist (os 11
-
O check
Dependências de mergeé publicado pelo App nohead_shada PR. Ele mora num reutilizável novo dobrabo-ci,dependencias-de-merge.yml, chamado por umdependencias.ymlem cada um dos 11 repos, com os gatilhospull_request(opened,edited,reopened,synchronize,closed) esecrets: BRABO_APP_*. Não é um passo dopr-police, por três motivos: opr-policeé exigido e não pode ficar vermelho por uma espera legítima; opolitica.ymlnão passa secrets; e o eventoclosednão pode rodar a política e a escada em toda PR fechada. O job em si nunca reprova (continue-on-error). O nome é o do check-run, não o do job.Estados de cada dependência, e do check:
- sem linha
Depende-de:success"Sem dependências declaradas", publicado sempre, para não deixar check velho colado; - alguma
OPEN(rascunho ou não):in_progress, o amarelo, com o títuloesperando viralabs-dev/<repo>#<n>(as que faltam, separadas por vírgula) e uma tabela no summary; - todas
MERGED:success"Dependências mergeadas", com o link de cada uma; CLOSEDsem merge:failurecom a mensagem "a dependência foi fechada sem merge: tire a linha ou aponte a PR que a substituiu". Não espera para sempre;- inválida, ciclo ou 404:
failurecom o motivo.
neutralnão entra em nenhum caso. Para ruleset,neutralconta como verde, e a espera passaria. - sem linha
-
Ciclo. O script segue as linhas
Depende-dedas dependências abertas até a profundidade 5. Se volta à PR avaliada, reprova com o caminho inteiro (A → B → A) e os links. Profundidade estourada também reprova. -
Re-check quando a dependência é mergeada. O evento
pull_request: closedcommergedroda no repo DONO da dependência (jobavisar-dependentes): busca as PRs abertas que citam a PR mergeada (search/issues?q=org:viralabs-dev is:pr is:open in:body "viralabs-dev/<repo>#<n>"), reparseia o corpo de cada uma, e atualiza o check delas com o token do App. A busca é difusa, por isso o reparse é obrigatório. Escolhido sobre orepository_dispatch, que exigiria um ouvinte em cada repo econtents:writeno destino. Além disso, um cron de hora em hora nobrabo-civarre as PRs abertas comDepende-de, como rede para o merge perdido quando o run do dono quebra. Oschedulesó roda da branch padrão, então o cron liga quando obrabo-cichegar àmain. -
Exigido em
devemain(decisão do dono, 07/11/2026). O check entra no ruleset como obrigatório nas duas branches, mas só depois das provas (P1 a P6 da AT-787, com prints em16-quality/prints/) e com o App já comchecks: write. Ligar antes disso travaria toda PR sem o check. Até lá, ele é informativo: aparece amarelo na PR e o vigia já o lista como não verde. Quem liga é o dono, no ruleset, e a ligação fica registrada emrulesets.md. -
Risco aceito e como destravar. Com o check exigido, há quatro maneiras de travar uma PR:
- ciclo e dependência fechada sem merge: destravam editando o corpo (tirar ou corrigir a linha). Não pedem bypass;
- App sem
checks: writeou PR de fork (fork não recebe secrets, então não publica check): nenhuma edição destrava. O destrave é o bypass do ruleset, por pessoa e com registro, ou a correção do App.
Esse é o risco que o dono aceitou ao exigir o check.
-
Promoção com
Depende-deautomático: fase 2, na AT-788. Opromoteabriria a PR de promoção com uma linha por PR de promoção aberta dos predecessores, na ordem ci → contracts → (api, engine, web, runner, broker) → infra → qa → brabo. Fica fora desta decisão porque tem um furo: se a promoção do predecessor ainda não foi aberta, não há número para citar, e a PR passaria. Fechar o furo pede outra regra ("amaindo predecessor contém adevdele"), que é outro check.
Consequências
- A ordem de merge fica escrita na PR, legível por quem merge e por quem vigia, e não depende de memória.
- Dependência resolvida atualiza a PR dependente em segundos, sem push. O cron cobre o caso do run perdido.
- Custo: um run curto por merge de PR com dependentes, e a varredura horária no
brabo-ci. Os repos são públicos, então não há custo de minutos. - Um check
in_progresshá mais de 14 dias virastale, estaletambém não é verde. A espera longa precisa de quem a leia, não de um timeout. - Nenhuma Action de terceiros:
z0al/dependent-issuesegregsdennis/dependencies-actionnão atualizam a PR dependente no merge, não conhecem o formato em pt-BR nem a allowlist, e exigiriam pin por SHA e permissão de escrita de terceiros. A lógica é nossa, em TypeScript com teste, no molde deqa-e2e-disparar.ts. - Para depois: a fase 2 da promoção (AT-788), e a decisão de tornar o cron de hora em hora permanente quando o
brabo-ciestiver namain.