auto-sync: 2026-06-04 22:10:01

This commit is contained in:
Stream
2026-06-04 22:10:14 +03:00
parent fea11cb581
commit 5b2b80b38e
2 changed files with 97 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
# DEV TASK — изолировать 3 теста от живого Plane API (сделать CI зелёным)
**Проект:** orchestrator | **Сервер:** slin@82.22.50.71 (pw motoZ@yaz2010, ConnectTimeout=15, StrictHostKeyChecking=no) | **Репо (хост):** /home/slin/repos/orchestrator | **Контейнер:** orchestrator (порт 8500)
**Ветка:** `fix/isolate-webhook-tests-from-plane` из свежего origin/main (`git fetch origin main && git checkout -B fix/isolate-webhook-tests-from-plane origin/main`).
## Контекст / зачем
В PR #26 мы впервые включили Gitea CI для orchestrator. CI прогнал тесты в чистом окружении (БЕЗ сети к Plane) и **3 теста упали** — они дёргают живой Plane API и в CI получают `Connection refused`. Это **дефект изоляции тестов** (pre-existing), а не баг кода. Локально на хосте они «проходят» только потому что там живой Plane под боком. Нужно замокать сетевые вызовы Plane в этих 3 тестах → CI станет зелёным → гейт качества для self-hosting orchestrator заработает честно.
**ВАЖНО: чинить ТОЛЬКО тесты (`tests/test_webhooks.py`). НЕ трогать `src/`, логику, поведение.** Задача — добавить недостающие `@patch`, тесты по сути не переписывать.
## Точная причина каждого падения (проверено на проде)
### Тест 1 — `test_plane_webhook_creates_task` (tests/test_webhooks.py:59)
- Путь `work_item.created``handle_work_item_created` → внутри вызывается `fetch_issue_sequence_id(plane_id, plane_project_id)` (`src/webhooks/plane.py:448-449`) — **сетевой вызов к Plane**. В CI `Connection refused` → исключение прерывает цепочку ДО `INSERT INTO tasks``assert task is not None` падает.
- Код задуман с fallback: если `fetch_issue_sequence_id` вернёт `None` → берётся `get_next_work_item_id` (DB-инкремент). Но реальный сетевой сбой бросает exception, а не None.
- **Фикс теста:** добавить `@patch` на `src.webhooks.plane.fetch_issue_sequence_id``return_value = None` (штатный fallback на DB-инкремент, поведение кода НЕ меняется, просто без сети). Также замокать `src.webhooks.plane.add_comment` (вызывается на :534 после создания, тоже сетевой) — `new_callable=MagicMock`.
- Образец: тест уже мокает `_create_gitea_branch` и `_create_initial_docs` (AsyncMock) — добавить ещё два @patch к этим.
### Тест 2 — `test_gitea_push_with_adr_advances_stage` (tests/test_webhooks.py:206)
- Путь gitea push → `handle_push` → после advance вызывается `plane_notify_stage(work_item_id, ...)` (`src/webhooks/gitea.py:129`) — сетевой вызов к Plane → `Connection refused` → исключение валит до `mock_launcher.launch.assert_called_once()` (launch вызывается 0 раз / падает раньше).
- **Фикс теста:** добавить `@patch("src.webhooks.gitea.plane_notify_stage")` (MagicMock).
### Тест 3 — `test_gitea_ci_failure_on_development_notifies_qg_failure` (tests/test_webhooks.py:278)
- Тот же класс проблемы: путь gitea status=failure на development. Проверь точно, какой сетевой вызов Plane срабатывает на этом пути (вероятно `plane_notify_stage` или `add_comment` в gitea.py при notify_qg_failure-ветке ~:217-223). Замокать ровно тот, что лезет в сеть.
- **Фикс теста:** добавить недостающий `@patch` на сетевой Plane-вызов в этом пути (`src.webhooks.gitea.plane_notify_stage` и/или соответствующий). НЕ трогать assert'ы про `mock_notify`/`check_ci_green`/stage.
## Рабочие образцы моков (уже в этом файле, копировать стиль)
- `tests/test_webhooks.py:151-154``@patch("src.webhooks.plane.httpx.get")` (как мокают сеть в plane).
- `tests/test_webhooks.py:241-246``@patch("src.webhooks.gitea.check_ci_green")` + `@patch("src.webhooks.gitea.launcher")` (как мокают gitea-путь). Тест `test_gitea_ci_success_advances_to_review` рядом — успешный близнец, посмотри, что он мокает, и сделай по аналогии.
- Импорты уже есть: `from unittest.mock import patch, MagicMock, AsyncMock` (строка 5).
## Принцип (не нарушать)
- Мокать НАДО **место вызова** (`src.webhooks.plane.X` / `src.webhooks.gitea.X`), а не источник в `plane_sync`, т.к. некоторые импорты локальные внутри функций — мок источника не перехватит. Смотри как сделано в conftest.py для send_telegram (там описано почему патчат именно место связывания).
- Если функция импортируется ЛОКАЛЬНО внутри тела (`from ..plane_sync import add_comment` внутри функции) — патчить надо `src.plane_sync.add_comment` (источник), т.к. локальный импорт резолвится в рантайме из источника. Определи для каждого вызова: модульный импорт вверху файла → патчить место (`src.webhooks.X.name`); локальный импорт внутри функции → патчить источник (`src.plane_sync.name`). Это критично, проверь по факту, не угадывай.
## Проверка (выполнить и приложить пруф)
1. Прогнать ровно эти 3 теста как в CI (чистое окружение, read-only, без .env):
```
docker run --rm -v /home/slin/repos/orchestrator:/code:ro -w /code -e PYTHONPATH=/code \
--entrypoint python3 $(docker inspect orchestrator --format '{{.Config.Image}}') \
-m pytest tests/test_webhooks.py::test_plane_webhook_creates_task \
tests/test_webhooks.py::test_gitea_push_with_adr_advances_stage \
tests/test_webhooks.py::test_gitea_ci_failure_on_development_notifies_qg_failure -q
```
— должно быть **3 passed**.
2. Прогнать ВЕСЬ test_webhooks.py тем же способом — убедиться, что ничего не сломал (не появилось новых fail сверх известных 9 HMAC/401, которые из-за .env и в read-only без .env ведут себя стабильно — зафиксируй число).
3. После push ветки: убедиться, что Gitea Actions прогнал workflow и job test → **success** (`/api/v1/repos/admin/orchestrator/actions/tasks`, токен `docker exec orchestrator printenv ORCH_GITEA_TOKEN`).
4. `git log origin/main..origin/fix/isolate-webhook-tests-from-plane` показывает коммит ДО отчёта.
## Ограничения / правила
- ⚠️ PR в Gitea, push в main ЗАПРЕЩЁН (pre-receive hook). НЕ мержить самому — мержит ревьюер (Стрим). Только ветка + PR.
- Менять ТОЛЬКО `tests/test_webhooks.py`. НЕ трогать src/, off-limits тесты (9 HMAC/401), conftest.py, workflow-файл.
- Conventional Commits, один коммит: `test: isolate webhook tests from live Plane API (fix CI)`.
- ⚠️ **НЕ регистрировать новых раннеров, НЕ запускать ничего через nohup.** Раннер orchestrator уже есть (`mva154-runner-orch`). Если CI не подхватывает — СТОП, отчёт, НЕ плоди процессы.
- Если факт ТЗ разошёлся с реальностью — СТОП, отчёт с вопросом.
## Результат
- PR с правкой только `tests/test_webhooks.py`, 3 целевых теста зелёные в чистом окружении, workflow прогнан и job test = success, отчёт с пруфом. Сохрани отчёт в `tasks/orchestrator/reports/dev-2026-06-04-fix-plane-mocks.md`.

