Skip to main content

botapp

PyPI Python Django License: MIT

botapp é um SDK + dashboard Django para observabilidade de automações RPA. Ele instrumenta seus bots com um único decorator, registra cada execução (sucesso, falha, duração, ambiente), expõe um painel web para acompanhamento e dispara alertas (Slack, Discord, e-mail) quando algo foge do esperado.


Sumário


Visão geral

Quando você mantém uma frota de bots RPA, a dor de cabeça não é escrever o bot — é saber quando ele parou de rodar, quando passou a falhar demais ou quando está mais lento do que deveria. O botapp resolve isso com três camadas acopladas:

  1. SDK (from botapp import BotApp) — um decorator @app.task que envolve suas funções e grava cada execução no banco automaticamente.
  2. Dashboard web — painel administrativo Django com listagens, detalhes de logs, exploração filtrada, exportação CSV/PDF e gestão de alertas.
  3. Motor de alertas — um scheduler que varre periodicamente o banco em busca de anomalias (silent_bot, error_spike, heartbeat_lost, duration_regression) e dispara notificações em Slack, Discord e e-mail.

Todos os três podem ser usados em conjunto ou separadamente.


Funcionalidades

Observabilidade

  • Decorator único para instrumentar tarefas (@app.task), com captura automática de:
    • host_name, host_ip, user_login, pid, bot_dir
    • os_platform, python_version, env (dev/staging/prod)
    • start_time, end_time, duration, status, exception_type, error_message, trigger_source.
  • Denormalização Bot.last_execution_at / Bot.last_status via post_save signal para listagens rápidas.
  • Função reconcile_bot_last_execution() para self-heal quando SDKs antigos escrevem logs sem disparar signals.

Dashboard

  • Lista de bots com status, última execução, contadores, filtros por departamento/status.
  • Detalhe do bot com histórico paginado de execuções, gráficos de taxa de erro e duração.
  • Página Dashboard global com contadores agregados (bots ativos, silenciosos, alertas críticos).
  • Explore — filtros combinados em TaskLog com exportação CSV.
  • Manutenção — ações de limpeza de órfãos e configuração em massa de thresholds por bot.
  • Tema responsivo, CSP opcional, rate limiting em rotas sensíveis.

Alertas

  • 4 regras de detecção prontas, todas com severidade graduada (low, medium, high, critical):
    • silent_bot — bot ativo sem execução há mais de N horas/minutos.
    • error_spike — pico de falhas em janela recente.
    • heartbeat_lost — log com status='started' que nunca fechou.
    • duration_regression — duração média recente acima do SLA da task.
  • Idempotência: não cria alerta duplicado se já existir um ativo do mesmo tipo para o mesmo bot.
  • Dispatcher multi-canal com fallback tolerante (Slack, Discord, e-mail).
  • Ações de acknowledge e resolve via UI ou REST.
  • Override de threshold por bot (silence_threshold_hours, silence_threshold_minutes).

API REST

  • DRF com ViewSets para Bot, Task, TaskLog.
  • Autenticação SessionAuthentication + BasicAuthentication.
  • Permissão padrão: IsAuthenticated.
  • Rate limiting em endpoints sensíveis via django-ratelimit.

Operacional

  • Comandos de gerência para setup, scheduler, limpeza de órfãos e reconciliação.
  • Thread in-process opcional para dev (BOTAPP_ALERT_SCHEDULER_ENABLED).
  • Comando dedicado para produção multi-worker: botapp run_alert_scheduler.

Arquitetura — modos de uso

O botapp pode ser consumido de duas formas, detectadas automaticamente em botapp/__init__.py:

Modo standalone

Quando DJANGO_SETTINGS_MODULE não está definido, o pacote usa seu próprio botapp.settings. É assim que o dashboard é servido como serviço autônomo.

from botapp import BotApp  # resolve para botapp.core.BotApp
app = BotApp('meu_banco')
  • Grava direto no Postgres usando os modelos Django.
  • Ideal para bots que rodam no mesmo host/rede do banco.

Modo plugin (REST client)

