Contributing¶
Contributing to QuestMaster¶
Thanks for your interest in contributing! Here's how to get started.
Getting started¶
- Fork the repo and create a branch from
main. - Set up your local environment — see the Getting Started Guide for instructions.
- Make your changes, following the guidelines below.
- Open a pull request against
main.
Commit messages¶
All commits must follow the Conventional Commits format. Examples:
feat: add trophy leaderboardfix: prevent duplicate session registrationsrefactor: extract game validation into service layerdocs: update local setup instructionstest: add unit tests for UserService
Code style¶
- Format with Black:
black . - Sort imports with isort:
isort . - Lint with flake8:
flake8 website/ - Lint docstrings (google-style) with pydoclint:
pydoclint website/
A pre-commit configuration is provided. Install the hooks to run these checks automatically before each commit:
Architecture¶
The codebase follows a layered architecture. When adding or modifying code, respect these boundaries:
| Layer | Location | Responsibility | Rules |
|---|---|---|---|
| Models | website/models/ |
SQLAlchemy models, relationships, constraints | No business logic, no Flask imports |
| Repositories | website/repositories/ |
Data access (queries, CRUD) | No validation, no business rules, no Flask context |
| Services | website/services/ |
Business logic, validation, transactions | No direct Flask request/session access |
| Views | website/views/ |
HTTP handling (parse input, call services, return response) | No business logic |
New logic should go in the service layer. Views should stay thin.
Tests¶
- Use
pytest - Add or update tests when changing service logic
- Mock external services (Discord, VTT APIs)
- Run the test suite before pushing:
CI Pipeline¶
Every pull request is checked by the CI pipeline which runs:
- Conventional commit check — all commits must follow the conventional commits format.
- Linting — import ordering with isort, formatting with Black, static analysis with flake8 and docstring lint with pydoclint.
- Tests and coverage — pytest runs with coverage reported to SonarCloud for code quality analysis.
On merge to main, release-please creates or updates a release PR. Merging that PR creates a GitHub release and a version tag automatically, the CI also pushes the Docker image to GHCR.
Dependencies are kept up to date by Renovate, which opens PRs for new versions of Python packages, Docker base images, and GitHub Actions.