CI/CD sem madrugadas de deploy: o que muda com automação de verdade

Deploys na madrugada são sintoma, não destino. Veja como automação, testes confiáveis e entrega progressiva eliminam o risco do go-live.

Se a sua equipe ainda agenda deploys para a madrugada de sábado, o problema não é o horário — é a falta de confiança no processo. Quando cada release é um evento arriscado, faz sentido fazer escondido, com poucas pessoas e a esperança de que nada quebre. Automação de verdade muda isso. O objetivo deste artigo é prático: mostrar como sair do deploy-evento e chegar ao deploy não-evento, com pipeline reproduzível, testes confiáveis e entrega progressiva — usando exemplos concretos de GitLab CI/CD.

Por que o deploy vira um evento

Deploys assustam quando:

  • O processo é manual e cheio de etapas que só uma pessoa conhece.
  • Não há testes automatizados confiáveis cobrindo o caminho crítico.
  • Reverter é difícil, então um erro vira incidente prolongado.

Cada um desses pontos tem solução, e nenhuma delas é "deployar com mais cuidado". O cuidado individual não escala: ele depende de uma pessoa específica estar acordada, lúcida e disponível. O que escala é o processo codificado, versionado e executável por qualquer pessoa do time.

Vale separar dois custos que costumam ser confundidos. O custo direto é o tempo da janela noturna e o pessoal de plantão. O custo indireto, maior, é o acúmulo: quanto mais raro o deploy, maior o lote de mudanças por release, maior a superfície de erro e mais difícil isolar a causa quando algo quebra. A madrugada não reduz risco — ela apenas esconde o sintoma de quem está dormindo.

Os três pilares de um deploy tranquilo

1. Pipeline reproduzível

Tudo que acontece entre o commit e a produção precisa estar no pipeline — versionado, automatizado e idêntico a cada execução. Nada de scripts na máquina de alguém.

Na prática, isso significa que o build, os testes e o deploy vivem no .gitlab-ci.yml (ou em arquivos incluídos via include), não em um runbook de wiki que ninguém atualiza. A mesma definição roda em merge request, em branch e em produção. Imagens de container com tag fixa garantem que o ambiente de execução não mude por baixo dos panos.

stages:
  - build
  - test
  - deploy

build:
  stage: build
  image: node:20-bookworm
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 week

Dois detalhes que separam um pipeline frágil de um reproduzível: usar npm ci (instala exatamente o que está no lockfile) em vez de npm install, e fixar a tag da imagem base em vez de latest. Ambos eliminam a classe de bug "funciona no meu pipeline, falha no seu".

2. Testes que dão confiança

Não basta ter testes; é preciso confiar neles. Suítes de unidade, integração e API rodando em minutos transformam o "será que quebrou?" em um sinal verde objetivo.

Confiança vem de duas propriedades: a suíte é rápida o suficiente para rodar a cada commit, e é estável o suficiente para que um vermelho signifique sempre um problema real. Teste instável (flaky) é pior que teste ausente, porque treina o time a ignorar a falha. Coloque em quarentena ou conserte o teste flaky no mesmo dia — não deixe acumular.

test:unit:
  stage: test
  image: node:20-bookworm
  script:
    - npm ci
    - npm run test:unit
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    - if: '$CI_COMMIT_BRANCH == "main"'

test:api:
  stage: test
  image: node:20-bookworm
  services:
    - postgres:16
  variables:
    DATABASE_URL: "postgres://test@postgres:5432/test"
  script:
    - npm ci
    - npm run test:api
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

Estruture a suíte em camadas, do mais barato ao mais caro:

Camada O que cobre Quando roda Tempo-alvo
Unidade Lógica de negócio isolada Cada commit/MR Segundos
Integração / API Contratos com banco e serviços Cada MR Poucos minutos
End-to-end Caminho crítico do usuário MR de release ou nightly Minutos a dezenas

A regra prática: tudo que precisa estar verde antes do merge tem que caber na paciência de quem abriu o MR. Empurre o que for lento (E2E completo, carga) para execuções nightly ou para o pipeline de release.

3. Entrega progressiva

