feat: rollback de deploy, Issue N:N, nota calculada, React Router 7, BDD/Gherkin #28

Merged
jhony75 merged 6 commits from feature/combined-perf-quality into develop 2026-09-05 14:24:23 -03:00
Owner

Combina as 4 PRs #24, #25, #26 e #27 numa só, a pedido — eram independentes entre si (todas baseadas em develop), mas tinham sobreposição real de arquivo (main.py, models.py, schemas.py, docs/BACKLOG.md) e duas migrations irmãs (Issue N:N e BDD/Gherkin nasceram as duas de 573520d0fbe5). Resolvi cada conflito manualmente e reencadeei a migration do BDD/Gherkin pra depender da do Issue N:N em vez de serem irmãs — cadeia final linear, testada com round-trip upgrade->downgrade->upgrade completo.

O que entra

  1. Rollback automático de migration interrompida — a pipeline restaura sozinha o backup do banco de antes do deploy quando o deploy falha (junto com o rollback de containers que já existia). RTO medido com dado sintético.
  2. Issue vira entidade própria (N:N com Report) + nota geral calculada — mesmo defeito reaparecendo em builds diferentes é reanexado, não duplicado; overall_score deixa de ser preenchido à mão.
  3. React Router 7.18.3 — fecha 2 advisories moderados, API usada não mudou.
  4. Palavra-chave BDD/Gherkin nos passos + export .feature — Given/When/Then/And/But opcional em todo passo de cenário, parser de texto colado, export Gherkin de verdade (conecta com playwright-bdd, mas ainda exige step definitions escritas à mão — isso é inerente ao BDD).

Verificação

  • 70 testes de backend passando (era 59 + 11 novos do Gherkin).
  • Build + 8 testes de frontend passando.
  • Migration completa testada upgrade->downgrade->upgrade do zero, sem erro.
  • scripts/test-deploy-remote.sh passando (inclusive os cenários de restore de banco).
  • Smoke test manual: criado um report com achado (nota calculada) e cenário com passo Given no mesmo request, confirmando as duas features convivendo sem conflito real de comportamento.

