Code Quality
This project enforces a high standard of code quality through a combination of automated tools. These tools are configured to run automatically before each commit, ensuring that all code in the repository is consistent, readable, and free of common errors.
Pre-commit Hooks
The project uses pre-commit to manage and maintain a set of Git hooks. These hooks are run automatically before each commit to inspect the code being committed. The configuration is stored in the .pre-commit-config.yaml
file.
The following tools are configured to run as pre-commit hooks:
pre-commit-hooks
- Purpose: A collection of basic, essential hooks that perform checks on files.
- Key Hooks:
trailing-whitespace
: Trims trailing whitespace.end-of-file-fixer
: Ensures that a file is either empty or ends with a single newline.check-yaml
: Checks yaml files for parseable syntax.check-added-large-files
: Prevents giant files from being committed.check-merge-conflict
: Checks for files that contain merge conflict strings.detect-private-key
: Detects the presence of private keys.check-ast
: Checks Python files for valid syntax.check-docstring-first
: Checks that docstrings are the first statement in a module, class, or function.debug-statements
: Checks for debugger imports andbreakpoint()
calls.
black
- Purpose: An opinionated code formatter for Python.
- Usage: It automatically reformats Python code to ensure a consistent style across the project. This eliminates debates over code style and makes the code more readable.
ruff
- Purpose: An extremely fast Python linter, written in Rust.
- Usage: It checks for a wide range of code errors, style issues, and potential bugs. The
--fix
argument allows it to automatically fix many of the issues it finds.
mypy
- Purpose: A static type checker for Python.
- Usage: It analyzes the code to ensure that variables and functions are used with the correct types. This helps to catch type-related errors before the code is even run. The configuration is set to only check the
src/
directory.
Synchronizing Pre-commit Environments
A key challenge in this project was ensuring consistent behavior of the pre-commit hooks across different environments. We discovered that the pre-commit
hooks can run in two distinct contexts:
- The Local
git commit
Hook: When you rungit commit
,pre-commit
creates and manages its own isolated Python environment to run the hooks. This environment is cached locally on your machine. - The Dockerized
make pre-commit
Command: When you runmake pre-commit
, the hooks are executed inside the project's Docker container, using theuv
environment defined inpyproject.toml
.
These two environments were found to have different dependencies and package versions, which caused mypy
to report conflicting errors. To solve this, we synchronized the environments by modifying the .pre-commit-config.yaml
to ensure the mypy
hook uses the same dependencies as the main project. This was achieved by explicitly listing the required type-stub packages in the additional_dependencies
section of the mypy
hook, ensuring consistent and predictable behavior everywhere.
Usage
While the pre-commit hooks run automatically, you can also run the tools manually. This is useful if you want to check your code before committing, or if you want to apply formatting and linting to the entire codebase.
The following make
commands are available:
make format
: Formats the code withblack
.make lint
: Lints the code withruff
and automatically fixes issues.make type-check
: Runs themypy
static type checker.make pre-commit
: Runs all the pre-commit hooks on all files.
Hosting the Documentation
The documentation for this project is built using MkDocs and can be hosted for free on GitHub Pages.
There are two ways to deploy the documentation to GitHub Pages:
1. Using mkdocs gh-deploy
This is the recommended method, as it is the simplest.
Prerequisites:
- You need to have a personal access token with the
repo
scope.
Steps:
- Make sure the
repo_url
inmkdocs.yml
is set to your repository's URL. -
Run the following command:
When prompted for your username and password, enter your GitHub username and use your personal access token as the password.
-
After the command has finished, go to your repository's settings on GitHub, navigate to the "Pages" section, and select the
gh-pages
branch as the source for your GitHub Pages site.
2. Manual Deployment
If the mkdocs gh-deploy
command does not work, you can deploy the documentation manually.
Steps:
-
Build the documentation:
-
Navigate into the
site
directory: -
Initialize a new git repository and commit the files:
-
Add your repository as the remote origin and push the
gh-pages
branch: -
After the command has finished, go to your repository's settings on GitHub, navigate to the "Pages" section, and select the
gh-pages
branch as the source for your GitHub Pages site.
Continuous Integration & Deployment
The project uses GitHub Actions for Continuous Integration and Continuous Deployment (CI/CD). The workflows are defined in the .github/workflows
directory.
CI Workflow (ci.yml
)
The ci.yml
workflow runs on every push and pull request to the main
branch. It ensures the quality and correctness of the code by running the following jobs:
- Build Docker services: It builds the
app
Docker service to ensure the development environment is correctly configured. - Run pre-commit checks: It executes
make pre-commit
to run all the pre-commit hooks, which include checks for formatting (black
), linting (ruff
), and static typing (mypy
). - Run tests: It executes
make test
to run the entire test suite withpytest
.
This workflow guarantees that any code merged into the main
branch adheres to the project's quality standards and passes all tests.
Documentation Deployment Workflow (docs.yml
)
The docs.yml
workflow automates the deployment of the project documentation to GitHub Pages. It is triggered on every push to the main
branch that includes changes in the docs/
directory or the mkdocs.yml
file.
The workflow performs the following steps:
- Checkout code: Checks out the repository.
- Setup Python and uv: Sets up the Python environment and the
uv
package manager. - Install dependencies: Installs the project dependencies, including
mkdocs
. - Build docs: Builds the documentation site using
uv run mkdocs build
. - Deploy to GitHub Pages: Deploys the generated
site/
directory to thegh-pages
branch, making it available as a static website.