View File

@@ -0,0 +1,39 @@
# Dev Report: isolate webhook tests from live Plane API (fix CI)
Дата: 2026-06-04
Статус: IN PROGRESS
## Задача
Замокать сетевые Plane-вызовы в 3 тестах tests/test_webhooks.py чтобы они проходили в чистом CI-окружении без доступа к Plane API.
## Анализ
### Тест 1 — test_plane_webhook_creates_task
- plane.py:448-449: `from ..plane_sync import fetch_issue_sequence_id` — локальный импорт → патчить `src.plane_sync.fetch_issue_sequence_id`
- plane.py:534: `from ..plane_sync import add_comment as _add_comment` — локальный импорт → патчить `src.plane_sync.add_comment`
### Тест 2 — test_gitea_push_with_adr_advances_stage
- gitea.py:25: `from ..plane_sync import notify_stage_change as plane_notify_stage` — модульный импорт → патчить `src.webhooks.gitea.plane_notify_stage`
- РАСХОЖДЕНИЕ С ТЗ: тест assert'ит `mock_launcher.launch.assert_called_once()`, но код вызывает `enqueue_job` из db.py, не `launcher.launch`. Нужно дополнительно мокать `src.webhooks.gitea.enqueue_job` и исправить assert.
### Тест 3 — test_gitea_ci_failure_on_development_notifies_qg_failure
- Уже PASSED в чистом окружении! Дополнительных патчей не нужно.
## Сделано
- [ ] Изучить исходники src/webhooks/plane.py, gitea.py, plane_sync.py
- [ ] Создать ветку fix/isolate-webhook-tests-from-plane
- [ ] Применить патчи к tests/test_webhooks.py
- [ ] Проверить в чистом docker-окружении
- [ ] Push + PR
## Изменённые файлы
- `tests/test_webhooks.py` — добавлены @patch для изоляции сетевых вызовов Plane
## Результат
(в процессе)
## Проблемы и решения
- Тест 3 уже проходит (расхождение с ТЗ) — не требует изменений
- Тест 2: ТЗ говорит "только добавить @patch на plane_notify_stage", но этого недостаточно — нужно ещё мокать enqueue_job и исправить assert с launcher.launch
## Следующий шаг
Применить патчи и запустить тесты