Last of the swarm.* -> deploy.* moves for the enable-shaped options.
Whether this host also runs the CI runner is a per-machine decision, so
it was sitting in the namespace that has to be identical swarm-wide.
Renames all five options, not just enable: name, concurrency, labels and
package all describe the runner THIS host would run, and leaving them
behind would keep the original defect for four more options. One rename
entry each, because ci is a plain attrset rather than a submodule type,
so there is no parent path to rename in one go.
deploy.forgejo is the name deploy.nix's own header already specifies,
including this exact case -- "ci (does this host run the runner too) is
exactly that shape". It is the only entry with no enable: the forge is
not optional, it deploys with hyperhive itself, so running the runner is
the only deployment decision it has.
Also fixes hive-c0re/src/forge/ci_runner.rs, whose doc comment named
services.hyperhive.forge.ci.enable -- missing the swarm. segment, so it
had never resolved to a real option.
act_runner records the --instance URL it was registered with and reads the
forge address from .runner and nowhere else: the nix option reaches only
`register`, and upstream re-registers on a changed token or labels, never on
a changed URL. Our own precond short-circuits on .runner existing, and
runner_valid asks whether the runner id still exists -- which after a rename
it does. So changing swarm.forge.domain left the runner dialling a name its
container's derived extraHosts no longer resolves, with every check green.
The symptom is CI going quiet rather than anything failing.
Compare the persisted address against the configured base as part of the
same early return. A disagreement mints a fresh registration token, which
changes the token hash upstream already keys on, so upstream removes .runner
and re-registers against the current --instance. This module never writes or
deletes that file; the deletion stays with the script that owns registration.
The comparison is host-only and lenient on purpose. Both sides render from
one nix expression -- http://${swarm.forge.domain}, reaching the runner as
instances.hive.url and this daemon as HIVE_FORGE_URL -- so they cannot drift,
while scheme, port and trailing slash are exactly the cosmetic differences
that would otherwise re-register on every boot. Unreadable, missing or
unparseable input keeps the existing credentials, matching runner_valid's
treatment of a transport error: only a positive disagreement counts.
Both warn!-and-forget sites in ensure_ci_runner_registered() now also
call set_boot_warning():
- fetch_registration_token failure → crit banner (forge unreachable or
API error; runner stays with stale/absent creds)
- hive-priv register_ci_runner failure → crit banner (EROFS or priv
socket error; runner token not written)
Both are only ever invoked from ensure_all() at hive-c0re startup (no
periodic retry), so set_boot_warning() is the right API: the banner
persists until the next c0re restart that re-runs the step, which is
exactly when a config/environment fix (e.g. the ReadWritePaths EROFS
fix from 64075107) would take effect.
Journal warn! lines are kept alongside the banner (belt-and-suspenders).
Remaining in scope for #2289: sync_agent() warn! sites (called from
both startup and rebuild paths — needs set_warning RAII or explicit
return value to enable later success to clear the banner; left for a
follow-up).
Ran nix fmt on the whole change (not just the .nix): rustfmt wraps the long
ci_enabled() is_ok_and line that tripped the treefmt CI gate. Adds the # Errors
doc section on the pub priv_client::register_ci_runner per the HOW-TO rule.
Part B (c0re half). New forge/ci_runner.rs: validate the hive-ci runner's
persisted .runner against the forge (GET /admin/runners/{id}); if absent or
stale, mint a fresh registration token (GET /admin/runners/registration-token,
raw request against the local http forge — forgejo-api 0.11 doesn't wrap it)
and hand it to hive-priv's RegisterCiRunner to write the host env-file +
restart the runner. Gated on HYPERHIVE_FORGE_CI_ENABLED; best-effort (never
aborts the startup sweep). Called from ensure_all after the org/repo seeding.
The nix boot-path change (drop prefetch gating, add runner precond, set the
env var) lands next on this branch.