Assistentes de IA mudaram o volume de código que um time produz. Copilot, Cursor e Claude entregam diff pronto em minutos, e a revisão humana segue com a mesma janela de atenção de antes. Quality gate é o mecanismo que mantém o padrão do projeto quando o volume passa do que a revisão alcança.

Assistente não conhece a regra de negócio que só existe no Slack do time, a estrutura de pastas que o projeto adotou, nem a política de sanitização do time de segurança. Código gerado passa no lint, passa no review acelerado, e o defeito aparece em produção semanas depois, longe do diff que o causou.

O que entra num quality gate

Quality gate é critério objetivo que o código precisa satisfazer antes de avançar no pipeline. O manual de quality gates do SonarQube define a condição de cobertura sobre código novo, formato que não castiga o legado. A lista que eu monto para projeto JavaScript e TypeScript:

  • Cobertura de código novo. Piso de 80% nas linhas do diff, sem contar arquivo de teste.
  • Lint e typecheck sem erro. ESLint, PHPStan, Pylint, tsc --noEmit.
  • Análise estática de segurança. Semgrep com ruleset de OWASP ou equivalente. O manual do Semgrep cobre a escrita de regra própria e o uso de ruleset pronto.
  • Vulnerabilidade de dependência. npm audit, Dependabot ou Snyk.
  • Type safety. TypeScript em strict, contagem de any em código novo igual a zero.
  • Complexidade por função. A regra complexity do ESLint em 10 pega a função de IA que embrulha o if dentro do loop dentro do try.
// .eslintrc.json
{
  "rules": {
    "complexity": ["error", 10],
    "max-lines-per-function": ["warn", 50]
  }
}

Três calibrações quando a IA entra no fluxo

Gate que passava com três PRs por semana falha quando a mesma equipe abre quinze. Três ajustes que eu faço quando o time liga o assistente:

1. Cobertura medida no diff

Exigir 80% no projeto inteiro trava o legado e gera resistência. A condição sobre código novo pega o código que a IA acabou de escrever.

# sonar-project.properties
sonar.coverage.exclusions=**/*.test.*
sonar.qualitygate.wait=true
# gate: cobertura em código novo >= 80%

2. Regra curta e específica

Regra Semgrep de dez linhas vale mais que ruleset gigante que ninguém lê. Comece com eval(), innerHTML sem sanitização e query SQL construída por concatenação de string.

# .semgrep.yml
rules:
  - id: no-eval
    pattern: eval(...)
    message: "eval() detectado: risco de injeção de código"
    severity: ERROR

3. Gate que bloqueia o merge

qualitygate.wait=true no scan do SonarQube faz o job falhar quando a condição não passa, e a proteção de branch exige o job verde antes do merge. Gate que só comenta em alerta some em duas semanas de uso intenso.

- name: SonarQube Scan
  uses: SonarSource/sonarqube-scan-action@master
  env:
    SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
  with:
    args: >
      -Dsonar.qualitygate.wait=true

O que o gate libera

Gate bloqueiro muda o contrato do time com o assistente. PR gerado por IA passa pelo mesmo fluxo de aprovação de PR humano, com o compilador e o analisador respondendo antes do revisor. Juniors que usam assistente recebem o mesmo retorno de padrão que seniors, porque o gate não distingue quem escreveu.

Time que mede o tempo de ciclo do PR descobre que gate rápido (lint, typecheck, teste unitário) segura retrabalho logo no primeiro minuto de CI, e gate lento (scan completo, E2E) pode rodar só na main ou no PR grande. Com isso, o assistente opera no ritmo dele e o padrão do projeto sobrevive ao volume.