Skip to content

Latest commit

 

History

History
479 lines (322 loc) · 12.9 KB

File metadata and controls

479 lines (322 loc) · 12.9 KB

Contributing to RELab

Thanks for contributing. RELab is a research platform developed at CML, Leiden University. The goal of this document is simple: get you productive without making you dig through the repo first.

This page is for code and documentation changes. If you mainly want to run or deploy the stack, see Install & Self-Host.

Start Here

I want to... Start here
get the recommended working environment Devcontainer Setup
run the full stack locally in Docker Docker Development
work on one subrepo directly Local Development
understand the system first docs.cml-relab.org/architecture
understand config ownership engineering configuration

Code of Conduct

By participating, you agree to follow the Code of Conduct.

Devcontainer Setup

This is the recommended path into the repo if you use VS Code.

Requirements

First-Time Setup

  1. Clone the repository.

  2. Create the environment files.

    cp backend/.env.dev.example backend/.env.dev
    cp .env.example .env
  3. Fill in the required values in backend/.env.dev and .env.

  4. Reopen the repo in the relab-fullstack devcontainer.

  5. Run the standard bootstrap path.

    just setup
    just dev
  6. Run the standard checks when you want to verify the repo state.

    just ci

Available Configurations

Configuration Purpose
relab-fullstack primary onboarding path for full stack development
relab-backend focused backend work
relab-frontend-app focused Expo app work
relab-frontend-web focused public site work
relab-docs focused docs work

Forwarded Ports

Docker Development

Use this when you want the full stack without configuring each subrepo manually.

  1. Create the backend environment file.

    cp backend/.env.dev.example backend/.env.dev
    cp .env.example .env
  2. Install local tooling.

    just setup
  3. Start the stack with file watching.

    just dev
  4. Run migrations on first start.

    just dev-migrate

Local Service URLs

Useful Commands

just dev-up       # start without file watching
just dev-logs     # tail logs
just dev-down     # stop containers

Local Development

Use this when you want to work on a specific subrepo without Docker.

Root Setup

Install:

  • Git
  • uv
  • just recommended
  • Node.js LTS for the frontend subrepos

Then run:

git clone https://github.com/CMLPlatform/relab
cd relab
just setup

Task Runner

The repo uses just as the common task runner.

From the repo root:

just setup
just ci
just test
just test-integration
just security

Use just --list in any directory to see what is available there. Manifest ownership, env rules, and infra review guidelines live in the engineering configuration docs.

Backend Setup

The backend lives in backend/.

Requirements

  • uv
  • PostgreSQL
  • Redis recommended; required for production-like auth behavior

Setup

cd backend
uv sync --all-groups --frozen
cp .env.dev.example .env.dev
./scripts/local_setup.sh
just dev

The API is available at http://127.0.0.1:8000.

OpenAPI Examples

Keep examples centralized and predictable:

  • Domain-specific examples go in examples.py (e.g., backend/app/api/data_collection/examples.py)
  • Cross-domain examples go in backend/app/api/common/openapi_examples.py
  • Use *_EXAMPLE for single payloads, *_EXAMPLES for schema lists, *_OPENAPI_EXAMPLES for FastAPI named maps
  • In routers, pass examples via openapi_examples=... parameter
  • Update backend/tests/integration/api/test_openapi_endpoints.py when changing examples

Backend Module Structure

Keep modules small, explicit, and domain-shaped:

  • One top-level package per domain: auth, background_data, data_collection, file_storage, newsletter, plugins/rpi_cam
  • Prefer flat modules first: crud.py, dependencies.py, examples.py, exceptions.py, filters.py, models.py, schemas.py
  • Use routers/ only when multiple route files exist; entrypoint goes in routers/__init__.py
  • Use models/ only when both ORM models and storage primitives exist; expose public surface at models/__init__.py
  • Use services/ and utils/ only when they reflect a real boundary; delete pass-through layers when simple enough to call directly
  • Keep shared behavior in backend/app/api/common/

Backend Test Architecture

Keep the backend suite organized by execution cost first, then by feature:

  • backend/tests/unit/: pure unit tests only, with no database session, testcontainers startup, or real app lifespan
  • backend/tests/integration/db/: CRUD, ORM, and persistence behavior against the real schema
  • backend/tests/integration/api/: HTTP endpoint behavior against the ASGI app
  • backend/tests/integration/flows/: a small set of cross-boundary, multi-step scenarios

Use the backend test commands that match those tiers:

cd backend
just test-unit
just test-integration-db
just test-api
just test-flows
just test-ci

Fixture conventions should stay explicit and descriptive:

  • db_session for database access
  • db_user and db_superuser for persisted auth principals
  • api_client, api_client_user, and api_client_superuser for HTTP tests
  • redis_client or feature-local Redis fixtures where applicable

Do not add or reintroduce session or superuser as in-repo fixture aliases. Use the canonical db_session and db_superuser names directly.