Quando o SDK é importado dentro de outro projeto Django (DJANGO_SETTINGS_MODULE definido e ROOT_URLCONF diferente de botapp.urls), BotApp é substituído por BotAppRestful, que fala com um dashboard remoto via HTTP.

# Em outro projeto Django, com BOTAPP_API_URL apontando para o dashboard remoto
from botapp import BotApp  # resolve para botapp.core_restful.BotAppRestful
app = BotApp()
  • Não exige acesso direto ao banco.
  • Perfeito para bots embarcados em aplicações maiores ou em redes segregadas.
  • Requer BOTAPP_API_URL, BOTAPP_API_USUARIO, BOTAPP_API_SENHA.

Instalação

Requisitos: Python 3.8+, Django 3.2+, Postgres 12+ (SQLite funciona para testes).

pip install botapp

Dependências instaladas automaticamente: Django, psycopg2-binary, djangorestframework, django-admin-rangefilter, django-ratelimit, whitenoise, python-dotenv, openpyxl, xhtml2pdf, requests.


Início rápido

1. Configure o ambiente

Crie um .env na raiz do projeto:

BOTAPP_DEBUG=True
BOTAPP_SECRET_KEY=troque-em-producao
BOTAPP_ALLOWED_HOSTS=*

# Postgres
PG_BOTAPP_SCHEMA=botapp_schema
PG_BOTAPP_DBNAME=botapp
PG_BOTAPP_USER=botapp
PG_BOTAPP_PASSWORD=senha
PG_BOTAPP_HOST=localhost
PG_BOTAPP_PORT=5432

# Superusuário inicial (criado pelo comando setup)
BOTAPP_SUPERUSER_USERNAME=admin
BOTAPP_SUPERUSER_EMAIL=admin@example.com
BOTAPP_SUPERUSER_PASSWORD=troque-em-producao

2. Inicialize o banco

botapp setup      # cria schema + roda migrations + cria superusuário

3. Suba o dashboard

botapp runserver 0.0.0.0:8000

Acesse http://localhost:8000/.

4. Instrumente um bot

from botapp import BotApp

app = BotApp('botapp')  # mesmo PG_BOTAPP_DBNAME
app.set_bot(
    bot_name='relatorio_diario',
    bot_description='Consolida vendas do dia',
    bot_version='1.0.0',
    bot_department='Financeiro',
)

@app.task
def gerar_relatorio():
    """Gera e envia o relatório diário."""
    # seu código aqui
    return 'ok'

gerar_relatorio()  # será registrada como TaskLog automaticamente

Modelo de dados

Bot
 ├── name, description, version, department
 ├── is_active
 ├── last_execution_at (denorm)      ← atualizado pelo signal em TaskLog
 ├── last_status (denorm)
 ├── silence_threshold_hours/minutes ← override por bot do limiar de silent_bot
 └── tasks (1:N)

Task
 ├── bot (FK)
 ├── name (__name__ da função decorada)
 ├── description (docstring)
 ├── expected_duration_seconds      ← SLA usado pelo detector de regressão
 └── logs (1:N)

TaskLog
 ├── task (FK)
 ├── status                         ← started | completed | failed
 ├── start_time / end_time / duration
 ├── result_data (JSON)             ← retorno da função serializado
 ├── error_message / exception_type ← traceback do erro, se houver
 ├── host_ip, host_name, pid, user_login, os_platform, python_version
 ├── bot_dir, env, trigger_source, manual_trigger
 └── indexes: -start_time, task+-start_time, status+-start_time, env+-start_time

Alert
 ├── type        ← silent_bot | error_spike | heartbeat_lost | duration_regression
 ├── severity    ← low | medium | high | critical
 ├── bot (FK, nullable)             ← null = alerta global
 ├── message, payload (JSON)
 ├── created_at / updated_at
 ├── acked_at, acked_by (FK User)   ← reconhecimento manual
 ├── resolved_at, resolved_by       ← resolução manual
 └── notified_at                    ← última vez que o dispatcher enviou

