Troubleshooting

Solucoes para problemas comuns no CI/CD Runner.

Deploy

Deploy nao inicia

Sintoma: Push na dist nao aciona deploy.

Causas e solucoes:

  1. App nao registrada

    runner list
    # Se nao aparecer:
    runner add --repo usuario/meu-app
  2. Cron nao configurado

    crontab -l | grep runner
    # Se nao aparecer, adicionar:
    */5 * * * * /opt/runner/runner fetch --deploy --json >> /var/log/runner-fetch.json 2>&1
  3. Branch errada

    cd /data/apps/usuario_meu-app
    git branch
    # Deve estar na dist
  4. Configuracao invalida

    runner validate --file /data/apps/usuario_meu-app/.deploy.yml

Health check falha

Sintoma: Deploy falha com "health check timeout".

Solucoes:

  1. Verificar qual healthcheck o runner esta usando

    Rode o deploy em verbose para ver o --health-cmd injetado (ou a confirmacao de que o runner esta honrando o HEALTHCHECK do Dockerfile da imagem):

    runner deploy meu-app -V
    # Procure por: "[DEPLOY] Injecting healthcheck: ..." ou
    #              "Honoring HEALTHCHECK declared by image"
  2. Imagem minimal sem curl/wget/bash?

    Imagens *-alpine e distroless frequentemente nao tem nenhum dos binarios que o runner usa para o probe HTTP padrao. Solucoes:

    • Recomendado: declare HEALTHCHECK no seu proprio Dockerfile. O runner detecta isso via docker inspect e nao injeta nada por cima.
      HEALTHCHECK --interval=10s CMD /app/bin/healthcheck || exit 1
    • Alternativa: use o modo tcp: ou cmd: em .deploy.yml:
      healthcheck:
        tcp: 8000      # apenas verifica que a porta abre
      ou
      healthcheck:
        cmd: ["/app/bin/healthcheck", "--strict"]
  3. Verificar endpoint

    docker exec CONTAINER curl -s http://localhost:8000/health
  4. Verificar porta

    grep port /data/apps/meu-app/.deploy.yml
  5. Ver logs do container

    docker logs CONTAINER --tail 100
  6. Verificar status

    docker inspect CONTAINER --format='{{.State.Health.Status}}'

Container nao sobe

Sintoma: Deploy falha, container nao inicia.

Solucoes:

  1. Ver logs

    docker logs CONTAINER --tail 200
  2. Verificar imagem

    docker images | grep IMAGEM
  3. Testar manualmente

    docker run --rm -it IMAGEM /bin/sh
  4. Verificar volumes

    docker inspect CONTAINER --format='{{.Mounts}}'

Rollback falha

Sintoma: Rollback nao funciona.

Solucoes:

  1. Verificar versoes

    runner versions meu-app -i production
    # Precisa ter versao anterior
  2. Verificar logs

    runner logs tail --app /data/apps/meu-app

Deploy fica tentando o mesmo build quebrado

Sintoma: O fetch --deploy tenta fazer deploy da mesma versao que falha repetidamente.

Causa: Antes da v1.4.1, o Runner nao rastreava falhas. A partir da v1.4.1, o Runner bloqueia automaticamente apos max_deploy_retries tentativas (padrao: 3).

Solucoes:

  1. Atualizar o Runner para v1.4.1+

    runner self-update
  2. Verificar o estado da app

    cat /opt/runner/state/usuario_meu-app.yml | grep -E "failed_commit|retry_count|status"
  3. Resetar o estado de falha (para tentar novamente) Basta fazer um novo push na branch dist — o commit diferente reseta o contador.

  4. Configurar o limite

    # /opt/runner/config.yml
    max_deploy_retries: 3   # padrao: 3, 0 = ilimitado

Deploy falhou — o que aconteceu com o site?

Resposta: Depende da fase em que falhou:

Fase O que acontece
Build falhou Site continua no ar com versao anterior
Container nao iniciou (com Traefik) Site continua no ar com versao anterior
Container nao iniciou (com portas) Runner reinicia container anterior automaticamente (v1.4.1+)
Health check falhou Runner remove container novo e reinicia o anterior

