3.8 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.
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.
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).
- Bump
VERSIONby one on every commit. - When a commit changes something players can see, add an entry to the top of
CHANGELOG({ version, date, changes: [...] }) describing it in player-facing terms. Group everything shipping under one version into a single entry. - The changelog is for players: skip refactors, tests, tooling, and other internal-only changes. A commit with no user-facing change bumps
VERSIONbut adds no entry.
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.