Files
wiki/tasks/orchestrator/reports/dev-2026-06-04-fix-webhook-secret-isolation.md
2026-06-05 00:10:01 +03:00

5.8 KiB
Raw Blame History

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 готов к ревью координатором (Стримом). НЕ мержить самостоятельно.