Contributing to Umbryx¶
Prerequisites¶
- Docker + Docker Compose v2
- Python 3.11+ (for backend development outside containers)
- Node.js 20+ (for frontend development outside containers)
- Git
Local setup¶
- Copy the environment file and adjust values if needed:
- Build and start the full stack:
- The app will be available at
http://localhost:3000(nginx proxy).
On first run, the setup wizard creates the initial admin account.
Development workflow¶
All feature work must follow the branch model: feature branches merge
into dev, and dev merges into main manually after validation.
Short version:
- Create a branch from
dev:
-
Make your changes.
-
Validate with a full container rebuild:
- Run backend linting:
- Run frontend linting and build:
-
If the feature has a user-visible effect, document it in the development log (in the private repository).
-
Merge into
dev:
Code conventions¶
Backend (Python)¶
- Formatter: black (line length 100)
- Linter: ruff
- Config:
backend/pyproject.toml - Errors: use
AppErrorfromcore/errors.pyfor new endpoints - Logging: use
get_logger(__name__)fromcore/logging_setup.py; no bareprint() - Enums: use
core/enums.pytypes for roles and severity; no magic strings
Frontend (JavaScript/JSX)¶
- Linter: eslint (flat config in
frontend/eslint.config.js) - Run:
npm run lint - No bare
console.login production code (console.warnandconsole.errorare allowed) - Domain data hooks: use
src/hooks/useProjectData.jsinstead of callingapi.*directly in components when doing standard list fetches
Pre-commit hooks (optional)¶
Install pre-commit to run checks automatically before every commit:
Config: .pre-commit-config.yaml at the repo root.
Database migrations¶
Schema changes must be captured in an Alembic migration file. Never alter the schema by hand or by editing existing migrations.
Adding a migration¶
cd backend
# 1. Edit app/models/<domain>.py — add the new column or table to the ORM class
# 2. Generate a migration (autogenerate compares models vs. live DB):
make db-new MSG="add last_login_at to users"
# 3. Review the generated file in alembic/versions/ and verify both
# upgrade() and downgrade() are correct
# 4. Apply locally to confirm:
make db-upgrade
Migration style guide¶
- Use
op.add_column(),op.create_table(),op.drop_column()etc. (Alembic ops) rather than rawop.execute(text(...))for structural changes. - Always implement
downgrade(). For irreversible data migrations, add a comment explaining why rollback is not possible and raiseNotImplementedErrorso it fails loudly. - Keep each migration focused: one logical change per file.
- Test both directions:
make db-upgradethenmake db-downgradethenmake db-upgradeagain.
Common make targets (from backend/)¶
| Command | Action |
|---|---|
make db-status |
Show current migration version |
make db-upgrade |
Apply all pending migrations |
make db-downgrade |
Roll back one step |
make db-new MSG="..." |
Generate migration from model changes |
make db-history |
Show full migration chain |
Tests¶
Backend tests live in backend/tests/. Run inside the container:
For a fresh isolated DB (recommended for CI):
Or use the dedicated test image (SQLite, no external services required):