Required reviews: políticas de aprovação para merges

1. Fundamentos das Revisões Obrigatórias

1.1 O que são required reviews e seu papel no fluxo de merge

Required reviews são mecanismos de controle que exigem aprovação explícita de um ou mais revisores antes que um pull request (PR) possa ser mesclado ao branch de destino. No contexto do Git, essas revisões atuam como uma barreira de qualidade, garantindo que alterações críticas passem por escrutínio humano antes de integrarem a base de código principal.

O fluxo típico é:

1. Desenvolvedor cria um branch de feature
2. Abre um Pull Request contra o branch principal
3. Revisores designados analisam as mudanças
4. Aprovam ou solicitam alterações
5. Somente após o número mínimo de aprovações, o merge é permitido

1.2 Diferença entre revisão opcional e obrigatória

Existem dois tipos fundamentais de revisão em plataformas que implementam Git (como GitHub, GitLab e Bitbucket):

  • Non-blocking (opcional): Revisores podem comentar e sugerir mudanças, mas o autor do PR pode realizar o merge sem aguardar aprovação. Ideal para projetos informais ou protótipos.
  • Blocking (obrigatória): O merge é bloqueado até que o número mínimo de aprovações seja atingido. Qualquer solicitação de mudança (change request) também bloqueia o merge até ser resolvida.
Exemplo de configuração no GitHub:
- Non-blocking: sem proteção de branch ativada
- Blocking: branch protection rule com "Require a pull request review before merging"

1.3 Integração com proteção de branches

As required reviews são uma camada dentro do sistema de branch protection. Sempre que uma regra de proteção é ativada em um branch (como main ou develop), as revisões obrigatórias se tornam parte das condições que o PR deve satisfazer para ser mesclado.

Regra típica de branch protection:
{
  "required_pull_request_reviews": {
    "required_approving_review_count": 2,
    "dismiss_stale_reviews": true,
    "require_code_owner_reviews": true
  }
}

2. Configuração de Políticas de Aprovação

2.1 Habilitando required reviews nas regras de branch protection

No GitHub, a configuração é feita em Settings > Branches > Add rule. Selecione o padrão de branch (ex: main) e ative "Require a pull request review before merging".

Passos no GitHub CLI:
gh api repos/:owner/:repo/branches/main/protection \
  --method PUT \
  --input - <<< '{
    "required_pull_request_reviews": {
      "required_approving_review_count": 2
    }
  }'

2.2 Definição do número mínimo de aprovações

O número ideal de revisores depende do tamanho da equipe e da criticidade do código. Valores comuns:

  • 1 aprovação: projetos pequenos ou times ágeis
  • 2 aprovações: padrão para projetos de médio porte
  • 3+ aprovações: sistemas críticos (financeiro, saúde, segurança)
Exemplo de política no GitLab (via .gitlab-ci.yml):
merge_requests:
  approvals_before_merge: 2

2.3 Dismiss stale approvals (revogação de aprovações antigas)

Quando novos commits são adicionados a um PR após uma aprovação, as aprovações anteriores podem se tornar obsoletas. A opção "Dismiss stale pull request approvals when new commits are pushed" força revalidação das revisões.

Cenário prático:
1. Revisor A aprova o PR
2. Desenvolvedor adiciona um commit de correção
3. Aprovação de A é automaticamente revogada
4. Revisor A precisa reavaliar e aprovar novamente

3. Tipos de Revisores e Hierarquia de Aprovação

3.1 Revisores individuais vs. equipes

  • Revisores individuais: Pessoas específicas são designadas manualmente ou automaticamente baseadas em regras.
  • Equipes (teams): Qualquer membro de uma equipe designada pode aprovar. Útil para distribuir carga de revisão.
Configuração de equipe como revisor:
GitHub: Settings > Branches > Edit rule > "Require review from Code Owners"
GitLab: Settings > Merge requests > "Approval rules" > Add approval rule

3.2 Code owners: aprovação automática de paths específicos

Arquivos CODEOWNERS definem responsáveis por diretórios ou tipos de arquivo. Qualquer alteração nesses paths exige aprovação dos donos designados.

Exemplo de CODEOWNERS:
# Donos globais
* @equipe-core

# Donos específicos por diretório
/src/api/ @equipe-backend
/docs/ @equipe-docs
*.tf @equipe-infra

3.3 Políticas de "última palavra"

Em projetos com hierarquia definida, o último revisor pode ter poder de veto mesmo após outras aprovações. Isso é implementado via approval rules com ordem obrigatória.

