7.2 KiB
Dev Report: orchestrator — check_tests_passed машинный вердикт (ET-013 fix)
Дата: 2026-06-04 Статус: DONE
Задача
check_tests_passed (src/qg/checks.py:139) гейтила стадию testing→deploy наивным
substring-поиском if "PASS" in content по всему телу 13-test-report.md. На ET-013
тестер выставил verdict: BLOCKED / status: blocked (провален P1 AC-19), но в теле
были слова «23 passed», «✅ PASS», «All checks passed» → substring нашёлся → True →
недоделанная фича уехала в deploy и доползла до Done. Нужно привести функцию к
машинному контракту, как у уже починённых check_reviewer_verdict и check_deploy_status.
Сделано
- ШАГ 0: изучил
check_reviewer_verdict(эталон, читаетverdict:из frontmatter) - Собрал РЕАЛЬНЫЕ значения вердикта по прошлым отчётам ET-001..ET-014
- Переписал
check_tests_passed+ добавил_parse_tests_verdict(зеркало эталона) - Обновил/расширил тесты
TestCheckTestsPassed(3 → 11 тестов) - Прогнал unit + полный pytest
- Провалидировал на РЕАЛЬНЫХ отчётах прод-репозитория
- Ветка
fix/tests-machine-verdict, push, PR #24 (НЕ мержил)
Изменённые файлы
src/qg/checks.py—check_tests_passedтеперь читает ТОЛЬКО frontmatter; новый helper_parse_tests_verdict. НЕ трогал check_reviewer_verdict / check_deploy_status.tests/test_qg.py— классTestCheckTestsPassedпереписан под машинный контракт.
Положительные значения вердикта по РЕАЛЬНЫМ образцам (verbatim)
| WI | verdict (raw) | status (raw) | трактовка |
|---|---|---|---|
| ET-001 | PASS |
pass |
✅ True |
| ET-002 | PASS |
pass |
✅ True |
| ET-005 | PASS |
pass |
✅ True |
| ET-006 | ready-to-deploy |
PASSED |
✅ True |
| ET-007 | PASS — ready-to-deploy |
PASS |
✅ True |
| ET-008 | stage:ready-to-deploy |
pass |
✅ True |
| ET-009 | PASS |
PASS |
✅ True |
| ET-011 | PASS |
(нет) | ✅ True |
| ET-012 | PASS |
ready-to-deploy |
✅ True |
| ET-013 | BLOCKED |
blocked |
❌ False |
| ET-014 | PASS |
(нет) | ✅ True |
Вывод: поле verdict у тестера НЕ единообразно. Чисто verdict == "PASS"
сломал бы ET-006 (ready-to-deploy) и ET-008 (stage:ready-to-deploy). Поэтому:
- Positive tokens (нормализация
.upper().strip(), поиск токена вverdict+status):PASSED,PASS,READY-TO-DEPLOY,READY_TO_DEPLOY,GREEN,APPROVED. - Negative tokens (авторитетны):
BLOCKED,FAILED,FAIL,REQUEST_CHANGES,REJECT,RED. - Логика: нет frontmatter / битый YAML / нет ни verdict ни status → False с причиной; негативный токен в любом из полей → False (перебивает любой PASS); иначе позитивный токен → True; иначе → False. Никогда не падает.
Результат — до/после на ET-013 (на реальном файле прод-репо)
- До: substring
"PASS"в теле →(True, "Test report indicates PASS")→ deploy. - После:
_parse_tests_verdict→(False, 'Test verdict: BLOCKED (BLOCKED)')→ блок.
Прогон на РЕАЛЬНЫХ отчётах (/repos/_wt/enduro-trails/feature_ET-014-ui-z-index):
ET-001 (True, 'Test verdict: PASS (PASS)')
ET-005 (True, 'Test verdict: PASS (PASS)')
ET-006 (True, 'Test verdict: READY-TO-DEPLOY (PASS)')
ET-007 (True, 'Test verdict: PASS — READY-TO-DEPLOY (PASS)')
ET-008 (True, 'Test verdict: STAGE:READY-TO-DEPLOY (PASS)')
ET-009 (True, 'Test verdict: PASS (PASS)')
ET-011 (True, 'Test verdict: PASS (PASS)')
ET-012 (True, 'Test verdict: PASS (PASS)')
ET-013 (False, 'Test verdict: BLOCKED (BLOCKED)') <-- bug fixed
ET-014 (True, 'Test verdict: PASS (PASS)')
Все 9 ранее прошедших WI остаются True; ET-013 → False. Регрессий нет.
Обратная совместимость
Строгий машинный контракт сохранён БЕЗ ослабления: у всех реальных прошедших отчётов
ЕСТЬ frontmatter с положительным verdict:/status:, поэтому fallback на тело не нужен.
Единственная «несовместимость» была в старых pytest-фикстурах (Result: PASS в теле без
frontmatter) — они описывали старое substring-поведение. Согласно ТЗ их ПОЧИНИЛ под новый
контракт (добавил frontmatter verdict:), а не ослабил проверку. Отсутствие frontmatter
теперь = False (test_no_frontmatter_fails).
Тесты (pytest, прод-контейнер на /repos/orchestrator)
TestCheckTestsPassed: 11 passed (включая главный кейс ET-013, FAILED, "23 passed" в теле при BLOCKED, нет frontmatter, нет полей, битый YAML, файла нет).- Полный прогон: 285 passed, 9 failed. 9 failed = off-limits
test_webhooks.pyHMAC/401 — подтверждено pre-existing: при застешенных моих правках на чистом main те же webhook-тесты падают (их число плавает 9–10 от запуска к запуску, порядко-зависимы). Мои изменения их не затрагивают (толькоcheck_tests_passed+ его тесты). Прим.: baseline в ТЗ заявлен 277+9; фактический на этом окружении 276+10 до правки → 285+9 после (net +9 passed: класс вырос 3→11 тестов, минус один плавающий webhook-фейл).
Сдача
- Ветка:
fix/tests-machine-verdict(от актуального origin/main, push выполнен). - PR: #24 — http://localhost:3000/admin/orchestrator/pulls/24 (внешний: https://git.mva154.duckdns.org/admin/orchestrator/pulls/24). НЕ мержил — на ревью Стрим.
- В main НЕ пушил.
НЕ трогал
check_reviewer_verdict, check_deploy_status, gitea.py merge-gate, PLANE_STATES, set_issue_done, launcher deployer-guard, HMAC, queue, stages.py mapping.