Contributing¶
Bug reports, feature ideas, and pull requests are welcome. For a large change, open an issue first.
Development setup¶
Develop on Linux or macOS. Those are what evaltrack supports and what CI runs, and the suite does not pass on Windows. Under WSL2 you are on Linux, so that works.
Install uv and just. Then run:
just install_dev # uv sync --all-groups + install pre-commit hooks
For the dashboard frontend (TypeScript/React):
just frontend_install
just frontend_dev # Vite dev server, proxies /api to a running `evaltrack ui` (default :8765)
An editable install serves a fallback page at evaltrack ui until just frontend_build has run.
Tests and linting¶
just test # run the test suite
just lint # ruff, basedpyright (strict), import-linter, bandit, prettier (via pre-commit)
The justfile has the rest: the frontend checks, the runnable examples, and the live cloud
integration tests. Run what matches your change (for the frontend, also npm run lint, which
just lint does not cover). CI runs all of it on every PR bar the one exception below, so anything
you skip locally is still caught there.
The integration tests need credentials for the maintainer's Azure and AWS test accounts, so most
contributors cannot run them locally. That is fine. A PR from a fork is not given the secrets
either, so that job skips there rather than failing on empty credentials, and the run against live
storage happens after merge. If your change touches the Azure or S3 backend, say so in the PR and I
will run them. The azure and s3 fixtures in tests/repositories/conftest.py have the details.
Locally, the Azure tests use az login. The S3 tests use the AWS profile that AWS_PROFILE names.
Run AWS_PROFILE=<profile> just integration_test, or put AWS_PROFILE=<profile> in a .env file.
The justfile loads that file and git ignores it.
Documentation¶
The guides in docs/ are the source. The site at
evaltrack.jesravnbol.dk is built from them with Zensical, plus an
API reference from the docstrings.
just docs_build # strict: a broken link or docstring cross-reference fails it, as in CI
just docs_serve # live preview on http://localhost:8000
just docs_fallback # the same site with MkDocs and mkdocs-material, which must keep working
Conventions¶
- Branch off
main. A pre-commit hook blocks direct commits tomain. - Add tests for new behavior and for bug fixes.
- Prefer dependency injection with fakes over mocking. Test what a caller can observe, not internal behavior.
- The package's layers are set out in
.importlinter, andjust lintchecks them. If a new import breaks a rule, move the code, or change the rule there and say why. - If you change the stored run format, bump
RUN_SCHEMA_VERSION. Its docstring inevaltrack/core/run_record.pysays what else a bump needs.
Releasing¶
A release is a pull request and then a GitHub release. The pull request bumps version in
pyproject.toml, runs uv lock so the lockfile carries the new version, and turns the changelog's
[Unreleased] heading into the version and date, with a link reference at the bottom. Once it is
merged, publish a GitHub release with the tag v<version> and the changelog section as its notes.
That runs release.yml, which refuses a tag that does not match the declared version, builds and
smoke-tests the distribution, and uploads it to PyPI through the pypi environment. Releasing needs
write access to the repository and approval on that environment.
Once the package is on PyPI, the same workflow deploys the docs for the release's minor version
(0.2 for 0.2.x) and moves latest to it. dev is deployed from main on every push. Both go
to the gh-pages branch through mike. The branch, the Pages settings and the DNS record were set
up once by hand.