feat: item 7 do roadmap -- orquestração com runner externo #56

Merged
jhony75 merged 1 commit from feature/runner-orchestration into develop 2026-09-10 13:22:47 -03:00
Owner

Auditoria prévia (mesma disciplina do item 6) confirmou zero código/docs pro protocolo de orquestração — só achou um design diferente e já documentado (ADR-0012, TestCheck: o Cockpit chama HTTP pra fora sob agendamento/clique).

Decisões confirmadas com o usuário (AskUserQuestion)

  1. ADR-0012 (TestCheck) e este item coexistem — resolvem problemas diferentes: TestCheck é checagem leve de endpoint HTTP (sem suíte de teste de verdade); este item é orquestração de suítes reais (pytest/Playwright/Cypress) que precisam de um ambiente que o Cockpit não tem.
  2. Escopo desta rodada = só o lado Cockpit, validado com um runner-mock — não inclui construir um runner de produção de verdade (projeto grande e separado).

O que entra

Novo módulo backend/modules/orchestration/:

  • Runner (nome único + URL base) e RunnerJob — ciclo de vida QUEUED/RUNNING/COMPLETED/FAILED, deliberadamente separado do outcome de teste (PASS/FAIL/etc, que continua em TestRunStep via o contrato de ingestão que já existe, item 6).
  • client.py isola as 4 chamadas HTTP saintes (GET /health, GET /suites, POST /runs, GET /runs/{id}), mesmo padrão de ai_client.py/hubspot_client.py.
  • Sem polling em background/worker novo (restrição do roadmap) — cada GET /api/runner-jobs/{id} é a própria checagem ao vivo contra o runner, best-effort (mantém o último status conhecido se o runner estiver inalcançável).
  • Vínculo Job → TestRun nunca é uma FK guardada — resolvido ao vivo comparando (Runner.name, external_job_id) contra TestRun.automation_source/external_run_id, os mesmos campos que POST /api/automation/runs já grava. Zero acoplamento entre modules/orchestration e modules/automation — nenhum dos dois importa o outro (confirmado por teste de integração completo).

Frontend: tela nova Runners.tsx (master-detail, mesmo padrão de Library/AutomationDiscoveries) — registrar runner, ver saúde, listar suítes, disparar execução, acompanhar jobs com link direto pra Run gerada quando o resultado chega.

Verificação

  • Backend: pytest -n auto — 190 passed (14 testes novos, incluindo o teste de integração Job→TestRun sem acoplamento). Suíte de arquitetura confirma que o módulo novo respeita as mesmas fronteiras Core dos demais.
  • Frontend: tsc --noEmit, eslint, vitest — 131 passed (6 testes novos), build, build-storybook — todos ok.
  • Manual, ponta a ponta, com um runner-mock de verdade (script FastAPI descartável, fora do repo): registrar → saúde "Online" → suítes reais listadas → disparar job → acompanhar QUEUED→RUNNING→COMPLETED via "Atualizar" → mock publica resultado em POST /api/automation/runs → link "Ver Run #N" aparece sozinho → Run real com os 2 passos (1 PASS, 1 FAIL) certinha na tela que já existia, sem nenhuma mudança nela.

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com

