fix(tests): per-project Plane states in webhook tests + close CI hole (ORCH-39)
All checks were successful
CI / test (push) Successful in 11s
CI / test (pull_request) Successful in 10s

After ORCH-10 the webhook resolves Plane state UUIDs per-project via
get_project_states(project_id). The m6/plane webhook tests hardcoded the
enduro in_progress UUID for ORCH-project payloads, so the pipeline never
started and task creation assertions failed.

Tests:
- Mock get_project_states with a deterministic per-project ET/ORCH map (no
  network) and reset _STATES_CACHE via reload_project_states() per test.
- Send each request with the in_progress UUID that matches its own project.

CI hole:
- requirements.txt lacked pytest-asyncio, so the 6 @pytest.mark.asyncio tests
  in test_orch10_states.py were SILENTLY SKIPPED -> CI green while async paths
  never ran. Add pytest-asyncio + pytest.ini (asyncio_mode=auto, strict
  markers); harden ci.yml (set -euo pipefail, --strict-markers) so any failure
  or unknown marker reds the build and the whole suite runs.

src/ unchanged (per-project resolving is the ORCH-10 feature, kept as-is).
This commit is contained in:
dev-agent
2026-06-05 16:49:18 +03:00
parent 053ea3b1c5
commit 5f93cba297
5 changed files with 87 additions and 9 deletions

View File

@@ -34,6 +34,27 @@ import src.plane_sync as plane_sync # noqa: E402
ORCH_PLANE_ID = "8da6aa25-a60e-44d6-a1e2-d8ae59aa7d6a"
ENDURO_PLANE_ID = "7a79f0a9-5278-49cd-9007-9a338f238f9c"
# ORCH-39: after ORCH-10 the webhook resolves Plane state UUIDs per-project via
# get_project_states(project_id). Mock it deterministically (no network) and
# send each request with the UUID that matches its own project.
_PROJECT_STATES = {
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",
},
}
def _fake_get_project_states(project_id):
return _PROJECT_STATES.get(project_id, _PROJECT_STATES[ENDURO_PLANE_ID])
client = TestClient(app)
@@ -48,6 +69,10 @@ def setup(monkeypatch):
monkeypatch.setattr("src.webhooks.plane.verify_plane_signature", lambda body, sig: True)
# ORCH-39: deterministic per-project Plane states, clean cache per test.
plane_sync.reload_project_states()
monkeypatch.setattr(plane_sync, "get_project_states", _fake_get_project_states)
registry_json = (
f'[{{"plane_project_id": "{ENDURO_PLANE_ID}", "repo": "enduro-trails",'
f' "work_item_prefix": "ET", "name": "enduro-trails"}},'
@@ -60,6 +85,7 @@ def setup(monkeypatch):
yield
reload_projects()
plane_sync.reload_project_states()
if os.path.exists(_test_db):
os.unlink(_test_db)
@@ -103,10 +129,9 @@ def test_fetch_sequence_id_missing_field_returns_none():
# ---------------------------------------------------------------------------
# Feature 1: pipeline starts on a status change to In Progress, not on creation.
_IN_PROGRESS = "b873d9eb-993c-48cd-97ac-99a9b1623967"
# ORCH-39: in_progress UUID is project-specific; derive it from the project.
def _post(plane_id, plane_project_id=ORCH_PLANE_ID, name="A valid work item title"):
in_progress = _fake_get_project_states(plane_project_id)["in_progress"]
return client.post(
"/webhook/plane",
json={
@@ -117,7 +142,7 @@ def _post(plane_id, plane_project_id=ORCH_PLANE_ID, name="A valid work item titl
"name": name,
"description_stripped": "This is a sufficiently long description.",
"project": plane_project_id,
"state": {"id": _IN_PROGRESS, "name": "In Progress", "group": "started"},
"state": {"id": in_progress, "name": "In Progress", "group": "started"},
},
},
)