develop #57

Merged
jhony75 merged 31 commits from develop into main 2026-09-10 13:45:24 -03:00
Owner
No description provided.
ci: instrumenta fases do Backend tests + pytest --durations
All checks were successful
EEG QA CI / validate-and-build (push) Successful in 8m17s
EEG QA CI / Deploy production (push) Has been skipped
EEG QA CI / Deploy development (push) Has been skipped
EEG QA CI / validate-and-build (pull_request) Successful in 8m5s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
0d3532e8b9
Divide o step unico "Backend tests" em steps distintos (venv, pip
install, pip check, compileall, pytest, restore drill) so pra medir
onde o tempo esta indo, e adiciona --durations=30 temporariamente pra
achar os testes mais lentos. Investigacao, nao mudanca de comportamento.
perf: banco de teste pre-migrado, evita replay de Alembic em cada teste
All checks were successful
EEG QA CI / validate-and-build (pull_request) Successful in 5m2s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
9e2420ccce
_load_app(tmp_path, monkeypatch) era duplicado identico em 16 arquivos e
sempre apontava pra um SQLite vazio -- o lifespan do FastAPI roda
database.init_db() (== alembic upgrade head) a cada TestClient(app), e
isso sozinho custava ~1.5s por teste (medido isoladamente e confirmado
batendo com o --durations=30 real da CI: praticamente todo teste do top
30 ficava entre 2.5s e 4.9s). Com ~110 dos 151 testes nesse caminho, essa
replay respondia por ~180 dos ~250s da suite inteira.

Centraliza _load_app em conftest.py e muda seu comportamento: agora
aponta pra uma COPIA de um banco ja migrado ate head, construido uma
unica vez por sessao de pytest (_build_template_db), em vez de um banco
vazio. database.init_db() continua rodando de verdade a cada
TestClient(app) via o lifespan de main.py -- nada mudou la -- so que,
como a copia ja esta em head, vira uma checagem idempotente de ~50ms em
vez de reaplicar as 18 migrations do zero. Isolamento entre testes
continua total: cada teste ainda recebe seu proprio arquivo fisico (copia
fresca), nunca compartilha conexao ou estado com outro teste.

_load_app_from_scratch preserva o comportamento antigo (banco vazio, sem
atalho) e e usado exclusivamente por
test_alembic_initialization_is_idempotent_and_reaches_head, que existe
especificamente pra provar que o Alembic aplica as migrations do zero --
esse continua rodando as migrations de verdade, sem nenhum atalho.

