diff --git a/AGENTS.md b/AGENTS.md index 97ac534..d3e71e3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -26,6 +26,7 @@ Maintain a deliberately small, self-hosted rota application for a non-profit bar - SQLite by default - No frontend build step or JavaScript framework - Docker Compose for self-hosting +- Docker Compose `test` profile for running tests independently of the host Python environment ## Important files @@ -57,6 +58,16 @@ python -m compileall -q app pytest -q ``` +Prefer the containerized suite when the host Python environment is uncertain: + +```bash +make test-docker +# or +docker compose --profile test run --rm --build tests +``` + +The `test` target of the `Dockerfile` installs `requirements-dev.txt` on top of the app image and runs `pytest` with throwaway settings (`SECRET_KEY`, `DATABASE_URL`, `INITIAL_ADMIN_PASSWORD`). It mounts no host volumes and does not read `.env`, so it is safe on a fresh clone. + For route/UI changes also start the app and verify `/health`, `/login`, the rota, admin month editor, and swap workflow. ## Security notes diff --git a/Dockerfile b/Dockerfile index 2133091..34bdb71 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,8 @@ -FROM python:3.12-slim +FROM python:3.12-slim AS base ENV PYTHONDONTWRITEBYTECODE=1 \ - PYTHONUNBUFFERED=1 + PYTHONUNBUFFERED=1 \ + PIP_DISABLE_PIP_VERSION_CHECK=1 WORKDIR /app COPY requirements.txt ./ @@ -10,3 +11,13 @@ COPY . . RUN mkdir -p /app/data EXPOSE 8000 CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] + +# Test image: same app plus dev dependencies, runs the suite in isolation. +FROM base AS test + +COPY requirements-dev.txt ./ +RUN pip install --no-cache-dir -r requirements-dev.txt +ENV SECRET_KEY=test-only-secret-key \ + DATABASE_URL=sqlite:///./data/test.db \ + INITIAL_ADMIN_PASSWORD=test-only-password +CMD ["pytest", "-ra"] diff --git a/Makefile b/Makefile index e3bcc11..bf767d3 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: dev test init-db seed-demo reminders +.PHONY: dev test test-docker init-db seed-demo reminders dev: uvicorn app.main:app --reload @@ -6,6 +6,10 @@ dev: test: pytest -q +# Runs the suite inside Docker, independent of the host Python environment. +test-docker: + docker compose --profile test run --rm --build tests + init-db: python -m app.cli init-db diff --git a/README.md b/README.md index b277d47..a7f8ce4 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,14 @@ Example cron entry at 09:00 every day: pytest -q ``` +Or in a container, so the host Python environment does not matter: + +```bash +make test-docker +# or +docker compose --profile test run --rm --build tests +``` + ## Project documentation - `AGENTS.md` — instructions and guardrails for coding agents/LLMs. diff --git a/docker-compose.yml b/docker-compose.yml index 5ce78b0..d68118b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,8 +4,22 @@ services: container_name: bar-rota restart: unless-stopped env_file: - - .env + - path: .env + required: false ports: - "8000:8000" volumes: - ./data:/app/data + + tests: + build: + context: . + target: test + profiles: + - test + environment: + SECRET_KEY: test-only-secret-key + DATABASE_URL: sqlite:///./data/test.db + INITIAL_ADMIN_PASSWORD: test-only-password + PYTHONPATH: /app + command: ["pytest", "-ra"]