diff --git a/tasks/orchestrator/DEV_TASK_ORCH39_FIX_WEBHOOK_TESTS.md b/tasks/orchestrator/DEV_TASK_ORCH39_FIX_WEBHOOK_TESTS.md new file mode 100644 index 0000000..9a55b5e --- /dev/null +++ b/tasks/orchestrator/DEV_TASK_ORCH39_FIX_WEBHOOK_TESTS.md @@ -0,0 +1,85 @@ +# DEV TASK — ORCH-39: Починить отставшие webhook-тесты после ORCH-10 + закрыть дыру CI + +## Контекст +ORCH-10 ввёл per-project резолвинг статусов Plane (`get_project_states(project_id)`). +4 теста не были обновлены под это и падают. CI на ветке показывал success при красных тестах +локально — значит CI гоняет не весь набор. Код прода (src/) ПРАВИЛЬНЫЙ — чинить ТОЛЬКО тесты + CI-конфиг. + +## Репозиторий / ветка +- Репо: `orchestrator` (Gitea `admin/orchestrator`) +- Базовая ветка: `main` (HEAD `053ea3b` на момент задачи) +- Новая ветка: `fix/ORCH-39-webhook-tests` +- PR в main, НЕ мержить (мержит ревьюер после проверки) + +## Падающие тесты (проверено лично 05.06) +1. `tests/test_m6_sequence.py::test_created_uses_plane_sequence_id` +2. `tests/test_m6_sequence.py::test_created_falls_back_to_db_when_plane_down` +3. `tests/test_plane_webhook.py::test_orchestrator_project_routes_to_orchestrator_repo` +4. `tests/test_plane_webhook.py::test_prefixes_independent_per_project` + +## КОРЕНЬ (точный диагноз) +Оба файла используют хардкод `_IN_PROGRESS = "b873d9eb-993c-48cd-97ac-99a9b1623967"` +(это **ET** in_progress UUID) в payload `state.id`, в т.ч. для запросов по **ORCH-проекту**. + +После ORCH-10 `src/webhooks/plane.py::handle_issue_updated` резолвит ожидаемый UUID так: +```python +proj_states = get_project_states(project_id) +if new_state == proj_states["in_progress"]: + await handle_status_start(...) +``` +Для ORCH-проекта `get_project_states(ORCH_PLANE_ID)["in_progress"]` = `e331bfb3-...`, НЕ `b873d9eb`. +`get_project_states` в тестах НЕ замокан → ходит в реальный Plane API (которого в тестах нет) +или отдаёт неподходящее значение → UUID не совпадает → pipeline не стартует → +задача не создаётся → `assert task is not None` падает. + +## Что сделать (ТОЛЬКО tests/ + ci.yml) + +### 1. Замокать `get_project_states` в обоих тест-файлах +В `tests/test_m6_sequence.py` и `tests/test_plane_webhook.py` в autouse-фикстуре (или per-test +patch) подменить `get_project_states`, чтобы он возвращал корректную карту per-project БЕЗ сети: +- для `ENDURO_PLANE_ID` → карту с `in_progress="b873d9eb-993c-48cd-97ac-99a9b1623967"`, + `approved="a519a341-dada-4a91-8910-7604f82b79c5"`, `rejected="ba958f3c-5db5-461d-8f82-89425e413b97"` +- для `ORCH_PLANE_ID` → `in_progress="e331bfb3-e17e-4699-ba48-4abb89c21b7b"`, + `approved="63f2c8fe-dcda-4ace-952f-dd88bd0118ff"`, `rejected="4c769e90-bf80-4a52-b97a-e1c84904bfc3"` + +ВАЖНО: мокать там, где функция РЕЗОЛВИТСЯ (`src.webhooks.plane.get_project_states` — она +импортируется внутри `handle_issue_updated` через `from ..plane_sync import get_project_states`, +проверь точку импорта; если импорт локальный — патчить `src.plane_sync.get_project_states`). + +И/ИЛИ: в каждом тесте слать `state.id` = UUID, соответствующий проекту запроса +(ORCH-тест шлёт `e331bfb3`, ET-тест шлёт `b873d9eb`). Выбери чистейший вариант — мок +предпочтительнее (детерминированно, без сети). + +### 2. Сбросить кэш состояний между тестами +Если `src/plane_sync.py` имеет `_STATES_CACHE` / `reload_project_states()` — вызывать сброс +в фикстуре (как уже делается `reload_projects()`), чтобы тесты не протекали друг в друга. + +### 3. Закрыть дыру CI +- Прочитать `.gitea/workflows/ci.yml`. +- Убедиться, что шаг pytest гоняет ВЕСЬ набор: `pytest tests/ -q` из корня репо с `PYTHONPATH`. +- Если запускается частично/из неверного пути/с фильтром — поправить, чтобы 4 этих файла + попадали в прогон. Цель: CI краснеет, если ЛЮБОЙ тест падает. + +## Команды проверки (обязательно прогнать ДО отчёта) +```bash +# в окружении с зависимостями (прод-образ орка) +docker exec -w -e PYTHONPATH= orchestrator python3 -m pytest tests/ -q -p no:cacheprovider +# Ожидаемо: 0 failed (~396 passed, 6 skipped) +# Отдельно убедиться что 4 целевых зелёные: +... pytest tests/test_m6_sequence.py tests/test_plane_webhook.py -q +``` + +## Off-limits (НЕ ТРОГАТЬ) +- `src/` — код webhook/plane_sync ПРАВИЛЬНЫЙ (per-project резолвинг — это фича ORCH-10) +- HMAC-механизм, 401/подпись тесты, QG-логика, config.py settings +- Любые тесты КРОМЕ двух указанных файлов (если другой тест придётся тронуть — сначала спросить) + +## Грабли (из прошлых сессий) +- Push: после push `git log origin/main..origin/` ДОЛЖЕН показать коммит ДО отчёта «PR готов». +- Тесты НЕ в docker-образе (Dockerfile COPY только src/+data/) → гонять из клона репо, не из /app. +- Интерференция через синглтон settings: autouse-фикстура с monkeypatch (см. conftest.py паттерн PR #27). +- Не регистрировать раннеров, не nohup. + +## Результат +PR `fix/ORCH-39-webhook-tests` → main, 0 failed, CI ловит весь набор. Отчёт в +`tasks/orchestrator/reports/dev-2026-06-05-orch39-webhook-tests.md`.