From 4b47dabaf06b28d090dd1601a82c623bbcb3f2a9 Mon Sep 17 00:00:00 2001 From: Disco DeDisco Date: Tue, 12 May 2026 20:44:04 -0400 Subject: [PATCH] =?UTF-8?q?woodpecker=20main.yaml:=20serialise=20test-FTs-?= =?UTF-8?q?room=20behind=20test-FTs-non-room=20=E2=80=94=20both=20FT=20ste?= =?UTF-8?q?ps=20share=20the=20workspace=20AND=20fall=20back=20to=20SQLite?= =?UTF-8?q?=20(only=20test-UTs-n-ITs=20sets=20`DATABASE=5FURL`=20to=20the?= =?UTF-8?q?=20postgres=20service),=20so=20running=20them=20concurrently=20?= =?UTF-8?q?collided=20on=20`src/test=5Fdb.sqlite3`:=20the=20second-to-star?= =?UTF-8?q?t=20container=20hit=20a=20half-created=20DB=20and=20the=20runne?= =?UTF-8?q?r's=20`Type=20'yes'=20to=20delete=20the=20existing=20test=20dat?= =?UTF-8?q?abase`=20prompt=20EOFed=20under=20non-interactive=20CI=20stdin?= =?UTF-8?q?=20(pipeline=20run=20#296);=20fix=20flips=20`test-FTs-room.depe?= =?UTF-8?q?nds=5Fon`=20from=20`test-two-browser-FTs`=20=E2=86=92=20`test-F?= =?UTF-8?q?Ts-non-room`=20so=20the=20heavy=20room=20cluster=20strictly=20f?= =?UTF-8?q?ollows=20the=20non-room=20bucket;=20section=20comment=20rewritt?= =?UTF-8?q?en=20from=20"Parallel=20FT=20split"=20=E2=86=92=20"FT=20split?= =?UTF-8?q?=20(sequential=20for=20now)"=20w.=20the=20run=20#296=20EOFError?= =?UTF-8?q?=20documented=20+=20two=20re-parallelisation=20paths=20spelled?= =?UTF-8?q?=20out=20for=20later=20(per-step=20distinct=20sqlite=20paths=20?= =?UTF-8?q?via=20`DATABASE=5FURL=3Dsqlite:////tmp/test=5Fdb=5F.sql?= =?UTF-8?q?ite3`=20OR=20per-step=20distinct=20postgres=20DBs);=20the=20two?= =?UTF-8?q?=20stale=20"parallel"=20mentions=20(collectstatic=20note=20in?= =?UTF-8?q?=20test-two-browser-FTs=20+=20inline=20comment=20in=20test-FTs-?= =?UTF-8?q?room)=20also=20updated;=20screendumps=20+=20build-and-push=20de?= =?UTF-8?q?pends=5Fon=20unchanged=20=E2=80=94=20Woodpecker=20resolves=20th?= =?UTF-8?q?e=20transitive=20ordering=20fine?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Code architected by Disco DeDisco Git commit message Co-Authored-By: Claude Opus 4.7 --- .woodpecker/main.yaml | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/.woodpecker/main.yaml b/.woodpecker/main.yaml index e162d39..780f59a 100644 --- a/.woodpecker/main.yaml +++ b/.woodpecker/main.yaml @@ -52,7 +52,7 @@ steps: - pip install -r requirements.dev.txt - cd ./src # Also collectstatic'd here; output sits in the shared workspace so - # the downstream parallel FT steps don't have to repeat it. + # the downstream FT steps don't have to repeat it. - python manage.py collectstatic --noinput - python manage.py test functional_tests --tag=two-browser - python manage.py test functional_tests --tag=sequential @@ -64,19 +64,31 @@ steps: - "requirements.txt" - ".woodpecker/main.yaml" - # ── Parallel FT split ───────────────────────────────────────────────── + # ── FT split (sequential for now) ───────────────────────────────────── # # test_game_room_* is the heaviest cluster — 9 Selenium-driven room-flow # FTs that historically dominate the FT step wall-clock (~70% of the # ~40-min single-step runs). Split off into its own step (`test-FTs-room`) - # that runs in parallel with the rest (`test-FTs-non-room`). Both depend - # on test-two-browser-FTs (which leaves collectstatic'd assets in the - # shared workspace), so neither parallel step re-runs collectstatic. + # so the partition is visible in the pipeline view; the non-room bucket + # runs first as `test-FTs-non-room`. test-FTs-non-room depends on + # test-two-browser-FTs (collectstatic'd assets in shared workspace); + # test-FTs-room depends on test-FTs-non-room. # - # Tradeoff: 2 concurrent Selenium/Firefox containers on the runner - # instead of 1, in exchange for roughly halved test-FT wall-clock when - # the partition stays balanced. If the runner thrashes, drop the - # `depends_on` from one to serialize them again. + # NOTE — currently sequential, not parallel. Both FT steps share the + # workspace AND fall back to SQLite (only test-UTs-n-ITs has + # `DATABASE_URL` pointing at the postgres service). When they ran + # concurrently (both depending on test-two-browser-FTs), the second + # step to start hit a half-created `src/test_db.sqlite3` and prompted + # "Type 'yes' to delete the existing test database" → EOFError under + # non-interactive CI stdin. See pipeline run #296. + # + # To re-parallelise later, give each step its own DB: + # - point `DATABASE_URL` at distinct sqlite paths per step + # (e.g. `sqlite:////tmp/test_db_room.sqlite3` vs `_non_room`), or + # - have each step point at its own postgres DB (the existing + # `postgres` service already exposes one; spin up a second or + # `CREATE DATABASE` per step). + # Until then, test-FTs-room runs after test-FTs-non-room. - name: test-FTs-non-room image: gitea.earthmanrpg.me/discoman/python-tdd-ci:latest @@ -108,7 +120,7 @@ steps: - name: test-FTs-room image: gitea.earthmanrpg.me/discoman/python-tdd-ci:latest depends_on: - - test-two-browser-FTs + - test-FTs-non-room environment: HEADLESS: 1 CELERY_BROKER_URL: redis://redis:6379/0 @@ -122,8 +134,9 @@ steps: - pip install -r requirements.dev.txt - cd ./src # Heavy Selenium room flows — 9 files (deck_contrib, gatekeeper, - # invite, select_role/sea/sig/sky, tray, tray_tooltip) isolated into - # their own parallel sub-step. + # invite, select_role/sea/sig/sky, tray, tray_tooltip) isolated + # into their own sub-step. Runs after test-FTs-non-room (shared + # SQLite test DB; see split-rationale comment above). - python manage.py test --parallel --exclude-tag=channels --exclude-tag=two-browser $(ls functional_tests/test_game_room_*.py | sed 's|/|.|g;s|\.py||') when: - event: push