5.8 KiB
Dev Report: fix-webhook-secret-isolation
Дата: 2026-06-04 Статус: DONE
Задача
Исправить кросс-файловую утечку webhook-секрета через синглтон settings (Pydantic).
pytest tests/ давал 10 failed/284 passed (assert 401==200). Нужно: 0 failed.
Работать в ветке fix/isolate-webhook-tests-from-plane, добавить коммит поверх 7bbab9c, e856e09.
Сделано
- Прочитал ТЗ полностью
- Подключился к серверу slin@82.22.50.71, перешёл на ветку
- Изучил текущий conftest.py и образец из test_webhook_dedup.py:80-81
- Добавил autouse-фикстуру
_reset_webhook_secretsв tests/conftest.py - Обнаружил вторую скрытую проблему (db_path тоже протекает)
- Расширил фикстуру — добавил изоляцию db_path
- Прогнал полный pytest tests/ = 294 passed, 0 failed
- Проверил dedup тесты отдельно = 9 passed (HMAC/401 живы)
- Проверил test_webhooks.py отдельно = 16 passed
- git commit + push в ветку
- CI job = success ✅
Изменённые файлы
tests/conftest.py— добавлена autouse-фикстура_reset_webhook_secrets
Результат
294 passed, 4 warnings in 6.03s (было: 10 failed, 284 passed)
HMAC/dedup тесты:
tests/test_webhook_dedup.py: 9 passed (включая 401-тесты на строках 268, 278)
test_webhooks.py:
16 passed
CI job: success (2026-06-05T00:00:38+03:00, было failures с 2026-06-04)
git log:
1baae81 test: reset webhook secret per-test to fix cross-file isolation (CI green)
e856e09 test: migrate sequential_ids test to In Progress contract
7bbab9c test: isolate webhook tests from live Plane API (fix CI)
Проблемы и решения
Проблема 1 (ожидаемая): webhook-секрет
Причина: settings (Pydantic синглтон) создаётся при первом import src.config. Порядок
импорта тестов — алфавитный. test_webhook_dedup.py импортируется первым и не устанавливает
ORCH_*_WEBHOOK_SECRET="" жёстко (устанавливает через os.environ.setdefault). В итоге
если в среде есть реальный секрет — settings.{gitea,plane}_webhook_secret ≠ "" и HMAC включается.
Решение: monkeypatch.setattr перед каждым тестом сбрасывает оба секрета в "". Тесты 268,278 в test_webhook_dedup.py перекрывают это своим monkeypatch внутри теста — порядок: autouse conftest → autouse модульные → тест-код; monkeypatch стекируется.
Проблема 2 (обнаружена в процессе): db_path
Причина: Аналогичная утечка через settings.db_path. test_webhook_dedup.py импортируется
первым, устанавливает os.environ["ORCH_DB_PATH"] = "/tmp/test_orchestrator_dedup.db",
settings создаётся с этим значением. test_webhooks.py импортируется позже и устанавливает
env в /tmp/test_orchestrator.db — НО settings уже создан, поэтому settings.db_path
остаётся = dedup.db.
Следствие: setup_db в test_webhooks.py удаляет _test_db_webhooks (которого нет),
а фактическая БД — dedup.db — не очищается между тестами. Два теста подряд используют
ветку feature/ET-011-test, в БД остаётся задача со стадией review после первого теста,
второй тест вставляет новую задачу но get_task_by_repo_branch() без ORDER BY может
вернуть старую задачу → current_stage != "development" → notify_qg_failure не
вызывается → тест test_gitea_ci_failure_on_development_notifies_qg_failure падает.
Это было скрыто за assert 401==200 (первый assert в тесте не проходил). Стало видно после устранения первой проблемы.
Решение: В той же autouse фикстуре добавляем:
db_path_env = os.environ.get("ORCH_DB_PATH", "")
if db_path_env:
monkeypatch.setattr(db_mod.settings, "db_path", db_path_env, raising=False)
os.environ["ORCH_DB_PATH"] = последнее присвоенное значение после всех импортов =
/tmp/test_orchestrator.db (test_webhooks.py импортируется последним алфавитно). Тесты
dedup перекрывают это своим monkeypatch.setattr в их setup_db фикстуре — работает корректно.
Почему не нарушаются 401/HMAC тесты
Монопатч conftest autouse (_reset_webhook_secrets) применяется ПЕРЕД setup_db из
test_webhook_dedup. В тестах 268,278 monkeypatch.setattr вызывается ВНУТРИ теста
(после setup). monkeypatch стекирует патчи — последний выигрывает. После теста —
все откатываются в обратном порядке. autouse фикстура conftest повторно применяется
перед следующим тестом.
Следующий шаг
PR #27 готов к ревью координатором (Стримом). НЕ мержить самостоятельно.