Contributions¶
Contributions are welcome!
The repository is hosted at gitlab.com/yaal/canaille.
Discuss¶
If you want to implement a feature or a bugfix, please start by discussing it with us on the bugtracker or the matrix room.
Development environment¶
You can either run the demo locally or with Docker.
After having launched the demo you have access to several services:
A canaille server at canaille.localhost:5000
A dummy client at client1.localhost:5001
Another dummy client at client2.localhost:5002
A mail catcher at maildump.localhost:1080
The canaille server has some default users:
A regular user which login and password are user;
A moderator user which login and password are moderator;
An admin user which admin and password are admin;
A new user which login is james. This user has no password yet, and his first attempt to log-in would result in sending a password initialization email (if a smtp server is configured).
Backends¶
Canaille comes with several backends:
a lightweight test purpose memory backend
a sql backend, based on sqlalchemy
a production-ready LDAP backend
Local environment¶
The only tool required for local development is uv. Make sure to have uv installed on your computer to be able to hack Canaille.
Initialize your development environment with:
uv sync --all-groups --all-extras
if you want to have everything at your fingertips. Note that it may compile some Python dependencies that would expect things to be installed on your system;uv sync --extra front --extra oidc
to have a minimal working development environment. This will allow you to run the tests withuv pytest --backend memory
.uv sync --extra front --extra oidc --extra sqlite
to have a minimal working development environment with SQLite backend support. This will allow you to run the tests withuv pytest --backend sql
.uv sync --extra front --extra oidc --extra ldap
to have a minimal working development environment with LDAP backend support. This will allow you to run the tests withuv pytest --backend ldap
. Some dependencies of Canaille might need to be compiled, so you probably want to check that GCC and cargo are available on your computer.
SQL¶
With the SQL backend, the demo instance will load and save data in a local sqlite database.
uv run devserver
Memory¶
With the memory backend, all data is lost when Canaille stops.
uv run devserver --backend memory
LDAP¶
With the LDAP backend, all data is lost when Canaille stops.
uv run devserver --backend ldap
Note
If you want to run the demo locally with the LDAP backend, you need to have
OpenLDAP installed on your system.
It is generally shipped under the slapd
or openldap
package name.
Warning
On Debian or Ubuntu systems, the OpenLDAP slapd binary usage might be restricted by apparmor, and thus makes the tests and the demo fail. This can be mitigated by removing apparmor restrictions on slapd.
sudo apt install --yes apparmor-utils
sudo aa-complain /usr/sbin/slapd
Docker environment¶
SQL¶
With the SQL backend, the demo instance will load and save data in a local sqlite database.
cd demo
docker compose up
Memory¶
With the memory backend, all data is lost when Canaille stops.
cd demo
docker compose --file docker-compose-memory.yml up
LDAP¶
With the LDAP backend, all data is lost when Canaille stops.
cd demo
docker compose --file docker-compose-ldap.yml up
Populate the database¶
The demo database comes populated with some random users and groups. If you need more, you can generate
users and groups with the populate
command:
# If using docker:
docker compose exec canaille env CONFIG=conf-docker/canaille-ldap.toml uv run canaille populate --nb 100 users # or docker-compose
# If running in local environment
env CONFIG=conf/canaille-ldap.toml uv run canaille populate --nb 100 users
Adapt to use either the ldap or the sql configuration file. Note that this will not work with the memory backend.
Unit tests¶
To run the tests, you just can run uv run pytest and/or uv run tox to test all the supported python environments. Everything must be green before patches get merged.
To test a specific backend you can pass --backend memory
, --backend sql
or --backend ldap
to pytest and tox.
The test coverage is 100%, patches won’t be accepted if not entirely covered. You can check the
test coverage with uv run pytest --cov --cov-report=html
or uv run tox -e coverage -- --cov-report=html
.
You can check the HTML coverage report in the newly created htmlcov directory.
Code style¶
We use ruff along with other tools to format our code.
Please run uv run tox -e style
on your patches before submitting them.
In order to perform a style check and correction at each commit you can use our
pre-commit configuration with uv run pre-commit install
.
Front¶
The interface is built upon the Fomantic UI CSS framework. The dynamical parts of the interface use htmx.
Using Javascript in the interface is tolerated, but the whole website MUST be accessible for browsers without Javascript support, and without any feature loss.
Because of Fomantic UI we have a dependency to jQuery, however new contributions should not depend on jQuery at all. See the related issue.
Documentation¶
The documentation is generated when the tests run:
tox -e doc
You can also run sphinx by hand, that should be faster since it avoids the tox environment initialization:
sphinx-build doc build/sphinx/html/en
The generated documentation is located at build/sphinx/html/en
.
Note
The documentation generates dynamic screenshots of Canaille using sphinxcontrib-screenshot, that internally uses Playwright. Playwright needs to be initialized with the following command:
uv run playwright install firefox
Code translation¶
Translations are done with Weblate.
The following commands are there as documentation, only the message extraction is needed for contributors. All the other steps are automatically done with Weblate.
Message extraction¶
After you have edited translatable strings, you should extract the messages with:
pybabel extract --mapping-file pyproject.toml --copyright-holder="Yaal Coop" --output-file canaille/translations/messages.pot canaille
Language addition¶
You can add a new language manually with the following command, however this should not be needed as Weblate takes car of this:
pybabel init --input-file canaille/translations/messages.pot --output-dir canaille/translations --locale <LANG>
Catalog update¶
You can update the catalogs with the following command, however this should not be needed as Weblate automatically update language catalogs when it detects new strings or when someone translate some existing strings. Weblate pushes happen every 24h.
pybabel update --input-file canaille/translations/messages.pot --output-dir canaille/translations --ignore-obsolete --no-fuzzy-matching --update-header-comment
Catalog compilation¶
You can compile the catalogs with the following command, however this should not be needed as catalogs are automatically compiled before running the unit tests, before launching the demo and before compiling the Canaille python package:
pybabel compile --directory canaille/translations --statistics
Documentation translation¶
Translations are done with Weblate.
The following commands are there as documentation, only the message extraction and the language addition is needed for contributors.
Message extraction¶
After you have edited translatable strings, you should extract the messages with:
sphinx-build --builder gettext doc doc/locales
Language addition¶
You can add a new language manually with the following command, however this should not be needed as Weblate takes car of this:
sphinx-intl update --pot-dir doc/locales --locale-dir doc/locales -l fr
Build the documentation in another language¶
sphinx-build --builder html --define language=fr doc build/sphinx/html/fr
Build a release¶
Python package¶
The Python packaging step is took care of by uv:
uv build
Binary file¶
To build a single binary of Canaille, you can use pyinstaller by installing the release dependency group:
uv sync --group release --all-extras --no-dev
uv run pyinstaller canaille.spec
Publish a new release¶
Check that dependencies are up to date with
uv sync --all-extras --all-groups --upgrade
and update dependencies accordingly in separated commits;Check that tests are still green for every supported python version, and that coverage is still at 100%, by running
uv run tox
;Check that the demo environments are still working, both the local and the Docker one;
Check that the Release notes section is correctly filled up;
Increase the version number in
pyproject.toml
;Commit with
git commit
;Build the packages with
uv build
;Install from the .whl generated with
uv pip install <path/to/dist/canaille-x.x.xx-py3-none-any.whl>[front,oidc,postgresql,server,otp,sms]
;Test creation of a user with
canaille config dump
andcanaille create user --user-name admin --password admin --emails admin@mydomain.example --given-name George --family-name Abitbol
andcanaille run
;Try to connect the user;
Publish the Python package on test PyPI with
uv publish --publish-url https://test.pypi.org/legacy/
;Install the test package somewhere with
pip install --extra-index-url https://test.pypi.org/simple --upgrade "canaille[front,oidc,postgresql,server,otp,sms]"
. Check that everything looks fine;Publish the Python package on production PyPI
uv publish
;Tag the commit with
git tag XX.YY.ZZ
;Push the release commit and the new tag on the repository with
git push --tags
.