GitOps mode — fetch automático e retry

O Runner opera em modo GitOps: um cron compara o SHA do repositório com o último deploy bem-sucedido. Se mudou, deploya. Esta página explica o mecanismo completo, o comportamento de retry e como proteger apps durante manutenção.

Pré-requisitos

  • Runner instalado e configurado (runner init)
  • Pelo menos uma app registrada (runner add)
  • Acesso ao crontab do servidor (para configurar o cron)

Como configurar o cron

Adicione ao crontab do servidor (crontab -e):

*/5 * * * * /usr/local/bin/runner fetch --deploy >> /opt/runner/logs/cron.log 2>&1

O intervalo padrão é 5 minutos. Ajuste conforme a frequência de deploys esperada — intervalos menores aumentam a carga na API do GitHub.

Como o fetch --deploy funciona

A cada execução, o runner percorre todas as apps registradas em apps_path:

Para cada app:
  1. git ls-remote → lê o SHA atual do repo (branch dist)
  2. Compara com state.last_deployed_commit
  3. Se mudou → executa runner deploy <app>
  4. Se o container morreu (mesmo SHA) → executa runner deploy <app>
  5. Se status=paused → skipa sem tentar

O estado de cada app fica em /opt/runner/state/<app>.yml.

Retry-exhausted — o que acontece com commits quebrados

Quando um deploy falha (healthcheck não passa, build quebra), o runner não tenta indefinidamente o mesmo commit. O controle é feito por dois campos no estado:

Campo no state Tipo Função
last_failed_commit string SHA do último commit que falhou
deploy_retry_count integer Quantas vezes tentou esse SHA

O threshold é configurado em /opt/runner/config.yml:

max_deploy_retries: 3   # default; 0 = ilimitado

Após 3 falhas no mesmo SHA, o runner para de tentar aquele commit. Quando um novo commit chega (push novo no repo), o contador zera e o ciclo recomeça.

Para ver o estado atual de uma app:

runner status minha-app

Auto-pause — N falhas consecutivas no fetch (v2.23.19)

Diferente do retry-exhausted (que rastreia falhas de deploy de um SHA específico), o auto-pause rastreia falhas consecutivas no próprio fetch — quando o runner não consegue nem ler o repo remoto.

# /opt/runner/config.yml
max_consecutive_fetch_errors: 10   # default; 0 = desabilita

Quando consecutive_fetch_errors >= max_consecutive_fetch_errors, o runner muda status para paused e o cron skipa a app. Isso evita flood de erros quando o repo foi removido ou a rede está instável.

Para recuperar:

# Após corrigir o problema upstream
runner unpause minha-app

Ver mais em pause e unpause.

O que pode dar errado

Commit quebrado passa no healthcheck

O cenário mais crítico: o código faz git push com um bug, o container sobe, o healthcheck passa (endpoint /health sempre retorna 200), e o deploy mal-sucedido vai para produção.

Mitigação: Configure o healthcheck para um endpoint que valida dependências reais da aplicação — conexão ao banco, fila disponível, etc. Endpoint que só retorna {"status": "ok"} sem checar nada é inútil para esse propósito.

# .deploy.yml — healthcheck robusto
healthcheck:
  path: /health/ready   # endpoint que verifica DB, cache, etc.
  interval: 10s
  retries: 5

Cron tenta loop infinito em build quebrado

Sem max_deploy_retries, um Dockerfile com erro de compilação tentaria um novo deploy a cada 5 minutos.

Mitigação: Manter max_deploy_retries: 3 (default). O runner para após 3 falhas no mesmo SHA e aguarda novo push.

Deploy automático durante manutenção planejada

Um push acidental ou automatizado (dependabot, CI) pode acionar deploy durante uma migração de banco em andamento.

Mitigação: Pausar a app antes de iniciar a manutenção.

runner pause minha-app
# ... executa a manutenção ...
runner unpause minha-app

GitHub API rate limit

O git ls-remote consome tokens da API do GitHub. Servidores com muitas apps podem atingir o limite com intervalos curtos.

Mitigação: Usar */10 * * * * (10 minutos) para servidores com mais de 30 apps, ou configurar autenticação com token que tem limite maior.

Canary para mudanças sensíveis

Para mudanças de alto risco, use canary deployment ao invés de confiar só no healthcheck:

# .deploy.yml
instances:
  production:
    domain: app.meu-dominio.com
    canary:
      weight: 10    # começa em 10% do tráfego

Com canary ativo, o cron incrementa o peso automaticamente a cada tick configurado. Se o healthcheck falhar em qualquer ponto, o runner faz rollback automático.

Ver canary deployment.

Notificações de falha

Configure notificações para receber alertas quando um deploy falha:

# /opt/runner/config.yml
notify:
  channel: telegram
  telegram_bot_token: "123456:ABC..."
  telegram_chat_id: "-1001234567890"
  verbose_errors: true   # segunda mensagem com erro completo

Com verbose_errors: true, o runner envia duas mensagens: o resumo e o log completo do erro (truncado em 800 caracteres).

By Borlot.com.br on 27/05/2026