Do not add compatibility-only test coverage for fixture aliases, re-export modules, or pass-through wrappers unless they protect a deliberate stable external contract. Prefer testing behavior at the canonical fixture or module surface.

Keep fixtures close to the tests that use them when the reuse is local. Reserve backend/tests/conftest.py for bootstrap concerns such as testcontainers, test database setup, and global logging behavior. Avoid broad autouse fixtures unless they are true cross-suite safety rails.

Keep API tests focused on one behavior per test. Avoid multi-step CRUD journeys in tests/integration/api/; move those broader stories to tests/integration/flows/.

Path is the primary source of truth for where a test belongs:

  • Choose unit when the test can run with mocks/stubs only.
  • Choose integration/db when the behavior depends on SQLAlchemy queries, migrations, or constraints.
  • Choose integration/api when the behavior is expressed as HTTP requests against the app.
  • Choose flows only when the value comes from verifying a full multi-step journey.

If a test file starts growing into a mixed “god file”, split it by behavior before adding more cases.

Frontend Setup

frontend-app

cd frontend-app
pnpm install --frozen-lockfile
just dev

The Expo dev server runs on http://localhost:8081.

If you are using a physical device or a non-default backend URL, create frontend-app/.env.local and set EXPO_PUBLIC_API_URL.

To enable Google OAuth on web, set EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID in your env file to the web client ID from Google Cloud Console. The authorized redirect URI for your environment must also be registered there (e.g. http://localhost:8013/login for local dev).

Regenerating API types

The frontend TypeScript API types are autogenerated from the backend OpenAPI schema and written to frontend-app/src/types/api.generated.ts.

When working on backend API changes, regenerate the types:

# from repo root
cd frontend-app
pnpm run codegen:api

# regenerate and redact embedded JWT examples (recommended)
pnpm run codegen

You can also run just codegen inside frontend-app (after just install) which runs the regeneration and redaction steps.

frontend-web

cd frontend-web
pnpm install --frozen-lockfile
just dev

The Astro dev server runs on http://localhost:8081.

Docs Setup

Docs Development

cd docs
pnpm install --frozen-lockfile
just dev

The docs site runs on http://localhost:8000.

The docs app is the canonical home for public guides, architecture reference, and project context. Keep repo-level setup text in this file short and link back to the docs site when deeper explanation belongs there.

Development Workflow

If you are new to the repo, start with the architecture docs before making structural changes.

Pull Requests

  1. Create a branch.

    git checkout -b feature/your-change
  2. Make the change.

  3. Run the relevant checks.

    just ci
  4. Push your branch and open a PR.

  5. Address review feedback.

Commit Messages

Use Conventional Commits:

<type>(<scope>): <short summary>

CI

The repo uses GitHub Actions for:

  • normal CI
  • security checks
  • release automation

Locally, the important commands are:

  • just ci
  • just test
  • just test-integration
  • just security

Backend Development

Backend Code Style

The backend uses:

  • Ruff for linting and formatting
  • Ty for static type checking
  • ShellCheck for shell scripts

Useful commands from backend/:

just lint
just format
just fix
just typecheck
just shellcheck
just check

Backend Testing

Useful commands from backend/:

just test
just test-unit
just test-integration
just test-cov

When adding backend behavior, add tests close to the change. Prefer small unit tests unless the behavior really depends on routing, persistence, or integration boundaries.

Database Migrations

When changing schema:

  1. Create a migration.

    cd backend
    just migrate-create "describe the change"
  2. Review the generated file in alembic/versions/.

  3. Apply it.

    just migrate

For Docker-based runs, you can also use just dev-migrate from the repo root.

Email Templates

MJML source templates live in backend/app/templates/emails/src/. Compiled HTML lives in backend/app/templates/emails/build/.

Do not edit compiled output directly.

To rebuild email templates:

cd backend
just compile-email

Frontend Development

Frontend Code Style

  • frontend-app uses Expo linting and TypeScript-based tooling
  • frontend-web uses Biome and Astro validation
  • follow the existing folder structure and naming patterns
  • prefer consistency with the current UI and component patterns over novelty

Frontend Testing

For frontend-app:

cd frontend-app
just test
just test-ci
just check

For frontend-web:

cd frontend-web
just test
just test-ci
just test-e2e
just check

When adding a new public-facing page to frontend-web, add at least one browser test. When adding app behavior in frontend-app, add Jest coverage for the new logic or screen behavior.

Docs Development

Documentation Style

  • write plainly
  • keep docs informative but simple
  • avoid hype, filler, and brittle implementation detail unless it is genuinely needed
  • prefer Markdown and Mermaid over custom HTML where possible

Before opening a docs-focused PR:

cd docs
just check

To apply formatting:

cd docs
just format

License

By contributing, you agree that your contributions are licensed under the project LICENSE.