5.7 KiB
Use the version of Python/Pytest in the .venv directory when attempting to run commands, as that's where the pip dependencies (and pytest) are installed.
Database migrations
Schema changes use Alembic (migrations live in src/pirats/migrations/, shipped inside the package). The app applies them automatically at startup via pirats.database.run_migrations(); databases predating Alembic are normalized and stamped at the 0001 baseline first.
After editing src/pirats/models.py, generate a migration and sanity-check it:
.venv/bin/alembic revision --autogenerate -m "describe the change"
.venv/bin/alembic upgrade head # or just start the app
Note on adding NOT NULL columns in SQLite:
SQLite does not support adding a NOT NULL column without a default value to an existing table. When Alembic auto-generates a migration that adds a nullable=False column, you MUST manually edit the migration to include server_default="..." in the sa.Column definition (e.g., server_default="" for strings) before applying it. Otherwise, the migration will crash with Cannot add a NOT NULL column with default value NULL.
Do NOT add ad-hoc ALTER TABLE statements to database.py — that legacy list exists only to upgrade pre-Alembic databases to the baseline and must not grow.
Visual verification
Always visually verify fixes or changes expected to have an aesthetic impact in the running app before marking them complete. Inspect browser screenshots of the affected UI, including relevant interaction states (such as expanded and collapsed panels) and screen sizes when layout is affected. Code review, DOM inspection, automated tests, and a successful build do not replace visual verification. Correct any visual issues found and inspect the result again. If visual verification is blocked, explicitly report the blocker and do not claim the appearance is verified.
Learning during testing
When you run into a repeatable problem during testing (e.g. port assignment collision, missing executable, etc), note down the problem and solution in this file so that you'll have access to it in future sessions.
-
If Alembic autogeneration says the target database is not up to date, create a temporary database with
DATABASE_URL=sqlite:////tmp/<name>.db .venv/bin/alembic upgrade head, then run the autogeneration command with that sameDATABASE_URL. -
Before browser testing, check whether the default Vite port belongs to this project. If it is occupied by another app, start this frontend with
npm --prefix frontend run dev -- --host 127.0.0.1 --port 5174 --strictPortand use that URL. Local server binds may require sandbox escalation. -
In-memory SQLite tests that use FastAPI TestClient need
poolclass=StaticPoolas well ascheck_same_thread=False, so request threads share the database after commits. Otherwise they can fail withno such table. -
Rollback tests must fetch Player/Obstacle/Challenge/Vote rows again by ID after
apply_game_state; it deletes and recreates those rows, so old ORM instances cannot be refreshed. -
The project
.venvuses Python 3.9. UseOptional[T](or postponed annotations) instead of evaluatedT | Noneannotations, which fail during import. -
Multi-socket TestClient tests must use
with TestClient(app) as clientso sockets share one event loop; separate portals can hang on cross-socket broadcasts. Close sockets explicitly before asserting disconnect messages. Override lifespan when using an isolated test database. -
For browser QA, use a temporary database (for example,
DATABASE_URL=sqlite:////tmp/pirats-qa.db) andPIRATS_PURGE_ENABLED=false. Normal app startup migrates the selected database and automatically purges stale games.
Versioning & changelog
The app shows its version number and a player-facing changelog in the ☰ menu → About. Both come from frontend/src/lib/changelog.js (rendered by frontend/src/components/AboutModal.svelte).
- Ordinary commits do not bump
VERSIONor the Nix package versions. - Accumulate player-visible changes in one entry at the top of
CHANGELOGwithversion: nullandchanges: [...]. The About dialog labels it In testing. Append to or consolidate this batch across commits; do not create a separate entry per commit or assign a release date yet. - Omit the In testing entry when there are no unreleased player-facing changes; empty batches are hidden. Do not add placeholder entries just to describe changelog maintenance.
- The changelog is for players: skip refactors, tests, tooling, and other internal-only changes. Internal-only commits need no changelog entry.
- Release labeling is a separate process, performed only when explicitly requested. At release time:
- Consolidate the In testing batch into meaningful player-facing groups using
groups: [{ title, changes: [...] }], replacing its flatchangeslist. Remove duplicates and describe the final behavior. - Bump
VERSIONby one and give the batch that numericversionplus the releasedate(YYYY-MM-DD). - Bump both package
versionvalues inflake.nix(pirats-frontendandpirats) to the same new Nix release version. Preserve the Nix version scheme; do not equate its semantic version with the app's integer V number. - Commit the release metadata together. The next player-visible development change starts a fresh In testing entry.
- Consolidate the In testing batch into meaningful player-facing groups using
- Preserve already numbered history unless the user explicitly requests reorganizing past releases.
Work order
You will be working on tasks in [TODO.md](./TODO.md]. Work on at most two tasks at a time (one is preferable, but two is fine if they dove tail really nicely), and after you finish each task, make a git commit and update the TODO list to check off the completed task.