AUR-439 — Bloquear o merge quando o review reprova
Documento histórico do board. Pode descrever componentes removidos; para uso atual, consulte o guia do produto.
O que este card entrega
Uma nova flag no caminho de pull request de aurumcode review:
aurumcode review --pr <numero> --repo <dono>/<projeto> --publicar --check
Depois de publicar cada achado como comentario no pull request (o
comportamento que o AUR-438 ja entrega, inalterado), publica um commit
status no commit de topo do pull request atraves do cliente GitHub
restaurado (AUR-437, internal/git/githubclient.SetStatus):
"failure" quando pelo menos um achado e grave (severidade error, o
mesmo patamar que --fail-on high|error ja nomeia), "success" caso
contrario. Uma regra de branch protection que exige esse check bloqueia o
merge do pull request ate a correcao.
Este card e fiacao, nao reescrita: SetStatus ja existe, ja esta provado
(internal/git/githubclient/client_test.go) e ja e fail-closed em
permissao de escrita (requireWritePermission, a mesma garantia que
PostReviewComment/PostIssueComment ja usam). O que falta, e o que este
card adiciona, e inteiramente em cmd/aurumcode/pr.go: a flag --check, a
classificacao "grave" (reaproveitando severityRank/countAtOrAbove de
cmd/aurumcode/main.go -- nenhuma segunda escala de severidade), e a
funcao publishCheckStatus que monta e publica o githubclient.CommitStatus.
Flags
--check: opcional (booleano). Publica o commit status descrito acima. Com--pr, satisfaz sozinha a exigencia que--na-linhanormalmente impoe -- o comando declarado por este card (review --pr N --repo o/r --publicar --check) nao leva--na-linha, e--checknomeia seu proprio comportamento com a mesma clareza que--na-linhanomeia o dela. Sem--checke sem--na-linha, o caminho de PR continua recusando exatamente como antes (aurumcode review: --na-linha is required with --pr, exit2) -- nada nesse contrato pre-existente muda.--repoe--publicarcontinuam obrigatorios com--pr, com ou sem--check, exatamente como o AUR-438 ja exige.--checknao substitui nem suprime a publicacao de comentarios que--publicarja exige: os dois convivem na mesma execucao -- cada achado ainda vira comentario inline ou geral no pull request (AUR-438, inalterado), e o commit status e publicado depois, como um efeito adicional, nunca no lugar dos comentarios.
O que conta como "grave"
Um achado e grave quando sua severidade e error -- o rank mais alto que
o motor de review ja usa (internal/prompt's vocabulary: error,
warning, info), o mesmo rank que --fail-on high|error ja nomeia no
caminho --base. publishCheckStatus conta os achados grave com
countAtOrAbove(issues, rankError), a mesma funcao que --fail-on ja usa
em cmd/aurumcode/main.go -- nao existe uma segunda nocao de "grave" só
para o --check.
O commit status publicado
githubclient.CommitStatus{
Context: "aurumcode/review",
State: "failure" | "success",
Description: "<N> achado(s) grave(s) no pull request #<numero>" |
"nenhum achado grave no pull request #<numero>",
}
Context e contrato publico: uma regra de branch protection identifica
qual check e obrigatorio pelo context exato, entao renomea-lo em uma
versao futura des-bloquearia silenciosamente todo merge que dependia dele
em vez de continuar bloqueando. "aurumcode/review" e o valor fixo que
este card publica e testa (tests/unit/AUR-439.go,
tests/integration/AUR-439.go).
Zero achados ainda publica "success": um commit que corrigiu todo achado
grave de uma execucao anterior precisa que o check anterior seja limpo, ou
o merge continua bloqueado para sempre por um status que nunca mais e
atualizado. "No issues found." continua imprimindo exatamente como
antes; o commit status e adicional, nao um substituto.
O SHA do commit: a mesma recusa fail-closed, agora tambem por --check
SetStatus publica em /repos/{owner}/{repo}/statuses/{sha} -- nao ha
forma dessa chamada sem um SHA de commit, exatamente como uma chamada
PostReviewComment inline nao existe sem um commit_id (AUR-438). Este
card nao abre um segundo guardiao paralelo para essa exigencia: a mesma
variavel needsCommitID que o AUR-438 ja usa para achados elegiveis a
comentario inline agora tambem comeca em true quando --check foi dado.
O efeito pratico: um review --pr ... --publicar --check sem GITHUB_SHA
recusa antes de qualquer POST -- mesmo quando nenhum achado e elegivel
a comentario inline, mesmo quando nao ha achado nenhum -- com a mesma
mensagem de recusa que o AUR-438 ja publica em stderr
(refusing to publish: an inline comment requires a commit SHA...). A
mensagem e reaproveitada tal como esta, sem alteracao: o contrato
pre-existente sem --check e byte a byte pinado, e mudar o texto so para
--check exigiria dois textos condicionais em vez de um guardiao unico.
tests/integration/AUR-439.go prova especificamente o caso mais estreito:
um achado so-geral (nenhum elegivel a inline) com --check e sem
GITHUB_SHA ainda recusa -- a prova de que --check contribui sua propria
exigencia ao guardiao em vez de depender de carona em um achado inline que
por acaso esteja presente.
Permissao de escrita: herdada, nao contornada
A checagem explicita de HasWritePermission que o AUR-438 ja faz antes de
qualquer trabalho (busca de diff, chamada ao modelo) cobre --check sem
nenhuma mudanca: --check nunca chega a publishCheckStatus quando o
token e so-leitura, porque a funcao inteira ja retornou. E mesmo que
chegasse, SetStatus em si tambem chama requireWritePermission
internamente (o mesmo guardiao fail-closed que PostReviewComment/
PostIssueComment ja usam) -- nao existe um caminho que contorne essa
garantia so porque a chamada e para o endpoint de status em vez de
comentario.
Exit codes
0: os achados foram publicados (ou "No issues found."), sem erro; com--check, o commit status publicado foi"success"(nenhum achado grave).1: falha em tempo de execucao -- inclui agora a falha ao publicar o proprio commit status (uma falha de transporte/API doSetStatus, nao um achado grave).2: erro de uso ----repo/--publicarausentes com--pr,--na-linhaausente quando--checktambem esta ausente,--prnao positivo, ou--repofora do formatodono/projeto.3(exitFindings, o mesmo codigo que--fail-onja usa): com--check, pelo menos um achado grave foi encontrado e o commit status publicado foi"failure". Este codigo nunca pode ser confundido com sucesso -- é exatamente o que MUT-001 prova: uma versao que reportasse sucesso (codigo0, ou um status"success") com um achado grave presente e o defeito que a mutacao introduz e que o aceite precisa pegar.
Uma falha ao publicar um comentario individual e a falha ao publicar o
commit status sao independentes: se um achado falha ao publicar mas o
commit status ainda publica com sucesso (ou vice-versa), o exit code
permanece 1 (a falha de publicacao de comentario tem precedencia sobre o
3 do --check, porque 1 ja significa "algo na publicacao falhou" --
nenhuma das duas causas de falha e silenciada, ambas aparecem em stderr).
Nenhum destes codigos e novo: e o mesmo vocabulario que --base e
--pr ... --na-linha ja usam (docs/specs/AUR-430.md,
docs/specs/AUR-431.md, docs/specs/AUR-438.md).
Exemplo executavel sem segredo
bash tests/e2e/AUR-439.sh E2EAUR439
Compila o binario real, sobe um fake GitHub em loopback a partir de
tests/fixtures/scm/github/ (o diff do PR 42, as permissoes de
leitura-escrita e so-leitura, a resposta de comentario criado) estendido
com o endpoint de status (/repos/dono/projeto/statuses/<sha>, que
responde 422 a um state ausente ou invalido, nunca um mock que
concorda com qualquer corpo), escreve quatro respostas de modelo
deterministicas -- uma com um achado grave (error) mais um achado geral,
uma so com um achado nao-grave (warning), uma sem achado nenhum, e uma
so-geral (para a prova mais estreita do SHA acima) -- e roda
aurumcode review --pr 42 --repo dono/projeto --publicar --check contra
cada uma. Prova: achado grave publica state=failure e um exit code que
nunca e 0; achado so warning publica state=success e exit 0; zero
achados ainda publica state=success; sem GITHUB_SHA o comando recusa
antes de qualquer POST mesmo quando nada e elegivel a inline; um token
so-leitura e recusado antes de qualquer POST; repetir a execucao produz a
mesma saida e o mesmo status publicado; e o contrato pre-existente
(--na-linha no lugar de --check) nunca contata o endpoint de status.
Tokens sao strings sinteticas montadas em tempo de execucao; nenhum shape
de credencial existe em arquivo rastreado.
Selectors e exit codes do aceite
- Aceite:
tests/acceptance/AUR-439.sh-- selectorsAC-001(tudo),TestAUR439,IntegrationAUR439,E2EAUR439,AC-001-MUT-001. - Exit codes (convencao do board,
tests/acceptance/EXIT_CODE_CONVENTION.md):0comportamento provado;1RED comportamental;64selector desconhecido;79infraestrutura / inconclusivo (nunca evidencia de RED).
Diagnostico de falha
AUR-439/AC-001/behavior-missing: o caminho--checknao entrega o fluxo prometido (ver stderr do harness emtests/e2e/AUR-439.sh).grave_wrong_exit: um achado grave nao produziu o exit code3esperado (ou produziu0, o defeito exato que MUT-001 injeta).wrong_state_reported_success: ostatepublicado no commit status foi"success"com um achado grave presente -- o outro rosto do mesmo defeito, visivel no corpo do POST em vez de so no exit code (a licao dos cards irmaos: o discriminador tem que ser ostatepublicado, nao so "nao deu erro").clean_wrong_state/empty_missing_check_line: o caminho sem achado grave nao publicou"success".nosha_not_refused/nosha_post_leaked:--checknao herdou a recusa fail-closed por SHA ausente.readonly_not_refused/readonly_post_leaked:--checknao herdou a recusa fail-closed por falta de permissao de escrita.nocheck_status_leaked/nocheck_check_line_leaked: o contrato pre-existente (--na-linha, sem--check) regrediu -- contatou o endpoint de status ou imprimiu a linha de check quando nao deveria.non_deterministic/non_deterministic_status_count: duas execucoes identicas divergiram na saida ou no status publicado.infrastructure/missing_go,infrastructure/mktemp,infrastructure/fakegithub_did_not_start(exit 79): ambiente, nunca RED.
Compatibility, migration, rollback
- Compatibility:
--baseereview --pr ... --publicar(sem--check) mantem o contrato publicado byte a byte -- toda a logica nova de--checkfica atras deif check { ... }, e o unico ramo pre-existente que muda de posicao (o calculo decommitID/needsCommitID, movido para antes do retorno antecipado de "No issues found.") e um no-op quandocheckefalse:needsCommitIDso passa atrueali pela mesma condicao que ja usava antes (um achado elegivel a inline), entao nenhuma saida observavel muda para quem nunca passa--check. - Migration: not-applicable.
- Rollback: reverter somente os
pathsdeste card; nenhum estado externo (alem do commit status publicado durante um teste real, nunca durante o aceite offline) e afetado.