uno is set up with a CI/CD development workflow that automatically generate
new releases whenever new commits or tags are pushed to the repository.
The workflow requires for all contributions to be made via a pull request to the main development branch.
A new "nightly" release is automatically triggered whenever commits are pushed
to the main development branch (master).
A new "stable" release is triggered whenever a tag is pushed to the repository.
The release process consists of the following steps:
-
Build a multi-platform Docker image from the referenced commit, and push it as private Package
mentalsmash/uno-dev:<tag>to GitHub's Container registry. -
Test the image by using it to run
uno's full test suite on each target platform. -
Re-tag the image as
mentalsmash/uno:<tag>and push it to both Docker Hub (as a public image), and to GitHub (as an "internal" Package for the mentalsmash organization). -
Update the "release badges" published in the README.
The <tag> used by the generated image depends on the type of release:
| Event | Release Type | Image Tag |
|---|---|---|
push tag without a / in the name |
stable | latest |
push commit to master |
nightly | nightly |
New commits can only be merged to the main development branch via pull request. In order for a pull request to be accepted it must pass all required checks:
-
At least one maintainer must have reviewed and approved the changes.
-
The changes must pass both the "basic" and "full" validation suites.
A "basic" validation will be triggered as soon as a non-draft pull request is opened. If a pull request is opened as draft, the build will be triggered once the PR is "ready for review". Every new commit pushed to the PR branch after that will:
-
Invalidate any approval that the PR received before the push.
-
Cancel (if already in progress) and trigger a new "basic" build.
The "full" validation will be triggered every time the PR transitions into "accepted" state.
Each validation workflow will target one or more platforms, and for each configuration it will:
-
Build a test Docker image for the selected platform.
-
Run
uno's full test suite.
The difference between the two validation workflows lies only in the number of "flavors" and platforms that they test:
| Build Type | amd64 | arm64 |
|---|---|---|
| basic | ✅ | ❌ |
| full | ❌ | ✅ |
uno uses ruff to automatically enforce a consistent
coding style.
The tool is installed with the dev dependency group, and it is run automatically
before every git commit. You can also run the checks manually:
# Enable virtual environment
. .venv/bin/activate
# Run git hooks (both linter and formatter)
pre-commit run --all
# Only linter
ruff check
# Only formatter
ruff format-
Install the
venvmodule:sudo apt-get install -y python3-venv
-
Clone
uno's repository:git clone --recurse-submodules https://github.com/mentalsmash/uno
-
Create a virtual environment:
cd uno python3 -m venv .venv -
(Optional) Make sure
pipandsetuptoolsare up to date:.venv/bin/pip install -U pip setuptools
-
Install
unoand its dependencies:.venv/bin/pip install -e . -
Install
gitcommit hooks:.venv/bin/pre-commit install
uno includes a configuration file for a devcontainer,
which can be used to spin up a development environment using Codespaces,
(and some of the free hours that most accounts receive from GitHub).
By default, uno uses RTI Connext DDS to implement a "synchronization databus" between
its agents. A valid RTI license file must be provided via the RTI_LICENSE_FILE environment variable.
You can request a free evaluation license from RTI.
If you don't have/don't want to get a free license from RTI, you can still use uno but the agent functionality
will not be available, and the UVN will need to be reconfigured by hand.
uno includes a Docker Compose file that can be used to build the development image
required to run integration tests.
The image also supports mounting the local copy of the uno package for testing.
-
Build the image (
mentalsmash/uno-test-runner:latest) with:cd uno/ docker compose build test-runner -
Use it to run the unit tests without having to install
uno's system dependenciesdocker run --rm -v $(pwd):/uno -w /uno \ mentalsmash/uno-test-runner:latest \ pytest -s -v test/unit -
Use it (implicitly) to run the integration tests:
DEV=y pytest -s -v test/integration
The
DEVvariable tells the integration test framework to mount theunopackage from the host to test changes made to it after building the image. If unspecified, the image will use the version ofunoinstalled during build.For increased logging verbosity try:
VERBOSITY=debug DEBUG=y DEV=y pytest -s -v test/integration
To persist the test directories created by each experiment after the tester terminates:
TEST_DIR=/tmp/uno-test DEV=y pytest -s -v test/integration
-
You can also build a test "release" image (
mentalsmash/uno:dev) with:docker compose build uno
NOTE: this image does not install
unoin "editable" mode and henve it will not pick up a local copy mounted as a volume.
The arm64 image can be built locally using QEMU, but running tests with it is not recommended
because of the crawling speed at which emulated instructions run.
Instead, uno CI/CD infrastructure includes arm64 runners that can run the tests natively.
The tests are automatically triggered during every release, and for every "full" PR validation.
Nevertheless, it can be useful to test building the release image locally, which can be achieved with:
docker compose build uno-arm64If you really want to test the local copy of uno on an emulated arm64 container, you
can build an arm64 "test runner" with:
docker compose build test-runner-arm64WARNING: in order to use these commands, you might have to enable QEMU emulation using the tonistiigi/binfmt image:
docker run --privileged --rm tonistiigi/binfmt --install allIf you enounter any emulation problems while using this image (e.g. QEMU segfaults), you can try replacing it with multiarch/qemu-user-static:
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes -c yes