Skip to content
Apothem
Runbooks

Cerimônia de merge de PR para mantenedor solo

Quando o mantenedor pode fazer o merge do próprio pull request diretamente, e a cerimônia para uma proteção de branch que exige uma aprovação e a impõe aos administradores.

Referência canônica para o auto-merge de PRs sob a proteção de branch do projeto. A proteção ativa em main exige 0 revisões de aprovação e deixa enforce_admins desativado, conforme registrado na página Proteção de branches. Por isso, o mantenedor faz o merge do próprio pull request diretamente. A cerimônia de alternância temporária desta página se aplica somente quando a proteção exige uma aprovação e a impõe aos administradores.


1. O impasse

A proteção ativa de main carrega:

  • required_pull_request_reviews.required_approving_review_count: 0
  • enforce_admins: false

Com essas configurações, não há impasse. Um pull request do mantenedor é mesclado com gh pr merge <pr-number> --squash --delete-branch assim que suas verificações de status obrigatórias estiverem verdes e suas conversas de revisão estiverem resolvidas.

Um impasse existe somente quando a proteção carrega ambas as configurações mais rígidas a seguir:

  • required_pull_request_reviews.required_approving_review_count: 1
  • enforce_admins: true

Essas regras são corretas para cenários com vários mantenedores (toda mudança chega a main por meio de um PR revisado por pares; os administradores não ficam isentos). Elas produzem um impasse para mantenedores solo: a política do GitHub não permite a autoaprovação de um PR de sua autoria, e enforce_admins=true bloqueia a sobreposição gh pr merge --admin do requisito de aprovação de revisão. Com enforce_admins: false, --admin contorna o requisito de aprovação e nenhuma alternância é necessária, mas também contorna verificações obrigatórias em vermelho, então confirme que elas estão verdes antes de usá-lo.

Existem três caminhos de resolução:

CaminhoQuando usar
Definir permanentemente required_approving_review_count: 0 (configuração ativa)Adote somente se o repositório for permanecer com mantenedor solo indefinidamente; reverte a intenção de revisão da proteção
Cerimônia de alternância temporáriaAuto-merges de mantenedor solo enquanto a proteção exige uma aprovação com enforce_admins=true; preserva o invariante de proteção fora da janela de merge
Provisionar uma identidade de bot de CI com acesso de escritaAdote somente se a integração de vários mantenedores for iminente; a aprovação por bot enfraquece a intenção de revisão humana da proteção

Este repositório usa atualmente o caminho de zero aprovação permanente. A cerimônia de alternância temporária é o caminho canônico sempre que a proteção exige uma aprovação e a impõe aos administradores.

2. A cerimônia de alternância temporária

O invariante da cerimônia: o estado da proteção no início da cerimônia é igual ao estado da proteção no fim. A flexibilização existe somente dentro da janela de merge.

Forma manual:

# 1. Open the PR, push branch, wait for CI green.
gh pr create --base main --head <feature-branch> --title "..." --body "..."
gh pr checks <pr-number>            # poll until all green

# 2. Relax approver-count to 0.
gh api repos/<owner>/<repo>/branches/main/protection/required_pull_request_reviews \
    -X PATCH -F required_approving_review_count=0

# 3. Squash-merge with admin override (admin override now succeeds because the
#    review-approval requirement is the only block enforce_admins refuses).
gh pr merge <pr-number> --squash --delete-branch --admin

# 4. Restore approver-count to 1.
gh api repos/<owner>/<repo>/branches/main/protection/required_pull_request_reviews \
    -X PATCH -F required_approving_review_count=1

Forma encapsulada: consulte scripts/dev/admin_merge.py para ver o wrapper atômico em Python que executa os passos 2 → 3 → 4 em uma única sequência não interativa, com segurança de rollback via try / finally caso o passo 3 falhe.

python scripts/dev/admin_merge.py <pr-number>

3. Invariantes

  • Janela de alternância minimizada. Os passos 2 → 3 → 4 são executados em uma única sequência não interativa. A proteção fica em seu estado flexibilizado somente pela duração da chamada à API de merge — menos de um segundo em toda execução observada.
  • A restauração é incondicional. O passo 4 é executado mesmo quando o passo 3 falha (a cláusula try / finally do wrapper garante a restauração em qualquer caminho de saída). Uma tentativa de merge malsucedida não deixa a proteção flexibilizada.
  • O controle de CI é preservado o tempo todo, enquanto enforce_admins está ativado. required_status_checks não é afetado pela alternância; com enforce_admins: true, o merge ainda exige que os contextos de verificação de status configurados estejam verdes. Com enforce_admins: false, o merge --admin do passo 3 também contorna verificações obrigatórias em vermelho, então não execute a cerimônia nesse estado.
  • Trilha de auditoria visível. A anotação gh pr merge --admin aparece nos metadados de merge do PR; as alternâncias da API de proteção aparecem no log de auditoria do repositório sob a identidade do mantenedor.

4. Quando NÃO usar a cerimônia

Enquanto a proteção exigir 0 revisões de aprovação ou deixar enforce_admins desativado, a cerimônia é desnecessária: faça o merge diretamente, como descreve a seção 1.

A cerimônia é para o auto-merge dos PRs do próprio mantenedor. Quando há um revisor par disponível (um contribuidor com acesso de escrita), o caminho padrão gh pr review --approve + gh pr merge --squash --delete-branch é o correto e a cerimônia é desnecessária.

Se o repositório integrar um segundo mantenedor, aposente a cerimônia: o fluxo padrão de revisão de PR restaura a intenção de revisão humana da proteção sem qualquer alternância.

5. Auditar uma execução passada

Cada invocação da cerimônia deixa registro em três superfícies duráveis que um operador pode inspecionar depois do fato:

  • Os metadados de merge do PR. gh pr view <pr-number> --json mergedBy,mergedAt,mergeCommit retorna o ator do merge, o carimbo de data e hora do merge e o SHA do commit de squash. O ator mergedBy corresponde à identidade do mantenedor que executou o passo 3.
  • O log de auditoria do repositório. gh api /repos/<owner>/<repo>/actions/runs --jq '.workflow_runs[] | select(.event=="push")' correlaciona a execução de CI pós-merge ao commit de merge; o log de auditoria das regras de proteção do repositório (histórico de gh api /repos/<owner>/<repo>/branches/main/protection pela interface Settings → Branches) mostra as alternâncias do passo 2 e do passo 4 delimitando a janela de merge.
  • O histórico git do mantenedor. git log main --first-parent --oneline lista cada commit de squash-merge em main com o número do PR correspondente no assunto do commit (sufixo (#<pr-number>), conforme o padrão de gh pr merge --squash), permitindo ao operador rastrear qualquer incorporação passada de volta ao seu PR e à invocação da cerimônia.

Quando scripts/dev/admin_merge.py é o ponto de entrada, seu log não interativo (stderr) nomeia as três chamadas à API de proteção e a chamada à API de merge, em sequência; canalizar o stderr para tee (2>&1 | tee) captura um fragmento de auditoria por execução sem depender da retenção de logs do lado do GitHub.

On this page