Extract runner-controller into its own repo (gitborg/runner-controller) with semver image releases #201

Öppen
öppnade 2026-07-21 23:10:16 +00:00 av supernaut · 0 kommentarer
Ägare

Prerequisite for #38 (self-host infra deploy). Design tracked internally.

Why (the #38 blocker)

The runner that would deploy bitborg-infra is built inside bitborg-infra: roles/runner-controller/tasks/main.yml builds the controller image on the services host from files/{Containerfile,controller.py} and tags it with a content hash. A self-deploy pipeline can't safely depend on CI substrate living in its own payload. Unblock = extract the controller into a neutral, externally-versioned artifact.

Scope

New repo gitborg/runner-controller (public, AGPL-3.0): controller.py, Containerfile (promote the pinned pip deps into pyproject.toml), test_controller_logic.py → tests/, the runner cloud-init template (decision: bake into the image), a config-schema README (the cross-repo contract). Add .forgejo/workflows/{ci.yml (ruff/mypy/pytest), release.yml (tag v* → build + push git.gitborg.se/gitborg/runner-controller:vX.Y.Z+:sha-XXXX + Forgejo Release)}.

Stays in infra: config.yaml.j2 (host-specific), the Quadlet unit template (change only Image=), the handlers, all group_vars wiring, both vault secrets + the readiness gate. Do NOT move vault_openstack_runner_cloud / runner_controller_os_network_id — backup-drill reuses them.

Slim the consumer role + fix #63 in the same change: delete the on-host build plumbing; add a containers.podman.podman_image: {pull: true} step before the Quadlet install (the forgejo-role pattern, tasks 199-235) + keep the unit-change→restart notify, else a pinned-tag consumer silently no-ops on a bump (the #63 class). Repoint Image= to the pinned registry tag; add a Renovate annotation on runner_controller_image_tag; reject :latest/AutoUpdate=registry for this destructive control-plane daemon.

Bootstrap (no gap)

Tag v1.0.0 at byte-parity with current main. release.yml runs on the still-in-repo host-built ci pool → the existing controller mints the runner that builds its own replacement. Only after v1.0.0 is in the registry, PR the infra slim-down (apply via infra-apply). Don't delete the build plumbing until v1.0.0 is confirmed pushed.

Risks

  • #63 pull-on-tag-change (must-fix here, not a follow-up): the content-hash mechanism guarantees rebuild+restart today; a pinned-tag consumer that only did state: started would keep the old image. The pre-pull + unit-restart is mandatory. Verify the running digest actually changes on a bump.
  • Config-schema skew across repos: document the schema; load_config fails loudly on missing keys; schema change = MAJOR bump.
  • Renovate vs own registry: verify the docker datasource resolves git.gitborg.se/gitborg/runner-controller tags anonymously on first bump; else add a hostRules token.

ADR: amend #0021 (new ADR — extraction + semver releases; retire host-build). Blocks #38.

area/ci, area/infra, ready-for-implementation, type/task

Prerequisite for #38 (self-host infra deploy). Design tracked internally. ## Why (the #38 blocker) The runner that would deploy bitborg-infra is *built inside* bitborg-infra: `roles/runner-controller/tasks/main.yml` builds the controller image on the services host from `files/{Containerfile,controller.py}` and tags it with a content hash. A self-deploy pipeline can't safely depend on CI substrate living in its own payload. **Unblock = extract the controller into a neutral, externally-versioned artifact.** ## Scope **New repo `gitborg/runner-controller` (public, AGPL-3.0):** `controller.py`, `Containerfile` (promote the pinned pip deps into `pyproject.toml`), `test_controller_logic.py` → `tests/`, the runner cloud-init template (**decision: bake into the image**), a config-schema README (the cross-repo contract). Add `.forgejo/workflows/{ci.yml (ruff/mypy/pytest), release.yml (tag v* → build + push `git.gitborg.se/gitborg/runner-controller:vX.Y.Z` + `:sha-XXXX` + Forgejo Release)}`. **Stays in infra:** `config.yaml.j2` (host-specific), the Quadlet unit template (change only `Image=`), the handlers, all group_vars wiring, both vault secrets + the readiness gate. **Do NOT move** `vault_openstack_runner_cloud` / `runner_controller_os_network_id` — `backup-drill` reuses them. **Slim the consumer role + fix #63 in the same change:** delete the on-host build plumbing; add a `containers.podman.podman_image: {pull: true}` step before the Quadlet install (the forgejo-role pattern, tasks 199-235) + keep the unit-change→restart notify, else a pinned-tag consumer silently no-ops on a bump (the #63 class). Repoint `Image=` to the pinned registry tag; add a Renovate annotation on `runner_controller_image_tag`; reject `:latest`/`AutoUpdate=registry` for this destructive control-plane daemon. ## Bootstrap (no gap) Tag `v1.0.0` at byte-parity with current `main`. `release.yml` runs on the *still-in-repo host-built* `ci` pool → the existing controller mints the runner that builds its own replacement. Only after `v1.0.0` is in the registry, PR the infra slim-down (apply via infra-apply). Don't delete the build plumbing until `v1.0.0` is confirmed pushed. ## Risks - **#63 pull-on-tag-change (must-fix here, not a follow-up):** the content-hash mechanism guarantees rebuild+restart today; a pinned-tag consumer that only did `state: started` would keep the old image. The pre-pull + unit-restart is mandatory. Verify the running digest actually changes on a bump. - **Config-schema skew across repos:** document the schema; `load_config` fails loudly on missing keys; schema change = MAJOR bump. - **Renovate vs own registry:** verify the `docker` datasource resolves `git.gitborg.se/gitborg/runner-controller` tags anonymously on first bump; else add a hostRules token. ADR: amend #0021 (new ADR — extraction + semver releases; retire host-build). Blocks #38. area/ci, area/infra, ready-for-implementation, type/task
Logga in för att delta i denna konversation.
Ingen milstolpe
Inga tilldelade
1 deltagare
Notiser
Förfallodatum
Förfallodatumet är ogiltigt eller utanför gränserna. Använd formatet "åååå-mm-dd".

Inget förfallodatum satt.

Beroenden

Inga beroenden satta

Referens
bitborg/bitborg-infra#201
Ingen beskrivning angiven.