Files
wiki/tasks/orchestrator/reports/dev-2026-06-04-tests-verdict-fix.md
2026-06-04 16:10:01 +03:00

7.2 KiB
Raw Blame History

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.pycheck_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.py HMAC/401 — подтверждено pre-existing: при застешенных моих правках на чистом main те же webhook-тесты падают (их число плавает 910 от запуска к запуску, порядко-зависимы). Мои изменения их не затрагивают (только check_tests_passed + его тесты). Прим.: baseline в ТЗ заявлен 277+9; фактический на этом окружении 276+10 до правки → 285+9 после (net +9 passed: класс вырос 3→11 тестов, минус один плавающий webhook-фейл).

Сдача

НЕ трогал

check_reviewer_verdict, check_deploy_status, gitea.py merge-gate, PLANE_STATES, set_issue_done, launcher deployer-guard, HMAC, queue, stages.py mapping.