A notificacao de falha mostra a versao que ficou ativa (campo "Rollback").

Notificacao de erro ilegivel

Sintoma: Notificacao mostra erro truncado ou com output do BuildKit (ex: #0 building with "default" instance...).

Causa: Versao anterior a v1.4.1 truncava o erro em 200 caracteres no inicio do output.

Solucao: Atualizar para v1.4.1+. O Runner agora extrai a linha de erro real (ex: ERROR: process "/bin/sh -c npm run build" did not complete successfully) e suporta ate 800 caracteres.

"Another deploy is in progress" mas nao tem deploy rodando

Sintoma: runner deploy aborta com Another deploy is in progress for this app, mas voce sabe que nao ha nenhum runner ativo (o anterior crashou, foi morto com kill -9, ou o servidor reiniciou).

Solucao automatica (v2.1+): O runner agora verifica se o PID gravado no .deploy.lock ainda esta vivo (via /proc/<pid>) e remove o lock orfao automaticamente. Tambem invalida locks com mais de 6h, mesmo se o PID estiver vivo (defesa contra reuse de PID e deploys realmente travados).

Se ainda assim o lock persistir (versao antiga ou bug):

ls /data/apps/meu-app/.deploy.lock
cat /data/apps/meu-app/.deploy.lock     # ver pid + timestamp
rm /data/apps/meu-app/.deploy.lock

"depends_on cycle detected"

Sintoma: runner deploy --all aborta com mensagem listando projetos em ciclo.

Causa: Voce declarou depends_on: formando um ciclo entre dois ou mais apps. Por exemplo, inboxer-sys depende de inboxer-mta e inboxer-mta depende de inboxer-sys.

Solucao: Quebre o ciclo. Normalmente um dos apps so precisa do outro no momento do request, nao no boot — entao remova esse depends_on: e deixe o app lidar com retry/connection-pool em runtime.

# Inspecionar deps de todos os apps registrados
for f in /opt/runner/state/*.yml; do
    project=$(grep "^project:" $(grep app_path "$f" | cut -d: -f2- | tr -d ' "')/.deploy.yml 2>/dev/null)
    deps=$(grep -A5 "^depends_on:" "${app_path}/.deploy.yml" 2>/dev/null)
    echo "$project -> $deps"
done

"Config inválido em .deploy.yml: ... at line N"

Sintoma: Mensagem clara apontando linha/coluna do erro de YAML.

Causa: A partir da v2.1, o runner propaga a localizacao exata reportada pelo parser YAML em vez do antigo Config inválido. Solução: runner fetch --force.

Solucao: Abra o .deploy.yml na linha indicada e corrija. Se a mensagem mencionar expected a string/invalid type, voce provavelmente colocou uma lista onde devia ir um escalar (ou vice-versa).

"Falha de autenticacao no git: token expirou"

Sintoma: runner fetch ou runner fetch --force falha em repo privado com mensagem orientando rodar runner edit <app> --token <ghp_...>.

Causa: O token salvo no state do app expirou ou foi revogado, e a operacao de pull precisa de autenticacao. Antes da v2.1 o erro aparecia como could not read Username for ..., sem instrucao de recuperacao.

Solucao:

runner edit meu-app --token ghp_NOVO_TOKEN
runner fetch meu-app --force

Staging

Staging nao cria

Sintoma: runner stage deploy falha.

Solucoes:

  1. Verificar GitHub CLI

    gh --version
    gh auth status
  2. Verificar limite

    runner stage list
    # Se cheio, destruir algum
    runner stage destroy --id staging_app_pr35
  3. Verificar PR existe

    gh pr view 42 --repo usuario/meu-app

DNS nao resolve

Sintoma: Staging criado mas URL nao funciona.

Solucoes:

  1. Verificar wildcard DNS

    dig pr-42.staging.meusite.com.br
    # Deve resolver para IP do servidor
  2. Verificar Traefik

    ls /etc/traefik/dynamic/ | grep staging
  3. Verificar container

    docker ps | grep staging_meu-app_pr42

Canary

Peso nao muda

Sintoma: runner weight executa mas trafego nao muda.

Solucoes:

  1. Verificar Traefik config

    cat /etc/traefik/dynamic/meu-app.yml
    # Ver se weights estao corretos
  2. Recarregar Traefik

    # Traefik faz hot-reload automatico
    # Mas pode verificar logs:
    docker logs traefik --tail 50
  3. Verificar ambas versoes

    docker ps | grep meu-app
    # Ambos containers devem estar rodando

Notificacoes

Telegram nao envia

Solucoes:

  1. Verificar token

    curl "https://api.telegram.org/bot{TOKEN}/getMe"
  2. Verificar chat_id

    # Para grupos, deve ser negativo
    grep telegram /opt/runner/config.yml
  3. Testar envio

    curl -X POST "https://api.telegram.org/bot{TOKEN}/sendMessage" \
      -d "chat_id={CHAT_ID}" \
      -d "text=Teste"

Discord nao envia

Solucoes:

  1. Verificar webhook

    curl -X POST "{WEBHOOK_URL}" \
      -H "Content-Type: application/json" \
      -d '{"content": "Teste"}'
  2. Webhook existe?

    • Verificar se nao foi deletado no Discord

MCP Server

Claude Code nao reconhece

Solucoes:

  1. Verificar instalacao

    runner mcp status
  2. Reinstalar

    runner mcp uninstall
    runner mcp install
  3. Reiniciar Claude Code

    • Fechar e abrir novamente
  4. Verificar config

    cat ~/.config/claude/claude_desktop_config.json

Tools nao funcionam

Solucoes:

  1. Verificar binario

    /opt/runner/runner --version
  2. Testar CLI diretamente

    runner list

Git

Fetch falha

Sintoma: runner fetch com erro.

Solucoes:

  1. Verificar acesso

    cd /data/apps/meu-app
    git fetch origin dist
  2. Verificar SSH key

    ssh -T git@github.com
  3. Verificar URL

    git remote -v

Conflitos na dist

Solucoes:

O Runner usa git reset --hard, conflitos nao devem ocorrer.

Se ocorrer:

cd /data/apps/meu-app
git fetch origin dist
git reset --hard origin/dist
git clean -fd

Logs

Onde estao os logs?

Log Localizacao
Fetch /var/log/runner-fetch.json
Deploy /opt/runner/logs/
Container docker logs CONTAINER
Traefik docker logs traefik

Ver logs recentes

# Fetch
tail -50 /var/log/runner-fetch.json | jq .

# Deploy de uma app
runner logs tail --app /data/apps/meu-app

# Historico
runner logs history --app /data/apps/meu-app

Deploy sem Traefik (Port-only)

"port is already allocated"

O runner v2.0.8+ para o container antigo antes de iniciar o novo quando ports: esta configurado. Se estiver numa versao anterior:

# Parar container antigo manualmente
docker stop <container_antigo>

# Redeployar
runner deploy meu-app --force

Atualize o runner: runner self-update

Container sobe mas nao e acessivel pela VPC

  1. Verifique o bind de porta: docker port <container>
  2. Confirme que o IP esta correto no ports: do .deploy.yml
  3. Teste de dentro do servidor: curl http://10.108.0.X:80/health

Imagens Docker

Disco cheio de imagens

# Ver espaco usado
docker system df

# Limpar imagens nao utilizadas de projetos runner
runner cleanup --images --dry-run    # Preview
runner cleanup --images              # Executa

# Limpar build cache (> 72h)
runner cleanup --build-cache 72h

# Nuclear: limpar tudo
runner cleanup --images --build-cache all

Comandos de Diagnostico

# Status geral
runner list --detailed

# Verificar app especifica
runner health --app /data/apps/meu-app

# Validar config
runner validate --file /data/apps/meu-app/.deploy.yml

# Ver versoes
runner versions meu-app -i production

# Ver pesos
runner weights meu-app -i production

# Listar stagings
runner stage list

# Status MCP
runner mcp status
By Borlot.com.br on 12/02/2026