Trabalho Por Equipe DevBras

Capa do artigo: Deploy na sexta à noite: como definir uma janela de deploy que o time respeita

Deploy na sexta à noite: como definir uma janela de deploy que o time respeita

Defina quando subir mudança, quando congelar e como liberar exceção com responsável acordado, e coloque a regra no pipeline para ela não depender da coragem de ninguém.

Sexta, 18h40. A loja virtual Feira Online sobe a versão nova do checkout, junto com uma migração que remove a coluna antiga de frete. Às 9h de sábado, o primeiro cliente reclama que o cupom some no pagamento. Quem escreveu o código está na estrada, quem aprovou desligou o celular, e a reversão não funciona porque a coluna já não existe. A resposta curta: deploy é seguro quando há gente com contexto disponível nas horas seguintes e um caminho de volta testado. Escolha uma janela em que essas duas coisas são verdade, normalmente de segunda a quinta em horário comercial, congele datas de alto risco e trate qualquer saída fora disso como exceção com motivo e responsável nomeado.

A regra não é superstição sobre sexta-feira. É conta de risco: a probabilidade de um defeito aparecer é a mesma em qualquer dia, mas o custo de não ter ninguém para corrigir muda muito.

Por que sexta à noite dá errado

Defeitos de produção quase nunca aparecem no minuto do deploy. Aparecem quando o tráfego real passa pelo caminho que o teste não cobriu: o pico de sábado de manhã, o cupom que só um tipo de cliente usa, o job que roda de madrugada. Entre o deploy e o defeito há horas.

Na sexta à noite, essas horas caem num período em que o time está cansado, desligando ou já fora. Quem atende o problema raramente é quem conhece a mudança. O diagnóstico demora, a correção vira um remendo apressado e o remendo às vezes quebra outra coisa.

Há também o efeito da pressa. Deploy de sexta à noite costuma ser o que "precisa sair esta semana". Mudança empurrada pelo calendário recebe menos revisão, menos teste e menos atenção na hora de subir. O livro de SRE do Google, no capítulo sobre engenharia de release, defende releases frequentes, pequenos e reproduzíveis. Pequeno e frequente é o oposto do pacote grande que acumulou a semana inteira.

Como definir a janela de deploy

  1. Escolha os dias e horários em que o time está presente. Para a Feira Online: segunda a quinta, das 10h às 16h, no fuso de Brasília. Começar às 10h dá tempo de todo mundo chegar; parar às 16h deixa duas horas de observação antes do fim do expediente.
  2. Defina as datas de congelamento. Véspera de feriado, semana de Black Friday, fechamento de mês para sistema financeiro, dia de campanha grande. Coloque as datas num arquivo versionado, não na memória de alguém.
  3. Exija reversão testada. Toda mudança precisa poder voltar. Se a reversão nunca foi ensaiada, ela não conta; o guia de rollback ensaiado mostra como.
  4. Separe a migração destrutiva. Remover coluna, apagar dado ou mudar formato não volta com um rollback do código. Faça em duas etapas, como em migração em dois passos, e nunca junte a etapa destrutiva com o fim da janela.
  5. Defina o que é exceção. Correção de incidente em andamento e falha de segurança são exceções legítimas. "O cliente pediu para hoje" quase nunca é.
  6. Exija um responsável acordado. Fora da janela, alguém com contexto se compromete a acompanhar as horas seguintes. Não é "me chama se precisar"; é estar de plantão de verdade.

Coloque a regra no pipeline

Regra que só existe num documento é ignorada no primeiro aperto. O script abaixo roda como passo do pipeline antes do deploy. Ele bloqueia fora da janela e nas datas congeladas, e libera exceção só quando alguém declara o motivo e o responsável, o que fica registrado no log do pipeline.

#!/usr/bin/env bash
# scripts/janela-de-deploy.sh
set -eo pipefail

FUSO="America/Sao_Paulo"

# Brasília está em -0300 desde o fim do horário de verão em 2019; revise se isso mudar.
# Sem a base de fusos instalada, o date cai em UTC sem avisar.
if [ "$(TZ="$FUSO" date +%z)" != "-0300" ]; then
  echo "Fuso $FUSO indisponível neste runner. Instale tzdata."
  exit 1
