From 77746ab054a8601c7804f934245e13e4c5f1d12b Mon Sep 17 00:00:00 2001 From: Michael Johnson Date: Thu, 1 Oct 2026 18:08:44 -0400 Subject: [PATCH 1/2] generate: stack choices, one way to deploy per runtime; release v1.10.0 x-daemonless.choices. A database choice (kind: database) names the engines the app runs on and what it calls the connection in its own env; dbuild supplies the postgres or mariadb service from one shared definition, so twenty apps do not carry twenty copies of the same block and a fix lands everywhere. sqlite runs nothing; external asks for a database the person already runs. A part choice (immich's machine learning) is the app's own: a profile to switch on, env to set, values to ask for. The default is always the compose as it stands, so podman-compose up -d with nothing set is the default answer; lint refuses a default that switches something on and a mapped variable the app never reads. --- .github/workflows/daemonless-build.yaml | 2 +- dbuild/__init__.py | 2 +- dbuild/choices.py | 410 +++++++++++++++++++++++ dbuild/config.py | 16 +- dbuild/docs.py | 121 +++++++ dbuild/lint.py | 5 + dbuild/templates/README.j2 | 224 +++++-------- dbuild/templates/README.mkdocs.j2 | 188 ++++++----- dbuild/templates/appjail-director.yml.j2 | 5 +- docs/dbuild.1 | 2 +- tests/test_docs.py | 185 ++++++++++ 11 files changed, 924 insertions(+), 236 deletions(-) create mode 100644 dbuild/choices.py diff --git a/.github/workflows/daemonless-build.yaml b/.github/workflows/daemonless-build.yaml index 5b3e73a..83e3c75 100644 --- a/.github/workflows/daemonless-build.yaml +++ b/.github/workflows/daemonless-build.yaml @@ -50,7 +50,7 @@ on: env: REGISTRY: ghcr.io - DBUILD_REF: v1.9.17 + DBUILD_REF: v1.10.0 jobs: # Detect which variants exist and build dynamic matrix diff --git a/dbuild/__init__.py b/dbuild/__init__.py index 849ab40..a8c4b3a 100644 --- a/dbuild/__init__.py +++ b/dbuild/__init__.py @@ -1,4 +1,4 @@ """dbuild: FreeBSD OCI container image build tool. """ -VERSION = "1.9.17" +VERSION = "1.10.0" diff --git a/dbuild/choices.py b/dbuild/choices.py new file mode 100644 index 0000000..52aba7f --- /dev/null +++ b/dbuild/choices.py @@ -0,0 +1,410 @@ +"""Stack choices: what a compose offers under ``x-daemonless.choices``. + +Two kinds of choice. The common one is a **database**: the app says which +engines it can run on and what it calls the connection in its own env, and +dbuild supplies the services -- one definition of a daemonless postgres or +mariadb service, shared by every app, fixed in one place:: + + x-daemonless: + choices: + database: + kind: database + offers: [sqlite, postgres, mariadb, external] + default: sqlite + env: + type: VIKUNJA_DATABASE_TYPE # the app's own names + host: VIKUNJA_DATABASE_HOST + user: VIKUNJA_DATABASE_USER + password: VIKUNJA_DATABASE_PASSWORD + name: VIKUNJA_DATABASE_DATABASE + types: { mariadb: mysql } # the app's word for an engine, when it differs + +The app's service reads those variables (``${VIKUNJA_DATABASE_TYPE:-sqlite}`` +and so on); lint checks they are there. The generated database service reads +the same variables, so one .env feeds both and nothing is wired by hand. +``external`` is a database the person already runs: no service, the +connection asked for. + +The other kind is a **part** the app can run with or without (immich's +machine learning). That one is the app's own, so it is written out: a +profile to switch on, env to set, values to ask for:: + + choices: + machine_learning: + label: Machine learning + default: "on" + options: + "on": { label: On, profile: ml } + "off": { label: Off, env: { IMMICH_ML_ENABLED: "false" } } + +Either way the default option is the compose as it stands: it names no +profile and adds no service, so ``podman-compose up -d`` with nothing set +is the default answer -- what a script, or a host with no UI, gets. + +For everyone who copies files instead of running fjord, each non-default +option gets a flattened pair: ``compose.-