GitLab: Approval rules com "Approve" sequencial:
1. Desenvolvedor sênior (aprovação obrigatória)
2. Tech lead (aprovação final)
3. Merge só ocorre após ambos aprovarem

4. Workflows de Revisão com Múltiplos Aprovadores

4.1 Estratégias de aprovação sequencial vs. paralela

  • Sequencial: Cada revisor aprova em ordem específica. Útil para validação em cascata (ex: QA depois de dev).
  • Paralela: Todos os revisores aprovam independentemente. Mais rápido, mas sem hierarquia.
Fluxo sequencial:
1. Revisor A (arquitetura) aprova
2. Revisor B (segurança) aprova
3. Merge liberado

Fluxo paralelo:
1. Revisor A e B aprovam simultaneamente
2. Quando ambos aprovarem, merge liberado

4.2 Uso de revisões de segurança (security review gates)

Gates de segurança podem ser integrados como revisores obrigatórios para PRs que alteram código sensível (autenticação, criptografia, dados pessoais).

Regra de aprovação para segurança:
- Paths: /src/auth/**, /src/encryption/**
- Revisores obrigatórios: @equipe-seguranca
- Número mínimo: 1 aprovação de segurança

4.3 Combinação com status checks: integração CI + revisão humana

Required reviews funcionam em conjunto com checks automatizados. O merge só é permitido quando ambos passam:

Condições para merge:
1. ✅ CI/CD pipeline passou (status check)
2. ✅ Pelo menos 2 revisões humanas aprovadas
3. ✅ Code owners aprovaram (se aplicável)
4. ✅ Nenhum change request pendente

5. Exceções e Bypass de Revisões Obrigatórias

5.1 Configuração de bypass para administradores e roles específicos

Em situações de emergência, administradores podem ser autorizados a ignorar revisões. No GitHub, isso é controlado pela opção "Include administrators" nas regras de proteção.

Configuração de bypass:
- Administradores: podem fazer push direto (se "Allow force pushes" ativado)
- Roles específicos: "Bypass pull request requirements" em settings organizacionais

5.2 Push bypass vs. merge bypass: diferenças e riscos

  • Push bypass: Permite commits diretos ao branch protegido sem PR. Alto risco, deve ser desabilitado em produção.
  • Merge bypass: Permite merge de PR sem aprovações. Menos arriscado, mas ainda deve ser auditado.
Riscos:
- Push bypass: possibilidade de introduzir código sem revisão
- Merge bypass: possibilidade de ignorar revisões mesmo com PR aberto

5.3 Auditoria de bypasses: como rastrear exceções no audit log

Plataformas como GitHub e GitLab mantêm logs de auditoria. Para rastrear bypasses:

GitHub Audit Log API:
GET /orgs/:org/audit-log?include=git&action=protected_branch.bypass

Exemplo de entrada:
{
  "action": "protected_branch.bypass",
  "actor": "admin-user",
  "repo": "projeto-critical",
  "timestamp": "2024-01-15T10:30:00Z"
}

6. Boas Práticas e Troubleshooting

6.1 Evitando gargalos: balance entre número de revisores e produtividade

  • Para equipes de até 5 pessoas: 1-2 revisores
  • Para equipes de 6-15 pessoas: 2-3 revisores
  • Acima disso: revisão por amostragem ou times especializados
Métrica recomendada:
- Tempo médio de revisão < 4 horas
- Taxa de aprovação > 80% na primeira rodada
- Número de revisores = sqrt(tamanho da equipe)

6.2 Lidando com conflitos entre revisores

Quando revisores discordam, a política "disagree and commit" pode ser aplicada:

Procedimento:
1. Revisor A solicita mudanças
2. Revisor B discorda, mas aprova
3. Tech lead media: se não houver consenso, a decisão do tech lead prevalece
4. Merge liberado com nota no PR sobre a divergência

6.3 Cenários comuns: revisões que nunca chegam, timeouts e stale PRs

Para evitar PRs abandonados:

Políticas de timeout:
- Após 48h sem revisão: notificação automática ao revisor
- Após 72h: escalonamento para tech lead
- Após 5 dias: PR marcado como stale e fechado automaticamente

GitHub Actions para stale PRs:
name: Stale PR Check
on:
  schedule:
    - cron: '0 0 * * *'
jobs:
  stale:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/stale@v9
        with:
          days-before-stale: 5
          stale-pr-message: 'Este PR está parado. Solicite revisão novamente.'

Referências