Migrations relevantes:

  • 0008_indexes_performance — índices de performance em TaskLog.
  • 0009_bot_last_execution_denorm — campos denormalizados em Bot.
  • 0010_alerts — tabela Alert.
  • 0011_task_expected_duration_seconds — SLA por task.
  • 0012_bot_silence_threshold_minutes — granularidade fina por bot.

SDK — instrumentando bots

BotApp (standalone)

from botapp import BotApp

app = BotApp(db_name='botapp')
app.set_bot(
    bot_name='meu_bot',           # normalizado: só alfanuméricos, capitalize
    bot_description='O que faz',
    bot_version='1.2.3',
    bot_department='TI',
)

@app.task
def minha_tarefa(arg1, arg2):
    """Docstring vira a description da Task."""
    return {'ok': True}

Comportamento do decorator:

  1. Se o bot estiver is_active=False, a execução é bloqueada com exceção.
  2. Cria/recupera a Task pelo func.__name__ e atualiza a description se a docstring mudou.
  3. Cria TaskLog(status='started') com snapshot do ambiente.
  4. Executa a função. Em caso de exceção, grava exception_type + error_message e re-lança.
  5. No finally, seta end_time e o status final.

BotAppRestful (modo plugin)

# Em outro projeto Django
from botapp import BotApp  # resolve para BotAppRestful se detectar host Django
app = BotApp()                         # usa BOTAPP_API_URL do env
app.set_bot('meu_bot', 'desc', '1.0', 'TI')

@app.task
def tarefa():
    ...

O fluxo é o mesmo, mas todas as operações batem na API REST do dashboard remoto via requests. Credenciais vêm de BOTAPP_API_USUARIO / BOTAPP_API_SENHA (HTTP Basic).


Dashboard web

Rotas principais (prefixadas por / quando em modo standalone):

Rota Descrição
/bots/ Lista de bots com filtros.
/bots/<id>/ Detalhe do bot: execuções, métricas, gráficos.
/bot/<id>/toggle-status/ Liga/desliga bot (POST).
/log/<id>/ Detalhe completo de um TaskLog.
/dashboard/ Painel agregado: bots ativos, silenciosos, alertas.
/alerts/ Lista de alertas (filtros: status, severity, type, bot).
/alerts/<id>/ack/ POST — ack um alerta.
/alerts/<id>/resolve/ POST — resolve um alerta.
/alerts/unread-count/ JSON para badge do menu (polling leve).
/maintenance/cleanup-orphans/ UI para acionar cleanup_orphans via HTTP.
/maintenance/silence-thresholds/ Edição em massa de thresholds de silent_bot.
/bots/bulk-silence-threshold/ Ação em massa dos thresholds.
/explore/ Filtros combinados em TaskLog.
/explore/export.csv Exporta o resultado filtrado como CSV.
/admin/ Django admin.
/api/ API REST (ver seção API REST).
/accounts/login/ · /accounts/logout/ Autenticação.
/accounts/password_reset/… Fluxo completo de reset por e-mail.

Sistema de alertas

Regras

Tipo Dispara quando Severidade calculada em função de
silent_bot Bot is_active sem execução há mais de N horas (override por bot ok). horas_silencio / threshold
error_spike ≥ X falhas em janela deslizante de M minutos. falhas / threshold
heartbeat_lost Log com status='started' mais antigo que N horas. Severidade fixa por idade
duration_regression Média das últimas N execuções acima de expected_duration_seconds × k. duração_média / expected

Fechamento automático

Cada rodada de check_alerts fecha o alerta cuja condição já passou, antes de detectar de novo: bot que voltou a executar, execução travada que encerrou, janela do pico que passou, duração que voltou ao esperado. O alerta fechado assim recebe payload.fechado_por = "condicao_superada".

Isso não é só limpeza de painel. A deduplicação de cada regra é contra alerta aberto do mesmo tipo para o mesmo bot — então um alerta que nunca fecha cega aquele tipo para aquele bot, e a próxima ocorrência real não gera alerta nenhum.

O fechamento é conservador: só fecha o que consegue julgar como normal agora. Sem como julgar (bot ausente, amostra insuficiente de duração), o alerta fica aberto. --dry-run não fecha nada.

