Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 16 additions & 15 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
- Chart pregenerator service: `chart_pregenerator/`
- Templates: each app has its own `templates/` directory
- Compiled bundles output: `build/static/bundles/`
- DevOps/Docker: `devops/docker/`, `devops/scripts/`
- Container builds and CI helper scripts: `ci/` (`ci/containers/Containerfile`, `ci/scripts/`)
- Requirements: `requirements.txt`, `dev-requirements.txt`, `ci-requirements.txt` (compiled from `.in` files via pip-compile)

## Tech Stack
Expand All @@ -31,9 +31,8 @@

## Development

- `make dev-init` for initial setup (creates `.env` with UID)
- `docker compose up` to start services (postgresql, django, node, node-chart-pregenerator, selenium)
- `docker compose exec django ./manage.py createdevdata` to seed dev data
- `just dev` (or `just dev-init` then `docker compose up`) to start services (postgresql, django, node, node-chart-pregenerator, selenium)
- `just createdevdata` to seed dev data
- Web app at `http://localhost:8000`
- Wagtail admin at `/admin` (dev credentials: `test` / `test`)
- API docs at `/api/schema/swagger-ui/`
Expand All @@ -42,26 +41,28 @@

## Testing

- Django tests: `make dev-tests` (runs with coverage via `coverage run ./manage.py test --noinput --failfast`)
- Jest tests: `make dev-jest-tests` (runs both main frontend and chart pregenerator tests)
- Migration check: `make check-migrations`
- Django tests: `just test` (runs with coverage via `coverage run ./manage.py test --noinput`)
- Jest tests: `just test-js` (runs both main frontend and chart pregenerator tests)
- Migration check: `just check-migrations`
- CI enforces **100% coverage on changed lines** using `diff-cover` against `origin/develop`
- Tests use a custom `SeededDiscoveryRunner` with fixed seed (`876394101`) for reproducibility
- Tests live in `tests/` subdirectories within each Django app (e.g., `incident/tests/`)

## Linting and Code Quality

- `make ruff` — linter/formatter
- `make bandit` — security static analysis
- `make eslint` — JavaScript linting (airbnb config)
- `make stylelint` — SCSS linting (sass-guidelines config)
- `just ruff` — linter/formatter (`just ruff-fix` applies fixes)
- `just bandit` — security static analysis
- `just eslint` — JavaScript linting (airbnb config)
- `just stylelint` — SCSS linting (sass-guidelines config)
- `just lint` — all of the above plus the migration check
- Ruff configured in `pyproject.toml`: `select = ["I", "F4"]` (isort + unused imports), target py312, Django/Wagtail-aware import section ordering

## Dependency Management

- Uses pip-tools (`pip-compile`) for reproducible, hash-verified pinning
- Edit `.in` files, then `make compile-pip-dependencies` to recompile
- `make pip-update PACKAGE=name` to upgrade a specific package
- Edit `.in` files, then `just pip-compile` to recompile
- `just pip-compile --upgrade-package=name` to upgrade a specific package
- `just pip-check` fails if the lockfiles drift from the `.in` files (CI runs it)
- pip-compile runs inside a Docker container matching the production Python version

## Frontend Build System
Expand All @@ -76,8 +77,8 @@
## Database

- Dev credentials: user `tracker`, password `trackerpassword`, db `trackerdb`, port `5432`
- `make dev-import-db` — import a database dump (place as `import.db` in repo root)
- `make dev-save-db` / `make dev-restore-db` — save/restore DB snapshots per branch
- `just import-db` — import a database dump (place as `import.db` in repo root)
- `just save-db` / `just restore-db` — save/restore DB snapshots per branch

## Debugging

Expand Down
72 changes: 64 additions & 8 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,66 @@
# We ignore all files in the repo by default,
# then selectively permit paths for inclusion.
# We do this to avoid non-source-code files, such as
# .env, *.db, db-snapshots/, coverage.xml, etc. from
# making it into the built artifact.


# ignore everything
*

# permit Django apps and the project package
!blog
!charts
!cloudflare
!common
!dashboard
!emails
!forms
!geonames
!home
!incident
!menus
!statistics
!styleguide
!tracker
# `build` is an INSTALLED_APP (a namespace package) as well as webpack's
# output directory, so Django will not start without it.
!build

# permit backend packaging tooling
!manage.py
!requirements.txt
!dev-requirements.txt
!pyproject.toml
!scripts
# read at request time by statistics/views.py
!STATISTICS.rst

# permit frontend packaging tooling
!client
!package.json
!package-lock.json
!webpack.config.js
!babel.config.js
!postcss.config.js
# the chart pregenerator is its own npm project; the `chartgen` stage copies it wholesale
!chart_pregenerator

# permit general build tooling,
# e.g. for git version info
!ci
!.git

# re-exclude unwanted artifact cruft, possibly included by the grants above
**/__pycache__
**/*.pyc
.env
client/build/
db-snapshots
logs
media/
node_modules
npm-debug.log
**/node_modules
tracker/settings/local.py
.versioninfo
# Stale dev bundles from a host `npm run start` would otherwise survive the
# prod asset build and break collectstatic's manifest rewriting.
build/static/bundles
# esbuild output and jest coverage are rebuilt in-image; `client` here is a
# gitignored convenience symlink some developers keep.
chart_pregenerator/build
chart_pregenerator/coverage
chart_pregenerator/client
Loading