butler#

One butler.py for every project, with the same commands in each. A project keeps a short shim at its root and a config file that says what it has: a Tauri app, a FastAPI server, a browser extension, a CMake build. butler turns that into a command line for building, testing, deploying and releasing it, and leaves out every command the project has no use for.

Why it exists#

Every project used to grow its own build script, and each one did the same things a little differently and broke in its own way. chords' script was 735 lines before it moved to butler; now it is a 96-line shim, a config file and a handful of tasks only chords needs. Every project on this site, waterrise included, runs on it.

The shim is plain Python with nothing to install. It pins a release of the harness, puts it in a cached virtualenv the first time it runs, and hands over. A fresh clone needs Python 3.11 or newer and nothing else, and moving to a newer butler means changing the version the shim pins.

What it does#

  • butler/butler.toml is the whole command line. A command exists only if the config says the project has that thing, so --help always describes the project in front of you.
  • app: Tauri desktop builds and Android, with signing, installing and logcat. server: FastAPI under Docker Compose, deployed over SSH. extension: Chrome and Firefox bundles. build and check: CMake with a Docker build environment, MegaLinter and clang-tidy.
  • doctor lists every tool the declared components need and says what is missing, before a build finds out ten minutes in.
  • release squashes dev onto main, tags it, waits for the CI build, and publish exports the result to a public mirror, with its release copied.
  • planning runs waterrise for the project.
  • What only one project does goes in butler/butler_tasks.py, next to the built-in commands.

Run it#

You need Python 3.11 or newer and git. Without butler installed, scaffold a project from a clone of the harness:

git clone https://github.com/vaelum/butler-harness.git
cd your-project
PYTHONPATH=../butler-harness/src python3 -m butler new . --tasks

That writes butler.py, butler/butler.toml and butler/butler_tasks.py. Commit all three. Then:

python butler.py --help      # what the config produced
python butler.py doctor      # what tooling is installed

Add --app, --server or both to new for a project that has them, or declare them later in butler/butler.toml.

Read more#

  • Documentation: adding butler to a project, and every config key and command.
  • Source: the repository on GitHub, with its README and releases, under the MIT licence.