Antes de tudo isso, cada rodada encerra execução morta: TaskLog preso em started por mais de BOTAPP_ORPHAN_TASKLOG_HOURS (default 24) vira failed com exception_type='ProcessoMorto'. O @task fecha o log no finally até quando a task levanta exceção — log eternamente em started significa que o processo morreu sem passar por ali (container derrubado, OOM, compose down, job cancelado). Sem esse encerramento o heartbeat_lost daquele bot nunca se resolve e, pela deduplicação, tampa o próximo alerta do mesmo tipo. O limiar é deliberadamente maior que o do heartbeat_lost (6h): na janela entre os dois o alerta deve aparecer, porque ali ainda pode ser job de verdade travado. end_time fica nulo — a hora da morte é desconhecida, e gravar now inflaria a duração com o tempo que o registro passou órfão.

Os alertas de CI seguem a mesma ideia, em ci_sync: pipeline_failed e pipeline_masked_error fecham quando um pipeline posterior do mesmo projeto passa (resolver_alertas_obsoletos), e schedule_without_run / project_never_ran fecham quando o projeto volta a executar dentro do intervalo do cron (resolver_agendamentos_em_dia, payload.fechado_por = "agendamento_em_dia").

Dispatcher (notifiers.py)

Ao criar um alerta, check_alerts chama dispatch_alert(alert) que envia para todos os canais configurados. Cada canal é opt-in: se a env var correspondente não estiver definida, o canal é silenciosamente ignorado. Uma falha em um canal não bloqueia os outros.

  • Slack: webhook com attachment colorido por severidade.
  • Discord: embed com cor hex equivalente.
  • E-mail: usa settings.EMAIL_* (SMTP do Django) com lista de destinatários em BOTAPP_ALERT_EMAIL_RECIPIENTS.

Se qualquer canal teve sucesso, alert.notified_at é atualizado — assim, executar check_alerts em intervalo curto não re-dispara notificações a cada rodada.

Como rodar o detector

Desenvolvimento (thread in-process, single worker):

BOTAPP_ALERT_SCHEDULER_ENABLED=true
BOTAPP_ALERT_SCHEDULER_INTERVAL_SECONDS=60

Ao subir o Django, o AppConfig.ready() inicia uma thread daemon que loopa check_alerts a cada intervalo. Não use em produção com múltiplos workers — N workers × N schedulers gera concorrência e alertas duplicados.

Produção (processo dedicado):

botapp run_alert_scheduler --interval 60

Ou em container:

services:
  botapp_scheduler:
    image: meu-registry/botapp
    environment:
      BOTAPP_ROLE: scheduler
    command: botapp run_alert_scheduler

Flags úteis:

  • --interval N — sobrescreve BOTAPP_ALERT_SCHEDULER_INTERVAL_SECONDS.
  • --once — roda uma vez e sai (útil para cron externo).
  • check_alerts --dry-run — só loga o que faria.
  • check_alerts --no-notify — cria alertas mas não envia webhooks.

API REST

Base: /api/ · Autenticação: Session ou Basic · Permissão: IsAuthenticated.

Método · Rota Descrição
GET /api/bots/ Lista bots (parametros: search).
POST /api/bots/ Cria bot.
GET /api/bots/{id}/ Detalhe.
PATCH /api/bots/{id}/ Atualização parcial.
DELETE /api/bots/{id}/ Remove.
GET /api/tasks/ Lista tasks (?bot=<id>&name=<str>).
POST /api/tasks/ Cria task.
GET /api/tasklog/ Lista logs.
POST /api/tasklog/ Cria log (usado pelo BotAppRestful).
PATCH /api/tasklog/{id}/ Atualiza log (status, end_time, duration…).

Exemplo:

curl -u admin:senha http://localhost:8000/api/bots/?search=relatorio

Comandos de gerência

Disponíveis via entry point botapp (equivalente a python manage.py):

