This guide is intended for our internal development team. It outlines our workflow and standards for contributing to this project.
Clone the repository and navigate to the root directory:
git clone git@github.com:luxonis/luxonis-train.git
cd luxonis-trainInstall uv and sync the development environment:
uv syncNote
This creates a .venv with the package installed in editable mode, together with the dev dependencies.
To also install the AIMET support, run:
uv sync --extra aimetThe requirements*.txt files are exports of uv.lock for users installing with pip.
Do not edit them manually. After changing the dependencies, run:
scripts/export_requirements.shNote
A pre-commit hook runs the script for you - you only need to stage the refreshed files.
We use pre-commit hooks to ensure code quality and consistency.
The hooks are run by prek, a faster drop-in replacement for pre-commit.
- Run
uv run prek installin the root directory. - The hooks will now run automatically on
git commit.- If a hook fails, it will print an error message and abort the commit.
- Some hooks will also modify the files in-place to fix found issues.
To run all the hooks manually, use uv run prek run --all-files.
Do not commit directly to main - the no-commit-to-branch hook blocks it.
The complexipy pre-commit hook gates the cognitive complexity of every function. A function must stay at complexity 15 or below.
When the hook fails, it prints ranked refactor plans for failing functions (the --suggest-refactors flag). Follow one of the plans, or simplify the function in another way. The usual levers: guard clauses, merged conditions, and extraction of helpers.
To check by hand, run:
uv run complexipy luxonis_train testsWe write docstrings in the Google style. pydoctor builds the API docs from them. The [tool.pydoctor] section of pyproject.toml holds its options.
Do not write types in docstrings. The annotations of the signature hold the types, and the docs show them from there.
Single backticks link to a name in luxonis_train. Put a name from another library, such as ``torch.nn.Conv2d``, in double backticks. The docs build does not download the indexes of other projects, so it cannot link to them.
def resize(image: Tensor, size: int) -> Tensor:
"""Resize an image to a square.
Args:
image: The image with shape ``[C, H, W]``.
size: The side of the result, in pixels.
Returns:
The resized image with shape ``[C, size, size]``.
"""To verify that your documentation is formatted correctly, run the following command:
uv run --group docs pydoctorThe codebase is type-checked using pyright, pinned in the dev dependency group to match CI. To run type checking, use the following command in the root project directory:
uv run pyright --warnings --project pyproject.toml- PyCharm - Pyright extension
- Visual Studio Code - Pyright extension
- NeoVim - LSP-Config plugin with the pyright configuration
We use pytest for testing.
The tests are located in the tests directory. To run the tests with coverage, use the following command:
uv run pytest --cov=luxonis_train --cov-report=htmlThis command will run all tests and generate HTML coverage report.
Tip
The coverage report will be saved to htmlcov directory.
If you want to inspect the coverage in more detail, open htmlcov/index.html in a browser.
Tip
You can choose to run only the unit-tests or only the integration tests by adding -m unit or -m integration to the pytest command.
Important
Mark an integration test with @pytest.mark.gpu when it trains, tunes or quantizes a model.
CI runs these tests on the GPU runner and all the other tests on a CPU runner.
A test without the marker still passes on the CPU, but it no longer covers the GPU code of the training, such as mixed precision.
Important
If a new feature is added, a new test should be added to cover it. The minimum overall test coverage for a PR to be merged is 90%. The minimum coverage for new files is 80%.
Our GitHub Actions workflow is run when a new PR is opened.
- First, the pre-commit hooks must pass and the documentation must be built successfully.
- Next, the type checking is run.
- If all previous checks pass, the tests are run.
The tests run in five suites, one job each.
The GPU suites start only after the cpu suite passes, so that a failure there costs no GPU time:
| Suite | Tests | Runner |
|---|---|---|
cpu |
The unit tests, and the integration tests without the gpu marker |
ubuntu-latest |
misc |
The integration tests with the gpu marker |
ubuntu-t4-4core |
predefined_light, predefined_heavy |
test_predefined_models.py, the light and the heavy variants |
ubuntu-t4-4core |
combinations |
test_combinations.py |
ubuntu-t4-4core |
CI does not run test_overfit_convergence.py, which has its own overfit_convergence marker.
Two rules keep the GPU suites from running when they cannot find anything new:
- A pull request that changes only docstrings, comments, Markdown files or the settings of the linters and of the API docs runs the
cpusuite only.scripts/only_docstrings_changed.pydecides this. - A draft pull request skips
predefined_heavy. The suite runs when you mark the pull request as ready for review.
Tip
Review the GitHub Actions output if your PR fails.
Important
Successful completion of all the workflow checks is required for merging a PR.
A release needs two manual steps: start the workflow, then merge the pull request it opens.
- Run the
Release PRworkflow from the Actions tab. Give itmajor,minor,patch, or an explicit version such as1.2.3. - The workflow changes
__version__inluxonis_train/__init__.pyand opens arelease/vX.Y.Zpull request that lists the changes after the last tag. - Review the pull request, wait for CI, and merge it.
- The
Release Tagworkflow then tagsvX.Y.Z-betaon the merge commit and creates the GitHub release with generated notes. - The release publication starts the PyPI upload.
Both workflows are thin callers. The shared logic lives in luxonis-ml, in .github/workflows/reusable-release-pr.yaml and .github/workflows/reusable-release-tag.yaml, so every Luxonis repository releases the same way.
.github/release.yaml groups the generated notes into categories from the pull request labels.
Important
The release runs on the WORKFLOW_SECRET secret. The default token does not start CI on a bot pull request, and it cannot start the publish workflow from a release event.
- Make changes in a new branch with a descriptive prefix such as
feat/orfix/. - Test your changes locally.
- Commit your changes (pre-commit hooks will run).
- Push your branch and create a pull request.
- The team will review and merge your PR.