From c5f60fd58f008acbfdb67762d2cc2f880b0c48a7 Mon Sep 17 00:00:00 2001 From: atlas Date: Sat, 19 Sep 2026 02:20:35 +0200 Subject: [PATCH] nix: stop three defaults from consulting hyperhive.enable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- nix/host-modules/hive-ci.nix | 3 +- nix/host-modules/hive-forge/default.nix | 13 +++---- nix/host-modules/swarm-controller.nix | 27 ++++++-------- nix/module-eval.nix | 47 +++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 27 deletions(-) diff --git a/nix/host-modules/hive-ci.nix b/nix/host-modules/hive-ci.nix index 1e41285d..3cb86f5c 100644 --- a/nix/host-modules/hive-ci.nix +++ b/nix/host-modules/hive-ci.nix @@ -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). ''; } ]; diff --git a/nix/host-modules/hive-forge/default.nix b/nix/host-modules/hive-forge/default.nix index 3562fbd5..32bb8921 100644 --- a/nix/host-modules/hive-forge/default.nix +++ b/nix/host-modules/hive-forge/default.nix @@ -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). diff --git a/nix/host-modules/swarm-controller.nix b/nix/host-modules/swarm-controller.nix index 1a1e0932..e045ee6d 100644 --- a/nix/host-modules/swarm-controller.nix +++ b/nix/host-modules/swarm-controller.nix @@ -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 diff --git a/nix/module-eval.nix b/nix/module-eval.nix index 572003c7..5ab93a11 100644 --- a/nix/module-eval.nix +++ b/nix/module-eval.nix @@ -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