Comando Uso
botapp setup Cria schema + roda migrations + cria superusuário.
botapp migrate [--noinput] Aplica migrations.
botapp collectstatic [--noinput] Coleta estáticos (whitenoise em produção).
botapp runserver [host:port] Servidor dev.
botapp check_alerts [--dry-run] [--no-notify] Roda o motor de alertas uma vez.
botapp run_alert_scheduler [--interval N] [--once] Loop blocante do motor (para processo dedicado).
botapp cleanup_orphans [--threshold-hours N] [--bot-id ID] [--dry-run] [--batch-size N] [--sleep-ms N] Fecha logs travados.
botapp reconcile_bot_denorm Reconcilia Bot.last_execution_at com o TaskLog real mais recente.

Variáveis de ambiente

Essenciais

Variável Default Descrição
DJANGO_SETTINGS_MODULE botapp.settings (standalone) Aponta para seu settings em modo plugin.
BOTAPP_DEBUG False Modo debug do Django.
BOTAPP_SECRET_KEY obrigatório em prod Secret key. Default de dev não é aceito com DEBUG=False.
BOTAPP_ALLOWED_HOSTS * Lista separada por vírgula.
BOTAPP_CSRF_TRUSTED_ORIGINS * (quando DEBUG=False) Lista separada por vírgula.
BOTAPP_PORT_ADMIN 8000 Porta usada por app.open_admin().
BOTAPP_LANGUAGE_CODE pt-br
BOTAPP_TIME_ZONE America/Cuiaba Fuso padrão.
BOTAPP_USE_I18N True
BOTAPP_USE_TZ True Mantenha True para datetimes aware (exigido pelos notifiers).
BOTAPP_DEPLOY_ENV dev Gravado em TaskLog.env.
BOTAPP_LOGGING_LEVEL INFO Nível do logger botapp.
BOTAPP_DJANGO_LOG_LEVEL WARNING Nível do logger django.

Banco de dados (Postgres)

Variável Descrição
BOTAPP_DATABASES (opcional) JSON com o dict DATABASES completo. Sobrescreve as demais.
PG_BOTAPP_SCHEMA Schema das tabelas (default botapp_schema).
PG_BOTAPP_DBNAME Nome do banco.
PG_BOTAPP_USER Usuário.
PG_BOTAPP_PASSWORD Senha.
PG_BOTAPP_HOST Host.
PG_BOTAPP_PORT Porta (default 5432).

Superusuário inicial (usado por botapp setup)

Variável Default
BOTAPP_SUPERUSER_USERNAME admin
BOTAPP_SUPERUSER_EMAIL admin@example.com
BOTAPP_SUPERUSER_PASSWORD admin123 (proibido em prod)

Cache / Redis

Variável Default
BOTAPP_CACHES JSON com o dict CACHES. Se ausente em prod, usa Redis.
BOTAPP_REDIS_URL redis://botapp_redis:6379/1

E-mail (SMTP)

Variável Default
BOTAPP_EMAIL_HOST
BOTAPP_EMAIL_PORT 587
BOTAPP_EMAIL_USER
BOTAPP_EMAIL_PASSWORD
BOTAPP_EMAIL_USE_TLS True
BOTAPP_DEFAULT_FROM_EMAIL BOTAPP_EMAIL_USER

Modo plugin (REST client)

Variável Default Descrição
BOTAPP_API_URL URL do dashboard remoto. Obrigatório no modo plugin.
BOTAPP_API_USUARIO HTTP Basic user.
BOTAPP_API_SENHA HTTP Basic password.
BOTAPP_API_TIMEOUT 10 Timeout (s) das chamadas HTTP.

Scheduler / alertas

Variável Default
BOTAPP_ALERT_SCHEDULER_ENABLED false (não inicia thread in-process)
BOTAPP_ALERT_SCHEDULER_INTERVAL_SECONDS 60
BOTAPP_SILENT_BOT_THRESHOLD_HOURS 24
BOTAPP_ERROR_SPIKE_WINDOW_MINUTES 60
BOTAPP_ERROR_SPIKE_THRESHOLD 5
BOTAPP_HEARTBEAT_LOST_THRESHOLD_HOURS 6
BOTAPP_DURATION_REGRESSION_MULTIPLIER 1.5
BOTAPP_DURATION_REGRESSION_WINDOW 20 (últimas N execuções)

