Skip to content

Releasing

All packages are released together under one version (see Packaging, Installation and Setup). A release is a tag; the workflow wheels.yml builds, tests, creates the GitHub release with the wheels and publishes to PyPI after a manual approval (one job per package).

  • Origin: the code stays under the MIT license of Phoniebox (its copyright line is in LICENSE) and the README names Phoniebox as the origin. The start and shutdown sounds and the placeholder cover that came from Phoniebox were replaced by our own (ci/make_sounds.py, the logo bear), so nothing of unclear origin is left. The Phoniebox project was told about the project and has no objections.
  • Searched for conflicts with the name “Lauschkiste” (trademark registers of the DPMA and EUIPO) and for similar logos (October 2026: no problems expected).
  • Private vulnerability reporting is switched on (repository Settings → Code security): the Code of Conduct and SECURITY.md send reports there.
  • Repository description, topics and social preview image are set.
  • The accounts, pending publishers and environments below exist.
  • A test upload to TestPyPI and a fresh installation from it on a box worked.

PyPI needs no token in the repository: the workflow proves its identity to PyPI (“trusted publishing”). What has to be done once, by the owner of the PyPI account:

  1. Create accounts on pypi.org and test.pypi.org (two separate accounts, both with two-factor authentication).

  2. On each of them, for every package below, add a pending publisher (Account settings → Publishing → “Add a new pending publisher”, tab GitHub). The package is created by its first upload. The same three values everywhere:

    Field Value
    Owner ladidadida
    Repository name lauschkiste
    Workflow name wheels.yml

    PyPI accepts one configuration as pending for one new project only, so every package has its own environment name: testpypi-<project> on test.pypi.org and pypi-<project> on pypi.org.

    PyPI project name Environment name on test.pypi.org on pypi.org
    lauschkiste testpypi-lauschkiste pypi-lauschkiste
    lauschkiste-core testpypi-lauschkiste-core pypi-lauschkiste-core
    lauschkiste-plugins testpypi-lauschkiste-plugins pypi-lauschkiste-plugins
    lauschkiste-plugins-raspberry-pi testpypi-lauschkiste-plugins-raspberry-pi pypi-lauschkiste-plugins-raspberry-pi

    PyPI allows three pending publishers at a time (an entry no longer counts once its first upload has created the project). A package that exists on PyPI already needs none; see “Packages in rounds” below.

  3. In the GitHub repository (Settings → Environments) create the environment pypi and give it required reviewers (yourself): it is the gate before the upload to PyPI, which cannot be undone. The other environments (testpypi-..., pypi-...) are created by GitHub when the workflow first uses them; they need no settings.

The workflow has one job per package. A job whose package has no trusted publisher yet fails with “invalid-publisher”, the others succeed. After each upload that created projects:

  1. Register the next (up to three) pending publishers of the packages that failed.
  2. In the workflow run on GitHub choose Re-run failed jobs: only those uploads run again.

Repeat until all four jobs are green (the four fit in two rounds). This is needed once per registry (TestPyPI, PyPI); later uploads need no pending publishers any more.

Every upload needs a version that was not used before, so test with development versions:

Terminal window
ci/set_version.py 0.1.0a4.dev1
git commit -am "Version 0.1.0a4.dev1" && git push

Run the workflow “Wheels and install” by hand (Actions → Run workflow, tick “Publish this ref to TestPyPI”). When it is green, install from there on a fresh machine:

Terminal window
curl -fsSL https://raw.githubusercontent.com/ladidadida/lauschkiste/main/install.sh \
| bash -s -- --from testpypi --version 0.1.0a4.dev1

The installer takes everything from PyPI (and piwheels) first; TestPyPI only supplies the Lauschkiste packages, because it holds test copies of other projects that must not be used.

  1. Set the version and commit it: ci/set_version.py 0.1.0-alpha.4.
  2. Tag it and push the tag: git tag v0.1.0-alpha.4 && git push origin v0.1.0-alpha.4. The workflow checks that the tag matches the version.
  3. The workflow builds, runs the install tests (from wheels, from a package index, from the source), creates the GitHub release (a pre-release while the tag has a suffix) and then waits for your approval of the pypi environment. After the approval the packages are on PyPI.
  4. Check: uv tool install lauschkiste on a machine, lauschctl plugin list.
  5. The installer installs from PyPI by default (install.sh, and lauschctl update follows the way a box was installed).

While there are only pre-releases, pip install lauschkiste needs --pre (uv and the installer do not).

  • uvx twine check dist/*: the descriptions render on PyPI.
  • test/test_packaging.py: names, one version, exact pins, README and LICENSE in every package.
  • Installation in fresh Debian containers from the wheels, from a package index built from the release files and from a checkout.