nix: stop three defaults from consulting hyperhive.enable

hive-forge's publicUrl and behindGateway, and swarm-controller's
forgeTokenFile, no longer gate their default on
config.services.hyperhive.enable — none of the three has a reader that
depends on hyperhive being enabled to make sense of the value, so the
extra condition only added a hidden coupling. module-eval.nix gains a
centralToggleOff fixture plus four cases asserting each affected
default now resolves identically whether the toggle is on or off.

Refs #4500
This commit is contained in:
atlas 2026-09-19 02:20:35 +02:00 committed by mara
commit c5f60fd58f
4 changed files with 63 additions and 27 deletions

View file

@ -167,8 +167,7 @@ in
services.hyperhive.deploy.forgejo.behindGateway = true.
The CI container runs with a private network namespace and
reaches the forge through the gateway vhost on the bridge IP.
Set behindGateway = true (it defaults to true alongside
services.hyperhive.enable).
Set behindGateway = true (it is the default).
'';
}
];

View file

@ -200,11 +200,7 @@ in
publicUrl = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default =
if config.services.hyperhive.enable && deployCfg.forgejo.behindGateway then
"https://${cfg.domain}"
else
null;
default = if deployCfg.forgejo.behindGateway then "https://${cfg.domain}" else null;
defaultText = lib.literalExpression ''
if behindGateway then "https://''${domain}" else null
'';
@ -303,8 +299,7 @@ in
behindGateway = lib.mkOption {
type = lib.types.bool;
default = config.services.hyperhive.enable;
defaultText = lib.literalExpression "config.services.hyperhive.enable";
default = true;
description = ''
Serve forgejo through the hive-gateway nginx as a sub-domain
vhost (`server_name = cfg.domain`) instead of directly on
@ -318,8 +313,8 @@ in
- `gateway.localHostsEntry = true` extends `/etc/hosts` to
include `cfg.domain 127.0.0.1` for local dev.
Defaults to `services.hyperhive.enable` (the gateway always runs
alongside hyperhive, so forge auto-routes through it). Set `false`
Defaults to `true` (the gateway always runs alongside
hyperhive, so forge auto-routes through it). Set `false`
explicitly to keep forge on the direct port even though the
gateway is running (e.g. an external git client that doesn't
traverse the gateway).

View file

@ -502,21 +502,16 @@ in
forgeTokenFile = lib.mkOption {
type = lib.types.nullOr lib.types.str;
# The forge has no `enable` of its own to check — neither half of
# its split namespace carries one — the module activates on the general
# `config.services.hyperhive.enable` instead (see
# `hive-forge/default.nix`'s own `config = lib.mkIf
# config.services.hyperhive.enable { ... }`), so that's the
# condition to match here too. Referencing a `forge.enable` that
# doesn't exist threw `attribute 'enable' missing` on every host
# that turns swarm-controller on — caught in review, not by
# `nix flake check` (nothing in its checked combinations forced
# this particular default to actually evaluate).
default =
if config.services.hyperhive.enable then deployCfg.forgejo.hostSwarmControllerTokenFile else null;
# The forge has no `enable` of its own to condition this on —
# neither half of its split namespace carries one — and it deploys
# unconditionally wherever the rest of the stack does, so its own
# delivery path is simply the right default. The controller's units
# are the thing that decides whether the file is ever read: they only
# exist under `deploy.swarm-controller.enable`, and a host whose forge
# lives elsewhere overrides this (or sets `null`) explicitly.
default = deployCfg.forgejo.hostSwarmControllerTokenFile;
defaultText = lib.literalExpression ''
forge's own `hostSwarmControllerTokenFile` when this host runs
hyperhive at all (forge has no separate enable), else null
config.services.hyperhive.deploy.forgejo.hostSwarmControllerTokenFile
'';
example = "/var/lib/secrets/swarm-controller-forge.token";
description = ''
@ -525,8 +520,8 @@ in
`forgejo-swarm-controller-account` + `hive-forge-swarm-controller-token`
units, which mint and collect it onto forge's own host).
Defaults to forge's own delivery path on every host running
hyperhive (forge deploys unconditionally alongside it see
Defaults to forge's own delivery path (forge deploys
unconditionally alongside the rest of the stack see
`hive-forge/default.nix`, it has no `enable` of its own).
Override explicitly if forge's actual token file ends up
somewhere else copy it out of forge's

View file

@ -97,6 +97,15 @@ let
allLocal = hive { deploy.singleHostSwarm = true; };
bare = hive { };
# The same stub with the central toggle off. Paired with `bare` below to pin
# the defaults that used to read `services.hyperhive.enable` and no longer
# do: each is asserted to hold the SAME literal in both, so a future edit
# that quietly re-introduces the dependency — or that changes what the
# default renders for a hive with the toggle on — fails here. Reading an
# option off this fixture forces that option only, not the config, so the
# toggle being off costs nothing.
centralToggleOff = hive { enable = false; };
withCi = hive { deploy.forgejo.ci.enable = true; };
# A host configured against the pre-rename option path. `mkRenamedOptionModule`
@ -781,6 +790,44 @@ let
# Each case: a name stating the property, and `ok`.
cases = [
{
# Both halves matter. The equality is the "no longer consults the central
# toggle" half; the literal is the "and still renders what it always
# did" half, which an equality on its own would let drift to `false` in
# lockstep.
name = "the forge's behindGateway default is true regardless of the central toggle";
ok =
bare.services.hyperhive.deploy.forgejo.behindGateway == true
&& centralToggleOff.services.hyperhive.deploy.forgejo.behindGateway == true;
}
{
# Downstream of the one above — publicUrl reads `behindGateway`, so it
# tracked the central toggle transitively as well as directly. The domain
# is the stub's swarm domain, which both fixtures share.
name = "the forge's publicUrl default follows behindGateway alone, not the central toggle";
ok =
bare.services.hyperhive.swarm.forge.publicUrl == "https://forge.t.local"
&& centralToggleOff.services.hyperhive.swarm.forge.publicUrl == "https://forge.t.local";
}
{
# And that it still tracks `behindGateway` at all: without this arm the
# case above passes just as well for a default hardcoded to the URL.
name = "the forge's publicUrl default is still null with behindGateway off";
ok =
(hive { deploy.forgejo.behindGateway = false; }).services.hyperhive.swarm.forge.publicUrl == null;
}
{
# The controller's token path defaulted to forge's delivery path only on
# a host with the central toggle on, and to `null` otherwise. Forge
# deploys unconditionally, so the path is now unconditional too.
name = "the swarm controller's forgeTokenFile defaults to forge's delivery path regardless of the central toggle";
ok =
let
forgePath = "/var/lib/hyperhive-forge/swarm-controller.token";
in
bare.services.hyperhive.deploy.swarm-controller.forgeTokenFile == forgePath
&& centralToggleOff.services.hyperhive.deploy.swarm-controller.forgeTokenFile == forgePath;
}
{
# `ctl` is in no deny list — it is reserved *because it is the subject a
# cert-auth role accepts*, which is a value an operator sets, so a