fi

hoje=$(TZ="$FUSO" date +%F)
dia=$(TZ="$FUSO" date +%u)      # 1 = segunda ... 7 = domingo
hora=$(TZ="$FUSO" date +%H)
hora=$((10#$hora))              # "08" não pode ser lido como octal

bloqueio=""
if [ -f congelamento.txt ] && grep -qx "$hoje" congelamento.txt; then
  bloqueio="$hoje está na lista de congelamento"
elif [ "$dia" -gt 4 ] || [ "$hora" -lt 10 ] || [ "$hora" -ge 16 ]; then
  bloqueio="fora da janela (segunda a quinta, das 10h às 16h)"
fi

if [ -z "$bloqueio" ]; then
  echo "Deploy liberado: dentro da janela."
  exit 0
fi

if [ -n "$MOTIVO_EXCECAO" ] && [ -n "$RESPONSAVEL_DE_PLANTAO" ]; then
  echo "Deploy liberado por exceção: $bloqueio."
  echo "Motivo: $MOTIVO_EXCECAO"
  echo "Responsável de plantão: $RESPONSAVEL_DE_PLANTAO"
  exit 0
fi

echo "Deploy bloqueado: $bloqueio."
echo "Para exceção, defina MOTIVO_EXCECAO e RESPONSAVEL_DE_PLANTAO."
exit 1

O arquivo de congelamento tem uma data por linha, no formato ano-mês-dia:

2026-11-26
2026-11-27
2026-11-30
2026-12-24
2026-12-31

A trava do fuso no começo do script não é enfeite. Em ambientes sem a base de fusos, como algumas imagens mínimas de container, o TZ com nome de região é ignorado e o horário sai em UTC. Às 8h de segunda em Brasília já são 11h em UTC, e o script liberaria o deploy antes de o time chegar; às 14h de quinta são 17h em UTC, e ele bloquearia um deploy dentro da janela. O guia de fuso horário no PHP mostra o mesmo tipo de surpresa em outra linguagem.

O que fazer quando a exceção é inevitável

Às vezes o incidente acontece no sábado e a correção precisa subir no sábado. Nesse caso, reduza o tamanho da mudança ao mínimo que resolve o incidente. Nada de aproveitar para incluir "aquela melhoria que já estava pronta".

  • Suba só a correção, com o diff mais curto possível.
  • Tenha a reversão pronta antes de subir, com o comando à mão.
  • Combine com quem está de plantão quanto tempo cada um acompanha depois.
  • Confira o sinal de saúde real, não só o endpoint que responde 200, como descrito em healthcheck que mente.
  • Registre o que subiu e por quê, para a segunda-feira começar com contexto.

Erros comuns

  • Tratar a janela como sugestão. Sem trava no pipeline, a regra cai na primeira semana apertada e volta o deploy de sexta à noite.
  • Juntar a semana inteira num deploy só. Quando algo quebra, ninguém sabe qual das vinte mudanças causou o problema.
  • Migração destrutiva junto com o código novo. O rollback do código não traz a coluna de volta, e a reversão vira restauração de backup.
  • Exceção sem responsável nomeado. Todo mundo acha que outra pessoa está olhando, e o alerta toca para ninguém.
  • Janela calculada em UTC. O pipeline libera ou bloqueia três horas fora do previsto, e ninguém entende por quê.
  • Congelamento só na cabeça do líder. Quem entrou no time há um mês sobe mudança na véspera da Black Friday sem saber que não devia.

Checklist

  • A janela de deploy está escrita, com dias, horários e fuso.
  • As datas de congelamento estão num arquivo versionado.
  • O pipeline bloqueia deploy fora da janela sem motivo e responsável declarados.
  • O runner tem a base de fusos instalada, e o script falha se não tiver.
  • Toda mudança tem reversão ensaiada.
  • Migrações destrutivas sobem separadas do código e longe do fim da janela.
  • Exceções ficam registradas no log do pipeline com motivo e responsável.

Pense no último deploy que o seu time fez: se ele quebrar amanhã às 9h, quem está trabalhando nessa hora e consegue reverter sem ligar para ninguém?

Avalie este artigo

Referência: https://sre.google/sre-book/release-engineering/