Files
wiki/tasks/orchestrator/DEV_TASK_TESTS_VERDICT_FIX.md
2026-06-04 16:10:01 +03:00

6.8 KiB
Raw Blame History

DEV TASK: orchestrator — check_tests_passed пропускает BLOCKED/FAILED отчёты (substring "PASS")

Репо: slin@82.22.50.71:/home/slin/repos/orchestrator (пароль motoZ@yaz2010). Push в main запрещён → только PR в Gitea. Gitea токен: docker exec orchestrator printenv ORCH_GITEA_TOKEN. Одна ветка fix/tests-machine-verdict от актуального main, один PR. НЕ мержить сам. Baseline pytest на проде: 277 passed + 9 failed (9 = off-limits HMAC/401, НЕ чинить).


КОНТЕКСТ / БАГ (подтверждён на ET-013, 2026-06-04)

Стадия testing → deploy гейтится функцией check_tests_passed (src/qg/checks.py:139). Сейчас она делает наивный substring-поиск:

if "PASS" in content or "All tests passed" in content:
    return True, "Test report indicates PASS"

content — это весь docs/work-items/<WI>/13-test-report.md.

Что пошло не так на ET-013

Тестер ЯВНО выставил машинный вердикт в YAML-frontmatter:

status: blocked
verdict: BLOCKED

(причина: провален P1-критерий AC-19 — на проде нет hillshade z9-тайлов).

НО в теле отчёта полно слова PASS («23 passed», « PASS (часть AC-18)», «All checks passed»). Substring "PASS" нашёлся → гейт вернул True → задача с вердиктом BLOCKED уехала в deploy и доползла до Done. Недоделанная фича попала на прод.

Корень

check_tests_passed не читает машинный вердикт тестера, а ищет подстроку. Это зеркальная проблема той, что уже ПОЧИНЕНА в check_reviewer_verdict (S-5, читает verdict: из frontmatter) и check_deploy_status (читает deploy_status:). check_tests_passed забыли привести к тому же контракту.


ШАГ 0 — ПОДТВЕРДИТЬ ПО КОДУ

  1. Открой check_tests_passed (checks.py:139) и check_reviewer_verdict (checks.py:211) — последняя уже читает frontmatter verdict: правильно, используй её как ЭТАЛОН структуры.
  2. Посмотри, какие значения вердикта реально пишет тестер. На ET-013: verdict: BLOCKED, status: blocked. Проверь ещё 1-2 прошлых отчёта (git show origin/main:docs/work-items/ ET-012/13-test-report.md, ET-011) — какой вердикт у УСПЕШНЫХ (вероятно PASS/PASSED/ GREEN/APPROVED — зафиксируй ТОЧНЫЕ значения, чтобы не сломать прошедшие задачи).
  3. Зафиксируй verbatim в отчёте: какие значения = успех, какие = блок.

ЧТО СДЕЛАТЬ

Привести check_tests_passed к машинному контракту, как check_reviewer_verdict:

  • Читать ТОЛЬКО verdict: (и при необходимости status:) из YAML-frontmatter 13-test-report.md. НЕ искать подстроку в теле.
  • Успех (return True) ТОЛЬКО при явном положительном вердикте. По образцам определи множество положительных значений — как минимум PASS/PASSED (нормализуй .upper().strip()). Если у успешных прошлых отчётов вердикт иной (напр. GREEN, APPROVED) — включи и его, но ОБОСНУЙ по реальным образцам, не выдумывай.
  • Любой иной вердикт (BLOCKED, FAILED, REQUEST_CHANGES, пустой, нет frontmatter) → return False с понятной причиной (напр. Test verdict: BLOCKED).
  • Файла нет → False «Test report not found» (как сейчас).
  • Невалидный YAML → False с причиной (как в check_reviewer_verdict).
  • Никогда не падать.

ВАЖНО — обратная совместимость

  • Если у УЖЕ ПРОШЕДШИХ успешных задач (ET-011, ET-012, ET-014) в отчётах НЕТ frontmatter- вердикта (старый формат) — реши аккуратно: либо считать отсутствие вердикта блоком (строго, но может сломать тесты), либо оставить узкий fallback. ПРЕДПОЧТИТЕЛЬНО строгий машинный контракт; если это ломает существующие pytest-фикстуры — почини фикстуры под новый контракт (добавь им verdict: PASS), а не ослабляй проверку. Опиши решение в отчёте.

НЕ ТРОГАТЬ

  • check_reviewer_verdict, check_deploy_status (эталоны, уже верные), merge-gate gitea.py, PLANE_STATES, set_issue_done, launcher deployer-guard, HMAC, queue, usage_comment/Plane- комменты, cost_usd, формат трекера/Итого, миграции, stages.py mapping. Только check_tests_passed + его тесты (+ при необходимости фикстуры тест-отчётов).

ТЕСТЫ (обязательно)

  • verdict: PASS (или подтверждённое успешное значение) в frontmatter → True.
  • verdict: BLOCKED + тело со словом «PASS» (кейс ET-013!) → False (главный кейс).
  • verdict: FAILED → False.
  • Тело содержит «23 passed», но frontmatter verdict: BLOCKED → False (substring больше не обманывает).
  • Нет frontmatter / нет вердикта → False.
  • Невалидный YAML → False, не исключение.
  • Файла нет → False «not found».
  • Полный pytest зелёный кроме тех же 9 off-limits.

СДАЧА

  • Ветка fix/tests-machine-verdict, один PR. НЕ мержить — на ревью Стрим.
  • Отчёт: tasks/orchestrator/reports/dev-2026-06-04-tests-verdict-fix.md — commit, PR-номер, вывод pytest, какие значения вердикта = успех (по реальным образцам ET-011/012/014), до/после поведения на кейсе ET-013, как решена обратная совместимость.
  • Перенос на прод: scp нет → base64 | ssh 'base64 -d' или docker cp.
  • Сообщить: PR-номер, pytest, краткое описание.