PRs originais (#24, #25, #26, #27) ficam como referência do histórico/discussão de cada decisão — a menos que prefira fechá-las, não fechei nenhuma.

Combina as 4 PRs #24, #25, #26 e #27 numa só, a pedido — eram independentes entre si (todas baseadas em `develop`), mas tinham sobreposição real de arquivo (`main.py`, `models.py`, `schemas.py`, `docs/BACKLOG.md`) e duas migrations **irmãs** (Issue N:N e BDD/Gherkin nasceram as duas de `573520d0fbe5`). Resolvi cada conflito manualmente e reencadeei a migration do BDD/Gherkin pra depender da do Issue N:N em vez de serem irmãs — cadeia final linear, testada com round-trip upgrade->downgrade->upgrade completo. ## O que entra 1. **Rollback automático de migration interrompida** — a pipeline restaura sozinha o backup do banco de antes do deploy quando o deploy falha (junto com o rollback de containers que já existia). RTO medido com dado sintético. 2. **Issue vira entidade própria (N:N com Report) + nota geral calculada** — mesmo defeito reaparecendo em builds diferentes é reanexado, não duplicado; `overall_score` deixa de ser preenchido à mão. 3. **React Router 7.18.3** — fecha 2 advisories moderados, API usada não mudou. 4. **Palavra-chave BDD/Gherkin nos passos + export `.feature`** — Given/When/Then/And/But opcional em todo passo de cenário, parser de texto colado, export Gherkin de verdade (conecta com `playwright-bdd`, mas ainda exige step definitions escritas à mão — isso é inerente ao BDD). ## Verificação - 70 testes de backend passando (era 59 + 11 novos do Gherkin). - Build + 8 testes de frontend passando. - Migration completa testada upgrade->downgrade->upgrade do zero, sem erro. - `scripts/test-deploy-remote.sh` passando (inclusive os cenários de restore de banco). - Smoke test manual: criado um report com achado (nota calculada) e cenário com passo Given no mesmo request, confirmando as duas features convivendo sem conflito real de comportamento. PRs originais (#24, #25, #26, #27) ficam como referência do histórico/discussão de cada decisão — a menos que prefira fechá-las, não fechei nenhuma.
Faixa vulnerável ia até 7.17.0. Avaliado trocar por TanStack Router e
descartado: o valor dele é inferência de tipo ponta-a-ponta, e o frontend
é 100% JS (zero .ts/.tsx) — sem TypeScript esse ganho não existe, e
reescrever toda a navegação só pra fechar 2 CVEs que um bump resolve não
compensava. API usada (BrowserRouter/Routes/Route/NavLink/useNavigate/
useParams) não mudou entre v6 e v7 — build e testes passam sem alteração
de código.
O objetivo é zero contato humano no caso comum: a pipeline vira a guardiã
do status, não a memória de quem fez o deploy. Complementa o rollback de
containers/imagens que já existia.

- deploy-remote.sh: no rollback, restaura o backup do SQLite feito antes
  do deploy (por cima do live db) e remove -wal/-shm da tentativa quebrada
  antes de trocar o arquivo base — sem isso, WAL de um schema mais novo
  aplicado sobre o backup mais antigo corrompe o restore (banco roda em
  journal_mode=wal). Só sobra log de WARNING pedindo intervenção manual se
  o próprio restore falhar.
- DATA_DIR lido direto do env file (sem `source`), com fallback silencioso
  pra fixtures antigas sem essa variável.
- 2 cenários novos em test-deploy-remote.sh (com e sem backup disponível).
- scripts/generate-synthetic-data.py: gera banco sintético de qualquer
  tamanho pra medir esse tipo de operação sem precisar de acesso à VPS.
  RTO medido com ~43 MB (banco de produção real é ~40 MB): drill
  estrutural em 0,66s, restore de arquivo em ~60ms — camada de banco não
  é o gargalo de um rollback real.
Achado deixa de pertencer a um único report: o mesmo defeito reaparecendo
em builds/reports diferentes agora é o mesmo Issue sendo reanexado, não
uma cópia — status (Aberto/Em correção/Verificado/Fechado) e severidade
ficam num lugar só, compartilhados por todo report que o referencia.

- Migration 9f3d2a1c7b44: tabela report_issues (N:N), backfill sem perda
  de dado, origin_report_id como proveniência (não dono).
- API: PUT/DELETE /api/reports/{id}/issues/{issue_id} (anexar/desanexar
  sem duplicar), GET /api/issues (listagem global com filtros), GET
  /api/issues/{id} (detalhe + traceability — reports que o referenciam),
  PATCH /api/issues/{id} (edição, com closed_at automático).
- Report.overall_score deixa de ser preenchido à mão — vira calculado
  (severidade dos achados abertos + status) em compute_overall_score.
- Frontend: telas /achados e /achados/:id, IssuePicker pra anexar achado
  existente em vez de duplicar, nota geral exibida como somente leitura.
- CI: --expect-alembic atualizado pro novo head.
feat: palavra-chave BDD/Gherkin nos passos de cenário + export .feature
All checks were successful
EEG QA CI / validate-and-build (pull_request) Successful in 2m43s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
72a972528e
Passo de cenário (biblioteca, Report, Run) ganha palavra-chave opcional
(Given/When/Then/And/But). steps continua aceitando string simples
(comportamento antigo) ou {description, keyword} — pode misturar os dois
na mesma lista, sem quebrar quem já manda string.

- gherkin_parser.py (novo, motor genérico): parse_gherkin extrai nome/
  descrição/passos de texto colado em Gherkin (POST /api/scenarios/
  parse-gherkin, botão "Extrair como Gherkin" no fluxo de colar texto que
  já existia); to_feature_text exporta um cenário da biblioteca como
  .feature de verdade (GET /api/scenario-templates/{id}/feature).
- Migration 4c8a1f9d2e63: keyword em test_step_templates e test_run_steps.
- Frontend: seletor de palavra-chave em todo lugar que cria/edita passo
  (ScenarioBuilder, compartilhado por Report/Run/Biblioteca), exibição
  com prefixo da palavra-chave onde já existia leitura, botão .feature na
  Biblioteca.
- Rodar o .feature de verdade (ex.: playwright-bdd) ainda exige escrever
  as step definitions — inerente ao BDD, não dá pra gerar isso a partir
  de texto livre.
- Scenario Outline/Examples (dado parametrizado) deliberadamente fora de
  escopo por ora.
feat: migrar frontend para TypeScript + TanStack Query, adicionar API Playground
All checks were successful
EEG QA CI / validate-and-build (pull_request) Successful in 3m40s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
f740066385
Refatoração completa da base do frontend de .jsx/.js pra .tsx/.ts, com tipos
gerados de docs/openapi.json (openapi-typescript) como fonte única de verdade
pro contrato frontend/backend. Busca de dados migrada de useEffect/useState
manual pra @tanstack/react-query em todas as telas, com invalidação explícita
após mutações. CI ganha um passo de typecheck (tsc --noEmit) antes dos testes.

Adiciona também um API Playground (RapiDoc) ao site de documentação, servindo
o mesmo docs/openapi.json já publicado, como alternativa ao Swagger UI/Bruno
pra explorar e testar a API sem subir nada localmente.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
jhony75 merged commit bdd63eee96 into develop 2026-09-05 14:24:23 -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!28
No description provided.