Canais de notificação

Variável Default Efeito
BOTAPP_SLACK_WEBHOOK_URL Se definida, envia para Slack.
BOTAPP_DISCORD_WEBHOOK_URL Se definida, envia para Discord.
BOTAPP_ALERT_EMAIL_RECIPIENTS Lista separada por vírgula. Se vazia, não envia.
BOTAPP_DASHBOARD_URL Base usada para gerar link nas notificações.
BOTAPP_NOTIFIER_TIMEOUT 5 Timeout (s) das chamadas aos webhooks.

Limpeza de órfãos

Variável Default
BOTAPP_ORPHAN_THRESHOLD_HOURS 24
BOTAPP_ORPHAN_BATCH_SIZE 500
BOTAPP_ORPHAN_SLEEP_MS 100
BOTAPP_ORPHAN_HTTP_MAX 5000

Export

Variável Default Descrição
BOTAPP_CSV_MAX_ROWS 0 0 = ilimitado. Teto opcional para /explore/export.csv.

Deploy em produção

Topologia recomendada:

┌──────────────┐   ┌────────────────────┐   ┌─────────────────────┐
│  Bots (SDK)  │──▶│  web (gunicorn)    │──▶│  Postgres + Redis   │
└──────────────┘   │  BOTAPP_ROLE=web   │   └─────────────────────┘
                   │  N workers         │
                   └────────────────────┘
                           │
                   ┌────────────────────┐
                   │  scheduler         │  (um único processo)
                   │  BOTAPP_ROLE=      │
                   │     scheduler      │
                   └────────────────────┘

Pontos importantes:

  1. Nunca deixe BOTAPP_ALERT_SCHEDULER_ENABLED=true no container web com múltiplos workers — use um container scheduler dedicado.
  2. Rode botapp migrate antes do primeiro start (ou no entrypoint do serviço web).
  3. Configure BOTAPP_SECRET_KEY, BOTAPP_ALLOWED_HOSTS, BOTAPP_CSRF_TRUSTED_ORIGINS explicitamente.
  4. HTTPS reverse proxy na frente do gunicorn; o settings já ativa SECURE_SSL_REDIRECT, HSTS e cookies seguros quando DEBUG=False.
  5. BOTAPP_DASHBOARD_URL deve apontar para a URL pública do dashboard — usado nos links das notificações.

Exemplo de docker-compose mínimo:

services:
  web:
    image: botapp:latest
    environment:
      BOTAPP_ROLE: web
      BOTAPP_ALERT_SCHEDULER_ENABLED: "false"
    env_file: .env.prod
    ports: ["8000:8000"]

  scheduler:
    image: botapp:latest
    environment:
      BOTAPP_ROLE: scheduler
      BOTAPP_ALERT_SCHEDULER_ENABLED: "true"
    env_file: .env.prod
    command: botapp run_alert_scheduler
    depends_on: [web]

  redis:
    image: redis:alpine

Troubleshooting

Alertas não estão sendo criados. Verifique nessa ordem: (1) a migration 0010_alerts rodou (\dt botapp_alert no psql); (2) o scheduler está rodando (botapp run_alert_scheduler em container dedicado ou BOTAPP_ALERT_SCHEDULER_ENABLED=true em dev); (3) existem bots com is_active=True e últimos logs fora do threshold. Rode botapp check_alerts --dry-run para ver o que seria criado sem tocar no banco.

Alertas criados mas sem notificação. Nenhuma das envs de canal foi definida — o dispatcher pula canais sem configuração. Defina pelo menos uma entre BOTAPP_SLACK_WEBHOOK_URL, BOTAPP_DISCORD_WEBHOOK_URL, BOTAPP_ALERT_EMAIL_RECIPIENTS. Verifique o log do scheduler por notifier.slack: falha / notifier.discord: falha / notifier.email: falha.

Bot.last_execution_at desatualizado. SDK antigo (sem o signal post_save) está escrevendo TaskLog direto no banco. Rode botapp reconcile_bot_denorm manualmente ou aguarde o check_alerts (ele chama a reconciliação a cada rodada).

