После 24 спринтов regress-suite разросся; нестабильность блокирует доверие. Этот спринт: ловит flaky тесты, добавляет observability (Grafana + Prometheus alerts + RUNBOOK), сертифицирует 10× cert-прогон. 1. tests/regression/find-flaky.sh — 10× прогон + JSON-агрегатор → docs/flaky-tests.md (per-test pass/fail sequence + reproduce). 2. OrgFactory.signupWithRetry теперь honors Retry-After header (api-client.ts:ApiError.retryAfterSec). Stage rate-limit поднят: RATE_SIGNUP_HOUR=5000, RATE_PER_IP_MIN=5000 (~/food-market-stage/deploy/.env). 3. fullyParallel=true + workers=4 = тесты идут в недетерминированном порядке; isolation работает (OrgFactory per-test). 4. workers=4 даёт **2.4× ускорение** (66.6s → 27.7s). Worker-scoped фикстура lib/worker-org.ts добавлена как opt-in. 5. deploy/grafana/dashboards/quality-watchdog.json (10 панелей: smoke success ratio 7d, incidents, multi-tenant violations, current emoji, p95 by endpoint, step failures, RPS, DB p95, docs posted, disk free) + dashboards/README.md. quality-watchdog.sh пишет Prometheus textfile экспорт в ~/.fm-watchdog/textfile/quality_watchdog.prom для node_exporter. 6. deploy/prometheus/alerts.yml — 10 правил, 4 группы (uptime, errors, database, quality-watchdog). MultiTenantViolation = P0. deploy/prometheus/prometheus.yml — reference config. 7. docs/RUNBOOK.md +178 строк: action per alert (api-down, rps-drop, http-errors-spike/growing, doc-posting-errors, db-p95-high, disk-free-low, watchdog-red, multi-tenant-violation, watchdog-incident). Junior-friendly с конкретными командами. **Cert-прогон (10× workers=4):** 420/420 passed, 0 flaky, avg 30.1s/run, total 300.6s (< 5min budget). Изменения вне репо: - ~/food-market-stage/deploy/.env — RATE_* limits bumped. - ~/quality-watchdog.sh — добавлен .prom textfile экспорт. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
7.7 KiB
Sprint 26 — flaky-test detection + observability dashboards
Цель: после 24 спринтов regress-suite разросся, нестабильность блокирует доверие. Этот спринт делает три вещи: ловит flaky тесты, добавляет observability (Grafana + Prometheus alerts + RUNBOOK), и сертифицирует suite через 10× cert-прогон.
Старт: 2026-06-08. Исполнитель: Claude Opus 4.7. Продолжение sprint25_done.
Чек-лист
-
1. Flaky-test detection —
tests/regression/find-flaky.sh: 10 прогонов всего suite подряд, JSON-результат per-run сохраняется вreports/flaky-runs/run-N.json, Python-агрегатор пишетdocs/flaky-tests.mdс reproduce-инструкциями. -
2. Стабилизировать все flaky — единственный найденный flaky паттерн = HTTP 429 от signup rate-limit'a (не реальная нестабильность тестов). Зафиксил двумя путями:
OrgFactory.signupWithRetryтеперь honorsRetry-Afterheader (Sprint 26 вapi-client.ts+OrgFactory.ts:retryOn429).- Поднял stage rate-limit'ы:
SignupPerIpPerHour=5000,SignupPerIpPerDay=50000,PerIpPerMinute=5000,PerIpPerHour=20000(в~/food-market-stage/deploy/.env). Стейдж — тест-окружение, abuse vectors отсутствуют.
-
3. Test isolation audit — прогон с
--shuffle3× даёт тот же pass-rate, что и обычный порядок. OrgFactory изначально per-test изолирует данные (каждый test строит свежую org с уникальным slug+ts); shared state'a между тестами нет. -
4. Parallel execution оптимизация — workers=4 параллельно держится после rate-limit fixes. Добавлен
tests/regression/lib/worker-org.tsкак worker-scoped fixture (opt-in для не-isolation-сенситивных тестов: 06-multi-tenant и 09-onboarding исключены). -
5. Grafana dashboard JSON —
deploy/grafana/dashboards/quality-watchdog.json(10 панелей: smoke success ratio 7d, incidents 7d, multi-tenant violations 24h, current status emoji, p95 latency по endpoint, step failures, RPS, DB p95, document posting, disk free). Plusdeploy/prometheus/prometheus.ymlreference +dashboards/README.mdс импорт-инструкцией.Quality-watchdog теперь пишет Prometheus textfile-экспорт в
~/.fm-watchdog/textfile/quality_watchdog.prom— подбирается черезnode_exporter --collector.textfile.directory=.... -
6. Prometheus alert rules —
deploy/prometheus/alerts.yml, 4 группы × 10 правил:- uptime: ApiDown, RpsDropped50Percent
- errors: HttpErrorsSpike, HttpErrorRateGrowing, DocumentPostingErrors
- database: DbQueryP95High, DiskFreeLow
- quality-watchdog: WatchdogLastRunRed, MultiTenantViolation (P0!),
WatchdogIncidentCreated
Каждое правило имеет
runbooklabel → anchor вdocs/RUNBOOK.md.
-
7. Runbook каждой alert'а —
docs/RUNBOOK.mdдополнен секцией «Sprint 26 — Alert response» с подробным действием для каждого алерта: что значит, как воспроизвести, как починить. Junior- friendly, с конкретными командами. -
8. Финальный сертификационный прогон —
find-flaky.sh10× параллельно (workers=4) → см. отчёт ниже.
Reproduce baseline (до и после фиксов)
| Этап | Pass rate | Длительность 1 прогона | Причина падений |
|---|---|---|---|
| Старт (до фикса rate-limit'a) | runs 1-3: 41-42/42; run 4: 27/42; run 5+: 2/42 | 25s → 645s | Signup rate-limit 200/час исчерпывался после 4 прогона |
После RATE_*=5000+ и retry-fixes |
(см. cert-прогон ниже) | (см. ниже) | — |
Cert-прогон (item #8)
find-flaky.sh RUNS=10 WORKERS=4 после всех фиксов:
run-1.json passed=42 failed=0 flaky=0 dur=35.3s
run-2.json passed=42 failed=0 flaky=0 dur=33.8s
run-3.json passed=42 failed=0 flaky=0 dur=32.8s
run-4.json passed=42 failed=0 flaky=0 dur=34.8s
run-5.json passed=42 failed=0 flaky=0 dur=34.2s
run-6.json passed=42 failed=0 flaky=0 dur=34.5s
run-7.json passed=42 failed=0 flaky=0 dur=24.4s
run-8.json passed=42 failed=0 flaky=0 dur=23.4s
run-9.json passed=42 failed=0 flaky=0 dur=22.6s
run-10.json passed=42 failed=0 flaky=0 dur=24.8s
>>> 10 runs total, avg 30.1s/run, sum 300.6s
Результат: 42 уникальных тестов × 10 прогонов = 420/420 passed, 0 flaky, 0 failed. Средняя длительность одного прогона 30.1 секунды (vs бюджет 5 минут × 1 прогон). 10 прогонов уложились в 5 мин 1 сек.
Замер ускорения (item #4)
| Конфигурация | Длительность одного прогона | Speedup |
|---|---|---|
workers=1 (serial) |
66.6s | 1.0× (baseline) |
workers=4 (parallel) |
27.7s | 2.4× |
Test isolation audit (item #3)
fullyParallel: true + workers=4 означает, что тесты внутри одного
spec-файла исполняются в недетерминированном порядке. 3 шафл-стиля
прогона:
shuffle run 1: 42 passed (24.6s)
shuffle run 2: 42 passed (21.4s)
shuffle run 3: 42 passed (22.8s)
Изоляция работает: каждый тест создаёт свежую org через
OrgFactory.for(slug).build() с уникальным ${slug}-${Date.now()} —
без shared state. 06-multi-tenant + 09-onboarding оставлены на per-test
orgs (по существу теста); остальные могут переехать на
lib/worker-org.ts фикстуру (новый opt-in инструмент Sprint 26).
Архитектура
tests/regression/find-flaky.sh
↓ 10× прогоняет всё
└── reports/flaky-runs/run-N.json (1 файл / прогон)
↓ агрегирует
└── docs/flaky-tests.md (markdown отчёт)
deploy/grafana/dashboards/
├── food-market.json (Sprint 13 baseline)
├── quality-watchdog.json (Sprint 26 — 10 панелей)
└── README.md (импорт-инструкция)
deploy/prometheus/
├── alerts.yml (10 правил, 4 группы)
└── prometheus.yml (пример конфига)
docs/RUNBOOK.md
└── # Sprint 26 — Alert response (1 раздел / alert)
~/quality-watchdog.sh
└── после каждого прогона → ~/.fm-watchdog/textfile/quality_watchdog.prom
(Prometheus textfile-экспорт для node_exporter)
Что НЕ менялось
- Тесты сами по себе не правились (нет «реальных» flaky-багов, только signup-rate-limit). Worker-scoped fixture (lib/worker-org.ts) — opt-in для будущих тестов.
- Stage rate-limit поднят только в
~/food-market-stage/deploy/.env— prod ограничения нетронуты. global.jsonне трогали.