Em vez de mandar 100% do tráfego para a nova versão de uma vez, o deploy canário libera aos poucos:

10%  ->  observa metricas  ->  50%  ->  observa  ->  100%
   (rollback automatico se latencia ou erro piorarem)

Se a nova versão degrada latência ou erro, o rollback é automático — antes que o usuário perceba.

A entrega progressiva só funciona se houver um sinal objetivo para promover ou reverter cada passo. Defina antes do deploy quais métricas observar e qual o limite de tolerância. Tipicamente: taxa de erro (5xx), latência de cauda (p95/p99) e, quando relevante, uma métrica de negócio (conversão, checkout). O canário compara a nova versão contra a estável recebendo tráfego ao mesmo tempo, o que isola variações de horário e sazonalidade.

Existem mais estratégias além do canário, com trade-offs diferentes:

Estratégia Como funciona Vantagem Custo / Trade-off
Rolling Substitui instâncias aos poucos Simples, sem infra extra Rollback mais lento; versões convivem
Blue-green Dois ambientes; troca o tráfego de uma vez Rollback instantâneo Dobra a infra durante a troca
Canário Fração crescente de tráfego na nova versão Detecta regressão com baixo blast radius Exige boa observabilidade e automação

No GitLab, o gate de promoção pode ser explícito enquanto o time amadurece a automação, usando ambientes e um passo manual:

deploy:canary:
  stage: deploy
  environment:
    name: production/canary
  script:
    - ./deploy.sh --weight 10
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'

deploy:promote:
  stage: deploy
  environment:
    name: production
  script:
    - ./deploy.sh --weight 100
  when: manual
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'

À medida que a confiança nas métricas cresce, o when: manual da promoção dá lugar a um gate automático baseado nos limites definidos — e é aí que o "deploy na madrugada" deixa de fazer sentido.

Reverter precisa ser barato

Nenhum dos três pilares importa se reverter for caro. Trate o rollback como caminho de primeira classe, não como exceção heroica:

  • Toda release é uma versão imutável e identificável (tag/digest), nunca uma sobrescrita.
  • Migrações de banco são compatíveis para frente e para trás dentro de uma janela de release — adicione colunas antes, remova depois, em deploys separados.
  • O rollback é o mesmo mecanismo do deploy, apontando para a versão anterior. Se reverter exige um procedimento diferente do deploy, ele não foi testado.

A pergunta de verificação é simples: se a release atual quebrar agora, em quantos minutos e com quantos comandos voltamos ao estado anterior? Se a resposta envolve "depende de quem está de plantão", o trabalho ainda não terminou.

Checklist para sair da madrugada

Use isto como um caminho incremental, não como tudo-ou-nada:

  1. Mova o deploy manual para um job de pipeline, mesmo que ainda com when: manual.
  2. Garanta que o build seja reproduzível: lockfiles, imagens com tag fixa, npm ci e equivalentes.
  3. Estabilize a suíte de testes e bloqueie o merge em vermelho.
  4. Torne o rollback um job tão simples quanto o deploy e teste-o de propósito.
  5. Instrumente erro e latência de cauda em produção, com dashboards que o time olha.
  6. Introduza canário com promoção manual; defina os limites de erro/latência por escrito.
  7. Automatize a promoção e o rollback com base nesses limites.
  8. Aumente a frequência: comece com um deploy diário em horário comercial e suba a partir daí.

Cada passo reduz risco de forma isolada. Você colhe benefício antes de chegar ao fim da lista — e é exatamente por isso que dá para começar nesta sexta-feira em vez de na próxima virada de trimestre.

O efeito cultural

Quando o deploy deixa de ser arriscado, ele deixa de ser raro. Times maduros entregam várias vezes por dia, em horário comercial, sem cerimônia. A frequência alta é consequência da confiança, não da coragem.

O melhor deploy é o que ninguém percebe que aconteceu.

A automação não elimina o trabalho de engenharia — ela elimina o medo. E um time sem medo de entregar é um time que entrega mais e melhor.

Para referência de sintaxe e recursos de pipeline, consulte a documentação oficial do GitLab CI/CD.

Quer transformar seus deploys em não-eventos? Agende um diagnóstico.