Auditoria prévia (mesma disciplina do item 6) confirmou **zero código/docs** pro protocolo de orquestração — só achou um design **diferente** e já documentado (ADR-0012, `TestCheck`: o Cockpit chama HTTP pra fora sob agendamento/clique). ## Decisões confirmadas com o usuário (AskUserQuestion) 1. **ADR-0012 (TestCheck) e este item coexistem** — resolvem problemas diferentes: TestCheck é checagem leve de endpoint HTTP (sem suíte de teste de verdade); este item é orquestração de suítes reais (pytest/Playwright/Cypress) que precisam de um ambiente que o Cockpit não tem. 2. **Escopo desta rodada = só o lado Cockpit**, validado com um runner-mock — não inclui construir um runner de produção de verdade (projeto grande e separado). ## O que entra Novo módulo `backend/modules/orchestration/`: - **`Runner`** (nome único + URL base) e **`RunnerJob`** — ciclo de vida `QUEUED`/`RUNNING`/`COMPLETED`/`FAILED`, deliberadamente separado do outcome de teste (`PASS`/`FAIL`/etc, que continua em `TestRunStep` via o contrato de ingestão que já existe, item 6). - **`client.py`** isola as 4 chamadas HTTP saintes (`GET /health`, `GET /suites`, `POST /runs`, `GET /runs/{id}`), mesmo padrão de `ai_client.py`/`hubspot_client.py`. - **Sem polling em background/worker novo** (restrição do roadmap) — cada `GET /api/runner-jobs/{id}` é a própria checagem ao vivo contra o runner, best-effort (mantém o último status conhecido se o runner estiver inalcançável). - **Vínculo Job → TestRun nunca é uma FK guardada** — resolvido ao vivo comparando `(Runner.name, external_job_id)` contra `TestRun.automation_source`/`external_run_id`, os mesmos campos que `POST /api/automation/runs` já grava. **Zero acoplamento** entre `modules/orchestration` e `modules/automation` — nenhum dos dois importa o outro (confirmado por teste de integração completo). Frontend: tela nova `Runners.tsx` (master-detail, mesmo padrão de Library/AutomationDiscoveries) — registrar runner, ver saúde, listar suítes, disparar execução, acompanhar jobs com link direto pra Run gerada quando o resultado chega. ## Verificação - Backend: `pytest -n auto` — 190 passed (14 testes novos, incluindo o teste de integração Job→TestRun sem acoplamento). Suíte de arquitetura confirma que o módulo novo respeita as mesmas fronteiras Core dos demais. - Frontend: `tsc --noEmit`, `eslint`, `vitest` — 131 passed (6 testes novos), `build`, `build-storybook` — todos ok. - **Manual, ponta a ponta, com um runner-mock de verdade** (script FastAPI descartável, fora do repo): registrar → saúde "Online" → suítes reais listadas → disparar job → acompanhar `QUEUED→RUNNING→COMPLETED` via "Atualizar" → mock publica resultado em `POST /api/automation/runs` → link "Ver Run #N" aparece sozinho → Run real com os 2 passos (1 PASS, 1 FAIL) certinha na tela que já existia, sem nenhuma mudança nela. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
feat: item 7 do roadmap -- orquestracao com runner externo (Cockpit nunca roda scripts)
All checks were successful
EEG QA CI / Frontend (pull_request) Successful in 3m22s
EEG QA CI / Build e publicação de imagens (pull_request) Successful in 1m48s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Detectar o que mudou (pull_request) Successful in 12s
EEG QA CI / Backend (pull_request) Successful in 1m26s
EEG QA CI / Deploy development (pull_request) Has been skipped
80f4c5840a
Auditoria previa (mesma disciplina do item 6) confirmou zero codigo/docs
pro protocolo de orquestracao -- so achou um design DIFERENTE e ja
documentado (ADR-0012, TestCheck: o Cockpit chama HTTP pra fora sob
agendamento/clique). Decisao do usuario via AskUserQuestion: os dois
coexistem (resolvem problemas diferentes -- TestCheck e checagem leve de
endpoint HTTP, este item e orquestracao de suites reais tipo
pytest/Playwright/Cypress que precisam de um ambiente que o Cockpit nao
tem), e o escopo desta rodada e so o lado Cockpit, validado com um
runner-mock (sem construir um runner de producao de verdade).

Novo modulo backend/modules/orchestration/:
- Runner (nome unico + URL base) e RunnerJob (ciclo de vida QUEUED/
  RUNNING/COMPLETED/FAILED -- deliberadamente separado do outcome de
  teste PASS/FAIL/etc, que continua vivendo em TestRunStep via o
  contrato de ingestao que ja existe).
- client.py isola as 4 chamadas HTTP saintes (GET /health, GET /suites,
  POST /runs, GET /runs/{id}), mesmo padrao de ai_client.py/hubspot_client.py.
- Sem polling em background/worker novo (restricao do roadmap): cada
  GET /api/runner-jobs/{id} e a propria checagem ao vivo contra o runner,
  best-effort (mantem o ultimo status conhecido se o runner estiver
  inalcancavel, nunca quebra a leitura).
- Vinculo Job -> TestRun NUNCA e uma FK guardada -- resolvido ao vivo
  comparando (Runner.name, external_job_id) contra
  TestRun.automation_source/external_run_id, os mesmos campos que
  POST /api/automation/runs (item 6) ja grava. Zero acoplamento entre
  modules/orchestration e modules/automation -- nenhum dos dois importa
  o outro, confirmado por teste de integracao completo (dispara job,
  simula o runner publicando resultado pelo endpoint que ja existe,
  confere que o vinculo aparece sozinho).

Frontend: tela nova Runners.tsx (master-detail, mesmo padrao de
Library/AutomationDiscoveries) -- registrar runner, ver saude (online/
inalcancavel), listar suites, disparar execucao, acompanhar jobs com
link direto pra Run gerada quando o resultado chega.

Verificacao: backend pytest -n auto (190 passed, 14 testes novos em
test_orchestration.py, incluindo o teste de integracao Job->TestRun sem
acoplamento), suite de arquitetura confirma que o novo modulo respeita
as mesmas fronteiras Core dos demais. Frontend tsc/lint/vitest (131
passed, 6 testes novos)/build/build-storybook -- todos ok. Testado
manualmente ponta a ponta com um runner-mock de verdade (script FastAPI
descartavel, fora do repo): registrar -> saude "Online" -> suites reais
listadas -> disparar job -> acompanhar QUEUED->RUNNING->COMPLETED via
"Atualizar" -> mock publica resultado em POST /api/automation/runs ->
link "Ver Run #N" aparece sozinho -> Run real com os 2 passos (1 PASS,
1 FAIL) certinha na tela que ja existia, sem nenhuma mudanca nela.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
jhony75 merged commit 6bd19e2a8b into develop 2026-09-10 13:22:47 -03:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jhony75/eeg-qa!56
No description provided.