Muitos alertas heartbeat_lost. Crashes deixaram logs em status='started'. Rode botapp cleanup_orphans --threshold-hours 24 para fechá-los retroativamente como failed/orphan_heartbeat.

ProgrammingError: relation "botapp_alert" does not exist. As migrations não rodaram no ambiente. Execute botapp migrate --noinput.

Unknown command: 'check_alerts'. Você está em uma versão < 0.3.1, que foi publicada sem o diretório management/. Atualize para 0.3.1+.


Desenvolvimento local

git clone https://github.com/botlorien/botapp
cd botapp
python -m venv .venv && source .venv/bin/activate
pip install -e .
pip install build twine

# Configure .env como na seção "Início rápido"
botapp setup
botapp runserver

Para testar o SDK contra o banco local, use example.py como referência.

Publicando uma nova versão

python setup.py sdist bdist_wheel
twine upload dist/*

Antes de publicar, verifique que find_packages() detecta todos os subpacotes (em particular botapp.management e botapp.management.commands, que precisam de __init__.py):

python -c "from setuptools import find_packages; print(find_packages())"

Integração com CI (GitLab)

A partir da 0.6.0 o painel também lê o servidor de CI, e não só o que o bot conta sobre si mesmo. Isso cobre três pontos cegos da instrumentação:

  1. Bot que morre antes de instrumentar — falha de credencial, dependência ausente, imagem quebrada: o SDK nunca é chamado e o painel não mostra nada.
  2. Bot que nunca instrumentou — sem o SDK configurado, ele roda, falha e ninguém vê.
  3. Verde que mente — pipeline com status de sucesso cujo log tem Traceback: a exceção foi engolida e o processo saiu com código 0.

A feature nasce desligada. Para ligar, no mínimo:

BOTAPP_CI_ENABLED=true
BOTAPP_CI_BASE_URL=https://seu-gitlab            # sem default de propósito
BOTAPP_CI_NAMESPACE=seu-grupo                     # path ou id numérico
BOTAPP_CI_TOKEN=<token de LEITURA>
python manage.py sync_ci --bootstrap --discovery   # cria a conexão e descobre
python manage.py run_ci_scheduler                  # loop (container separado)

As telas ficam em /ci/ (visão geral), /ci/projects/ e /ci/connections/.

Segurança do token

O token de leitura de API dá acesso a código-fonte e logs de build de todo o namespace. Recomendações que o próprio código impõe:

  • use um token de grupo/serviço somente-leitura, nunca um token pessoal de administrador;
  • por padrão o token não vai para o banco: o registro guarda só o nome da variável de ambiente (token_source="env"), então um dump de backup não contém credencial;
  • o modo token_source="db" exige BOTAPP_CI_TOKEN_KEY (Fernet, extra pip install "botapp[ci-db-token]") e é recusado sem a chave, em vez de gravar em texto puro;
  • a tela mostra no máximo uma impressão digital do token; a API nunca o serializa; o cliente HTTP mascara o valor em qualquer mensagem de erro;
  • o log de job é proxeado pelo servidor — o navegador nunca recebe o token — e servido como text/plain com nosniff, porque log é conteúdo não confiável.

Variáveis

variável default função
BOTAPP_CI_ENABLED false liga a integração
BOTAPP_CI_BASE_URL URL do servidor de CI
BOTAPP_CI_NAMESPACE grupo/organização a sincronizar
BOTAPP_CI_TOKEN token de leitura
BOTAPP_CI_TOKEN_KEY chave Fernet (só p/ token_source="db")
BOTAPP_CI_DISCOVERY_INTERVAL_MINUTES 1440 refresh de projetos/agendamentos
BOTAPP_CI_POLL_INTERVAL_MINUTES 15 busca de pipelines
BOTAPP_CI_ERROR_PATTERNS Traceback (most recent call last), CRITICAL, FATAL padrões de erro no log (separados por |)
BOTAPP_CI_IGNORE_PATTERNS vazio ruídos a ignorar antes de casar padrão
BOTAPP_CI_LOG_TAIL_BYTES 65536 tamanho máx. da cauda persistida
BOTAPP_CI_ALERT_MAX_AGE_DAYS 7 não alerta sobre execução mais antiga que isso — a carga inicial importa histórico, e falha de meses atrás não é acionável
BOTAPP_CI_STORE_TRIGGERED_BY true grava quem disparou o pipeline (dado pessoal — desligue se o seu regime tratar isso como monitoramento de pessoa)
BOTAPP_CI_ALLOW_INSECURE false permite http:// na base_url
BOTAPP_CI_TIMEOUT_SECONDS 30 timeout por chamada

Projetos inativos

Projeto arquivado no servidor de CI é detectado na redescoberta e marcado como inativo: a consulta traz os arquivados de propósito, porque filtrá-los criaria um ponto cego permanente — um projeto arquivado depois da primeira importação sumiria do resultado, o painel nunca saberia, e seguiria sincronizando e alertando um repositório que ninguém mantém.

Também dá para arquivar no painel um projeto que segue ativo no CI mas está dormente (/ci/projects/<id>/ › Arquivar no painel). Em ambos os casos o projeto deixa de ser sincronizado, deixa de gerar alerta, e os alertas abertos dele são fechados. Ele some da listagem por padrão — o checkbox incluir inativos o traz de volta.

O painel não arquiva no servidor de CI: o cliente é somente-leitura por desenho. A tela oferece o link direto das configurações do projeto para quem tem permissão de escrita fazer isso lá.

Em lote: python manage.py archive_dormant_ci_projects --days 60 --dry-run.

Detecção de "verde que mente"

É opt-in por projeto (scan_logs), porque custa uma chamada de log por job bem-sucedido — ligar para tudo multiplica o tráfego. Quando liga, use BOTAPP_CI_IGNORE_PATTERNS para os ruídos conhecidos da sua stack; sem isso a detecção vira alarme constante e alguém a desliga.

Detalhes de arquitetura em docs/ci-integration-design.md.


Licença

MIT — ver LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

botapp-0.6.19.tar.gz (175.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

botapp-0.6.19-py3-none-any.whl (191.8 kB view details)

Uploaded Python 3

File details

Details for the file botapp-0.6.19.tar.gz.

File metadata

  • Download URL: botapp-0.6.19.tar.gz
  • Upload date:
  • Size: 175.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.11

File hashes

Hashes for botapp-0.6.19.tar.gz
Algorithm Hash digest
SHA256 9aff9dd552f1f915fca2edb942fcde91bf5b3f27e2433f18297d1a1635231e01
MD5 43bf8aeccf26a7a1bd702bdd1121844f
BLAKE2b-256 0f6b70e894dc70da3547a9ee27f4afba8f07ab9e7d756f500951c5b459799f67

See more details on using hashes here.

File details

Details for the file botapp-0.6.19-py3-none-any.whl.

File metadata

  • Download URL: botapp-0.6.19-py3-none-any.whl
  • Upload date:
  • Size: 191.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.11

File hashes

Hashes for botapp-0.6.19-py3-none-any.whl
Algorithm Hash digest
SHA256 c564f3acf0dda1256c89ee01b8fa764eccf79de81697b11d252952f4c6c0aaa5
MD5 4210a8b084df0caf2c32bad6945de65e
BLAKE2b-256 e66ef415e17905b1ddd3bf3286d2ac54b938a27f6c8825e6ff2c0e27b2420ad8

See more details on using hashes here.

Release history Release notifications | RSS feed

0.6.21

2 files

0.6.20

2 files

This release

0.6.19 This release

2 files

0.6.18

2 files

0.6.17

2 files

0.6.16

2 files

0.6.15

2 files

0.6.6

2 files

0.6.5

2 files

0.6.4

2 files

0.6.3

2 files

0.6.2

2 files

0.6.1

2 files

0.6.0

2 files

0.5.4

2 files

0.5.3

2 files

0.5.2

2 files

0.5.1

2 files

0.5.0

2 files

0.4.3

1 file

0.4.2

1 file

0.4.1

1 file

0.4.0

1 file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page