Resultado local: suite inteira (151 testes) caiu de ~262s para ~67s, sem
tirar nenhum teste nem reduzir cobertura.
Merge pull request 'perf: banco de teste pré-migrado nos testes de backend' (#43) from feature/backend-test-fixture-speedup into develop
Some checks failed
EEG QA CI / Deploy production (push) Has been cancelled
EEG QA CI / Deploy development (push) Has been cancelled
EEG QA CI / validate-and-build (push) Has been cancelled
25257121ee
Reviewed-on: #43
Merge pull request 'ci: instrumenta fases do Backend tests + pytest --durations' (#44) from ci-speed-investigation into develop
All checks were successful
EEG QA CI / validate-and-build (push) Successful in 5m17s
EEG QA CI / Deploy production (push) Has been skipped
EEG QA CI / Deploy development (push) Successful in 24s
53e740a8cb
Reviewed-on: #44
Retrato congelado no momento da geracao: nome/status/causa da falha de
cada cenario e passo da run sao copiados pro run de suporte do novo
report (editar a run original depois nao muda mais um report ja
gerado). As evidencias nunca sao duplicadas -- RunAttachment ganha
source_attachment_id (self-FK opcional) e a property `data` resolve
pro anexo original quando a copia nao tem BLOB proprio, entao o passo
copiado aponta pro mesmo anexo sem duplicar o BLOB no banco.

Achados ja abertos via "Abrir defeito" (Report.run_step_id) nos steps
que falharam nessa run entram automaticamente no report gerado --
mesma associacao N:N de sempre (report_issues), revisavel depois via
anexar/remover, como qualquer achado de report.

Report.source_run_id (nullable, SET NULL, sem cascade) e so
proveniencia -- apagar a run original nao apaga o report, apagar o
report nao apaga a run original. Diferente de Report.run (a run "de
suporte" exclusiva e descartavel do report, com cascade de verdade).

TestRun.report precisou de foreign_keys explicito porque agora ha dois
caminhos de FK entre test_runs e reports (report_id e o novo
source_run_id).
Chama POST /api/runs/{id}/generate-report e navega direto pro report
criado. RunDetail tambem lista os reports ja gerados a partir da run
(TestRun.generated_reports), pra evitar gerar duplicado sem querer.
Tipos regenerados de docs/openapi.json via openapi-typescript.
fix: evidencia de step no report usa /api/run-images, nao /api/images
All checks were successful
EEG QA CI / validate-and-build (pull_request) Successful in 6m38s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
9a376133ef
ExistingAttachments (linha do step, aba Tests do ReportDetail) nunca
passava urlFn nem um onDelete correto -- caia no default (api.imageUrl/
api.deleteImage, endpoint de anexo de Report/Issue), mas evidencia de
step sempre fica em RunAttachment (/api/run-images). Bug pre-existente
(RunDetail.tsx ja fazia certo, ver urlFn={api.runImageUrl} la), so
ficou visivel agora testando reports com evidencia de step de verdade.
Merge pull request 'feat: gerar Report a partir de uma Run' (#45) from feature/generate-report-from-run into develop
All checks were successful
EEG QA CI / validate-and-build (push) Successful in 5m21s
EEG QA CI / Deploy production (push) Has been skipped
EEG QA CI / Deploy development (push) Successful in 34s
8baac84f3f
Reviewed-on: #45
perf: paraleliza a suite de backend com pytest-xdist (-n auto)
All checks were successful
EEG QA CI / validate-and-build (pull_request) Successful in 3m22s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
34b181746e
Seguro porque cada teste ja e totalmente isolado desde a mudanca do
banco pre-migrado (conftest.py): arquivo SQLite proprio por teste,
nenhum estado global mutavel compartilhado entre testes ou arquivos.
Confirmado via grep (sem os.environ direto fora de monkeypatch exceto
o build do template, sem paths fixos fora de tmp_path, sem globals
mutaveis, sem dependencia de ordem entre testes) e validado com 3
execucoes locais limpas + 1 execucao real nesta CI (156 passed, 0
falhas, sem flakiness).

Resultado real nesta CI: pytest caiu de 249.63s pra 24.63s (~10x).
Fase "Backend" completa (venv+pip+pytest+restore drill) caiu de ~4m49s
pra ~69s.
Merge pull request 'perf: paraleliza a suíte de backend com pytest-xdist' (#46) from perf/pytest-xdist-parallelism into develop
All checks were successful
EEG QA CI / validate-and-build (push) Successful in 4m11s
EEG QA CI / Deploy production (push) Has been skipped
EEG QA CI / Deploy development (push) Successful in 35s
b60c85a1a3
Reviewed-on: #46
fix: consistência de status via Badge em todas as telas (item 3)
All checks were successful
EEG QA CI / validate-and-build (pull_request) Successful in 4m16s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
e704800466
Auditoria do item 3 (Storybook/design system) achou a violação real de
"componente semântico deve receber valor de domínio, nunca cor crua":
as telas de LISTA (Runs/Issues/Requirements/ReportList) nunca usavam
Badge pra status -- caíam num <span className="pill" data-status=...>
resolvido em CSS com hex cru (globals.scss), enquanto as telas de
DETALHE do mesmo domínio (RunDetail/IssueDetail/ReportDetail) já
usavam Badge com um mapa status->variant local. Mesmo padrão reusado
sem querer como "traffic light" genérico em TechnicalValidationDetail/
Form/List e DevTools (sempre Aprovado/Reprovado, 2 estados).

Centraliza os 3 mapas status->variant (antes duplicados idênticos em
ReportDetail/IssueDetail/RunDetail) em domainStatusVariants.ts, e
aplica Badge de forma consistente nas 8 telas que ainda bypassavam.
Runs.tsx também ganha um Badge por faixa de pass_rate (era só
inline-style com var() tokens, sem componente).

Remove todo o CSS agora morto: .pill[data-status=...],
[data-issue-status=...], [data-step-status=...] (esse último já
estava morto desde o item 2, nunca foi limpo), .pill.sev-* e os 4
tokens --status-* em hex cru (o comentário no arquivo já dizia
"mantidos até a tela de Reports migrar" -- a migração aconteceu agora).

Storybook build limpo, sem mudança de cobertura (os 7 componentes
citados no roadmap já tinham stories cobrindo os estados relevantes;
StatCard já cobre loading/sem-dados, EmptyState já cobre error/texto
longo, ProgressBar's "Empty" já cobre o caso de sem-dados na prática).
Merge pull request 'fix: consistência de status via Badge em todas as telas (item 3)' (#47) from feature/design-system-badge-consistency into develop
All checks were successful
EEG QA CI / validate-and-build (push) Successful in 4m26s
EEG QA CI / Deploy production (push) Has been skipped
EEG QA CI / Deploy development (push) Successful in 35s
ed035abb7b
Reviewed-on: #47
feat: editar identidade de automação (external_key) na Library
All checks were successful
EEG QA CI / validate-and-build (pull_request) Successful in 4m41s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
ff744584ff
Fecha a lacuna deixada em aberto desde o item 1 do roadmap: o backend
já suportava external_key por completo (criar/editar, unicidade
verificada, nunca roubado em duplicação), mas não existia nenhuma UI
pra editar um cenário na Library -- external_key só era setado via
mapeamento de Automation Discovery.

Adiciona "Editar identidade de automação" no menu "..." do cenário,
com o mesmo padrão de formulário inline já usado pra renomear suíte.

fix: editar só external_key/suite_id/tags não deve virar uma versão
nova do cenário -- são metadados de classificação, não uma forma
diferente de testar a mesma coisa. update_scenario_template sempre
criava uma entrada de TestScenarioTemplateVersion e incrementava
version em QUALQUER PUT, mesmo um que só mudasse a external_key --
nunca dava pra perceber isso porque não havia UI nenhuma chamando esse
endpoint até agora. Version só bump quando name/description/steps
(conteúdo de verdade) estão no payload.
feat: Shared Steps -- passo reutilizavel e versionado (item 4)
All checks were successful
EEG QA CI / validate-and-build (pull_request) Successful in 4m15s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
1b19e0d7ed
Nova biblioteca de passos (modules/shared_steps/) independente de
qualquer cenario: um SharedStep tem versao propria (SharedStepVersion
guarda TODA versao, nao so historico -- diferente do padrao de
TestScenarioTemplateVersion, porque aqui uma referencia externa
precisa resolver "o conteudo exato da versao N" de forma uniforme).

Um passo de cenario (TestStepTemplate) pode opcionalmente referenciar
um SharedStep FIXADO numa versao especifica (shared_step_id +
shared_step_version). Editar um SharedStep NUNCA muda silenciosamente
quem ja usa uma versao antiga -- description/keyword do passo sao uma
copia real da versao fixada (todo export/copia-pra-run que ja le
step.description/step.keyword funciona sem nenhuma mudanca). Upgrade
so acontece quando o payload manda um shared_step_version diferente,
explicitamente -- resolvido sempre a partir de SharedStepVersion
(nunca do SharedStep "atual" direto), entao reenviar o mesmo pin em
edicoes sem relacao nenhuma nunca faz upgrade sem querer.

Cenarios podem misturar passos soltos e passos vinculados livremente.
Deletar um SharedStep so desfaz o vinculo (SET NULL) -- o passo mantem
a ultima copia de texto que tinha, nunca é apagado.

Frontend:
- Nova tela "Shared Steps" (biblioteca propria): criar, editar (sempre
  gera versao nova), tags, "onde e usado" (com flag de desatualizado),
  comparar 2 versoes lado a lado (diff de palavras, LCS local em
  wordDiff.ts -- sem biblioteca nova).
- ScenarioBuilder ganha: inserir um Shared Step existente num passo,
  "Tornar Shared Step" (extrai o texto de um passo solto pra um
  SharedStep novo), badge de vinculo + "Atualizar pra vN" quando a
  versao fixada fica pra tras.
- Library ganha "Editar cenario" (reusa ScenarioBuilder com prefill) --
  não existia NENHUMA forma de editar passos de um cenario ja
  existente antes disso; sem essa capacidade não dava pra gerenciar
  vinculo/upgrade/desvinculo em cenarios que ja existem.

fix (achado testando): update_scenario_template sempre criava uma
versao nova em QUALQUER PUT, mesmo um que so mudasse metadado
(external_key/suite_id/tags) -- ver commit da PR #48. Sem essa
correcao, cada vinculo/upgrade de Shared Step teria gerado uma entrada
de historico espuria no cenario.

Migration: shared_steps, shared_step_versions, shared_step_tags +
2 colunas em test_step_templates. Testado upgrade/downgrade.

Verificacao: backend pytest -n auto (166 passed, 9 testes novos),
frontend tsc/lint/vitest (116 passed, 8 testes novos)/build/
build-storybook -- todos ok. Testado manualmente ponta a ponta contra
o dev real: criar Shared Step -> vincular a um cenario real -> editar
o Shared Step -> "desatualizado" aparece na leitura e na edicao ->
upgrade explicito funciona -> revertido depois.
feat: tipo de cenario -- MANUAL_STEPS/BDD/CHECKLIST/EXPLORATORY (item 5)
All checks were successful
EEG QA CI / validate-and-build (pull_request) Successful in 4m50s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
36fcbcff3e
Cenario ganha `type`, um vocabulario fechado igual ao padrao ja usado por
outcome/failure_classification (String simples + Literal no Pydantic, sem
Enum de banco -- ver schemas.ScenarioType). AUTOMATED deliberadamente NAO
e um tipo: automacao e capacidade/implementacao de um cenario, nao uma
categoria de autoria (decisao do roadmap item 5).

Auditoria antes de implementar (ver memoria eeg_qa_roadmap_2026_09) confirmou
que esse conceito nao existia em NENHUM lugar do codigo -- so um keyword
Given/When/Then opcional e sem validacao por passo. Pra evitar que o tipo
vire so um rotulo decorativo (regra explicita do roadmap: "nao adicionar
tipo que so muda aparencia"), cada tipo agora exige coerencia real com a
keyword dos passos, validada em `_validate_steps_for_type` (roda DEPOIS de
resolver eventuais Shared Steps, senao um passo vinculado poderia burlar a
regra):
- BDD exige keyword (Given/When/Then/And/But) obrigatoria em todo passo.
- CHECKLIST proibe keyword em qualquer passo.
- MANUAL_STEPS e EXPLORATORY nao restringem nada (EXPLORATORY reaproveita
  100% a lista de passos e o modelo de Run atual, so tratada como notas de
  alto nivel na UI -- decisao explicita de manter o escopo pequeno nesta
  rodada, sem redesenhar execucao).

Trocar o tipo valida os passos que JA existem mesmo quando `steps` nao e
reenviado no PUT (ex.: só mudar pra BDD sem reenviar passos ainda checa se
os passos atuais tem keyword). `type` conta como CONTEUDO pra fins de
versionamento (mesma lista de name/description/steps que ja bump a versao
e grava historico -- ver update_scenario_template), porque redefine o que
os passos do cenario significam; metadado (tags/external_key/suite_id)
continua sem versionar.

Frontend: seletor de tipo no ScenarioBuilder, com normalizacao imediata ao
trocar (BDD preenche keyword em branco com "Given", CHECKLIST limpa
keyword de todo passo) pra manter a UI sempre coerente com o que o backend
vai validar -- keyword fica escondida pra CHECKLIST e sem a opcao vazia "—"
pra BDD. Checagem espelhada no cliente antes do submit evita um
round-trip previsivel; o backend continua sendo a fonte de verdade. Badge
de tipo na Library (detalhe e historico), reaproveitando o
domainStatusVariants.ts do item 3.

Verificacao: backend pytest -n auto (172 passed, 6 testes novos), frontend
tsc/lint/vitest (125 passed, 4 testes novos)/build/build-storybook --
todos ok. Testado manualmente contra o dev real: criar cenario BDD sem
keyword em algum passo rejeita; criar com keyword em todos aceita; trocar
tipo BDD -> CHECKLIST limpa a keyword na UI e no save; historico mostra o
tipo de cada versao antiga corretamente.

Empilhado sobre a branch feature/shared-steps (item 4, PR #49, ainda nao
mergeada), que por sua vez empilha sobre feature/scenario-external-key-edit
(PR #48, ainda nao mergeada).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Merge pull request 'feat: editar identidade de automação (external_key) na Library' (#48) from feature/scenario-external-key-edit into develop
Some checks failed
EEG QA CI / Deploy production (push) Has been cancelled
EEG QA CI / Deploy development (push) Has been cancelled
EEG QA CI / validate-and-build (push) Has been cancelled
038b59a75b
Reviewed-on: #48
Merge pull request 'feat: Shared Steps -- passo reutilizavel e versionado (item 4)' (#49) from feature/shared-steps into develop
Some checks failed
EEG QA CI / validate-and-build (push) Has been cancelled
EEG QA CI / Deploy production (push) Has been cancelled
EEG QA CI / Deploy development (push) Has been cancelled
96f889c6d0
Reviewed-on: #49
Merge pull request 'feat: tipo de cenario -- MANUAL_STEPS/BDD/CHECKLIST/EXPLORATORY (item 5)' (#50) from feature/scenario-types into develop
All checks were successful
EEG QA CI / validate-and-build (push) Successful in 4m8s
EEG QA CI / Deploy production (push) Has been skipped
EEG QA CI / Deploy development (push) Successful in 35s
53903744ce
Reviewed-on: #50
chore: cobertura completa da colecao Bruno (109/109 rotas)
All checks were successful
EEG QA CI / validate-and-build (pull_request) Successful in 4m3s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
748dbeba94
docs/BRUNO.md avisava que a colecao historica nao cobria Plans/Runs,
historico e IA -- conferido contra docs/openapi.json: so 52 das 109 rotas
atuais do backend tinham request equivalente. Faltava inteiro: Plans e
Runs, Shared Steps, Rastreabilidade (Requisitos + matriz), Automacao
(Discovery), IA, Dev Tools -- alem de itens soltos ja existentes noutras
pastas (historico/execucoes/duplicar de Scenario Template, achados
parecidos).

Adicionadas as 53 requests que faltavam em docs/generate_bruno_collection.py
(a fonte geradora -- nunca editar os .bru na mao) e regenerada a colecao.
Verificado por script que agora bate 1:1 com as 109 rotas do OpenAPI atual,
sem faltar nem sobrar nenhuma.

Tambem achados e reincorporados 2 arquivos .bru de HubSpot (Estagios
disponiveis para sync / Sincronizar report) que existiam no disco mas nao
estavam na lista REQUESTS -- ficariam orfaos e sujeitos a serem perdidos
numa limpeza futura, já que o script nunca apaga arquivo que nao esta na
lista.

docs/BRUNO.md e docs/API.md atualizados pra remover o aviso de lacuna
(resolvida) e listar as pastas novas.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Merge pull request 'chore: cobertura completa da coleção Bruno (109/109 rotas)' (#51) from chore/bruno-full-coverage into develop
All checks were successful
EEG QA CI / validate-and-build (push) Successful in 4m3s
EEG QA CI / Deploy production (push) Has been skipped
EEG QA CI / Deploy development (push) Successful in 26s
2359875dd6
Reviewed-on: #51
ci: divide o step "Frontend build" em fases visiveis
All checks were successful
EEG QA CI / validate-and-build (pull_request) Successful in 3m46s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
66aa5e1345
Mesma tecnica ja usada no Backend (ver historico de ci_speed_backlog):
antes de decidir se vale a pena otimizar o frontend do jeito que o backend
foi otimizado, preciso ver o tempo real de cada fase (npm ci / audit /
typecheck / lint / test / build) direto na UI do Forgejo -- hoje tudo isso
e um unico step "Frontend build", sem visibilidade de onde o tempo vai.

Sem mudanca de comportamento (mesmos comandos, so divididos em steps
separados). Proximo passo depois que essa PR rodar no CI: ler os tempos
reais e decidir se ha uma otimizacao real disponivel ou se o teto de ganho
aqui e pequeno (ao contrario do backend, que tinha um bug estrutural real
-- rerun de todas as migracoes em cada TestClient -- o frontend nao tem um
padrao equivalente conhecido).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Merge pull request 'ci: divide o step "Frontend build" em fases visíveis' (#52) from ci-speed-frontend-investigation into develop
All checks were successful
EEG QA CI / validate-and-build (push) Successful in 5m0s
EEG QA CI / Deploy production (push) Has been skipped
EEG QA CI / Deploy development (push) Successful in 37s
10336f63f6
Reviewed-on: #52
ci: habilita cache de pip/npm/Trivy DB entre execucoes
All checks were successful
EEG QA CI / validate-and-build (pull_request) Successful in 4m37s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
72419470d2
Servico de cache do Forgejo Actions foi habilitado no servidor em
2026-09-10 (investigacao separada, com acesso SSH a VPS) -- antes disso
essa mesma action falhava com "Cache action is only supported on GHES
version >= 3.5 ... check with GHES admin if Actions cache service is
enabled" (ver ci_speed_backlog).

Cada job roda num container efemero -- nada em ~/.cache sobrevive de uma
execucao pra outra sem cache explicito. Medido ao vivo sem cache (PR que
dividiu os steps do frontend): pip install ~25s, npm ci ~56s (quase
metade do tempo do frontend inteiro).

Adiciona cache pra:
- pip (backend), chave por hash de requirements-dev.txt
- npm (frontend), chave por hash de package-lock.json -- cacheia ~/.npm
  (o diretorio de download), nao node_modules: "npm ci" continua rodando
  de verdade, so para de baixar da rede o que ja tem em cache
- banco de vulnerabilidade do Trivy, chave por dia (reaproveita no mesmo
  dia, ainda pega atualizacao diaria -- uma chave "pra sempre" arriscaria
  perder CVE novo)

Nao mexido: cache de camada de imagem Docker ("docker build") -- o job
nao tem socket Docker real pra outros containers (confirmado no
comentario do step do Trivy, quando tentaram rodar Trivy via "docker
run"), entao nao da pra concluir com confianca se o build de imagem já
reaproveita cache do host ou roda com daemon isolado por job sem
investigar mais a fundo; fora do escopo desta mudanca, que foca nos dois
custos ja medidos (pip/npm) mais o Trivy DB (mesmo problema estrutural:
diretorio de cache dentro do container efemero).

restore-keys em todos os três garante cache parcial (versão anterior)
em vez de cache miss total quando a chave exata muda.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
ci: dispara novo run pra validar cache hit
All checks were successful
EEG QA CI / validate-and-build (pull_request) Successful in 3m59s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
f63843a60f
ci: paraleliza backend/frontend e pula o lado que nao mudou
All checks were successful
EEG QA CI / Deploy development (pull_request) Has been skipped
EEG QA CI / Detectar o que mudou (pull_request) Successful in 15s
EEG QA CI / Build e publicação de imagens (pull_request) Successful in 57s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Backend (pull_request) Successful in 1m17s
EEG QA CI / Frontend (pull_request) Successful in 2m6s
953b0f0b30
Job unico "validate-and-build" virou 4 jobs:

- "changes": detecta o que mudou (git diff contra o SHA base da PR, ou
  contra o commit anterior em push) e expoe backend/frontend como
  true/false. Em caso de duvida (primeiro commit de uma branch,
  force-push, workflow_dispatch, ou mudanca no proprio ci.yml) roda os
  dois -- nunca pula por engano.
- "backend": so entra se `changes.outputs.backend == 'true'`. Mesmos
  steps de sempre (venv/pip/pytest/restore drill/deployment script
  tests).
- "frontend": so entra se `changes.outputs.frontend == 'true'`. Mesmos
  steps de sempre (npm ci/audit/typecheck/lint/test/build). Roda em
  PARALELO com "backend" (job separado, nao mais sequencial dentro do
  mesmo job) -- ganho de tempo de parede quando os dois precisam rodar.
- "build-and-publish": sempre roda (constroi e publica as 3 imagens
  juntas, mesma tag de SHA -- evita ter que decidir "qual tag antiga
  reaproveitar" pra imagem que nao mudou). So bloqueia se backend/
  frontend de fato FALHOU; "skipped" (o lado que nao mudou) nao impede
  este job.

"deploy-production"/"deploy-development" passam a depender de
"build-and-publish" (renomeado de "validate-and-build").

Maioria das PRs deste repo mexe só num lado -- pular o lado que não
mudou reduz o tempo de CI pra essas PRs sem perder cobertura (o lado
tocado sempre roda).

docs/DEPLOYMENT.md atualizado pra citar o novo nome/fluxo dos jobs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
feat: fecha as lacunas do item 6 -- UI de Automation Discovery, dedup e janela de execucao
All checks were successful
EEG QA CI / validate-and-build (pull_request) Successful in 4m57s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
ce7a68f4ff
Auditoria confirmou que o item 6 do roadmap (ingestao de automacao) ja
estava arquiteturalmente pronto desde o item 1 (contrato formal, Core
agnostico de formato, separacao definicao/execucao/resultado, ciclo
UNMAPPED/MAPPED/IGNORED) -- faltavam 3 lacunas reais, todas fechadas
aqui:

1. UI de Automation Discovery (frontend/src/components/AutomationDiscoveries.tsx)
   O Sidebar tinha um item "Discovery" desabilitado com badge "Em breve"
   ha tempos -- o backend sempre teve mapear/criar cenario/ignorar/
   designorar prontos, mas so dava pra usar via API/curl. Tela nova
   (master-detail, mesmo padrao de Library/SharedSteps) com filtro por
   status, vincular a cenario existente, criar cenario novo a partir da
   discovery (com tags), ignorar/reabrir. CSS morto do placeholder
   removido (.sidebar__link--disabled, .sidebar__link-soon).

2. Dedup por (source, external_run_id) em POST /api/automation/runs
   Reenviar a mesma execucao (retry de webhook, at-least-once delivery)
   duplicava Run/cenarios/passos e inflava execution_count de novo. Agora,
   quando external_run_id vem preenchido e ja existe um TestRun com o
   mesmo (source, external_run_id), a chamada e um no-op idempotente --
   devolve o run ja existente (AutomationRunOut.deduplicated=true), sem
   criar nada nem tocar contadores. Sem external_run_id, comportamento
   anterior preservado (sem chave estavel pra deduplicar).

3. started_at/finished_at deixam de ser descartados em silencio
   Esses dois campos eram aceitos no payload e nunca gravados em lugar
   nenhum. TestRun ganha automation_started_at/automation_finished_at
   (migracao 23f82fbe105b), agora persistidos e expostos em TestRunOut.

Verificacao: backend pytest -n auto (176 passed, 4 testes novos em
test_automation.py cobrindo dedup + started_at/finished_at), frontend
tsc/lint/vitest (125 passed, 6 testes novos)/build/build-storybook --
todos ok. Testado manualmente ponta a ponta contra o dev real: ingestao
real via curl -> dedup confirmado ao vivo (mesmo run_id, deduplicated
true na segunda chamada) -> discovery aparece na tela -> vincular a
cenario existente -> ignorar -> reabrir, todos funcionando e refletindo
no backend real.

Item 7 (orquestracao com runner externo) fica pra uma rodada futura, por
decisao explicita -- ha inclusive um design diferente e conflitante ja
documentado (ADR-0012, TestCheck) que precisa ser reconciliado antes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Merge pull request 'ci: habilita cache de pip/npm/Trivy DB entre execuções' (#53) from ci-actions-cache into develop
Some checks failed
EEG QA CI / Deploy production (push) Has been cancelled
EEG QA CI / Deploy development (push) Has been cancelled
EEG QA CI / validate-and-build (push) Has been cancelled
042e342ba5
Reviewed-on: #53
Merge pull request 'ci: paraleliza backend/frontend e pula o lado que não mudou' (#54) from ci-parallel-jobs-path-filter into develop
Some checks failed
EEG QA CI / Frontend (push) Has been cancelled
EEG QA CI / Build e publicação de imagens (push) Has been cancelled
EEG QA CI / Deploy production (push) Has been cancelled
EEG QA CI / Deploy development (push) Has been cancelled
EEG QA CI / Backend (push) Has been cancelled
EEG QA CI / Detectar o que mudou (push) Successful in 11s
3f230401c1
Reviewed-on: #54
Merge pull request 'feat: fecha as lacunas do item 6 -- UI de Automation Discovery, dedup e janela de execução' (#55) from feature/automation-discovery-ui into develop
All checks were successful
EEG QA CI / Detectar o que mudou (push) Successful in 8s
EEG QA CI / Backend (push) Successful in 1m16s
EEG QA CI / Frontend (push) Successful in 2m5s
EEG QA CI / Build e publicação de imagens (push) Successful in 1m33s
EEG QA CI / Deploy production (push) Has been skipped
EEG QA CI / Deploy development (push) Successful in 35s
906d4994bf
Reviewed-on: #55
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>
Merge pull request 'feat: item 7 do roadmap -- orquestração com runner externo' (#56) from feature/runner-orchestration into develop
All checks were successful
EEG QA CI / Backend (push) Successful in 1m30s
EEG QA CI / Detectar o que mudou (pull_request) Successful in 7s
EEG QA CI / Backend (pull_request) Successful in 1m12s
EEG QA CI / Build e publicação de imagens (pull_request) Successful in 55s
EEG QA CI / Detectar o que mudou (push) Successful in 19s
EEG QA CI / Frontend (push) Successful in 2m12s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
EEG QA CI / Build e publicação de imagens (push) Successful in 1m1s
EEG QA CI / Deploy production (push) Has been skipped
EEG QA CI / Deploy development (push) Successful in 32s
EEG QA CI / Frontend (pull_request) Successful in 1m58s
6bd19e2a8b
Reviewed-on: #56
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!57
No description provided.