From 190763b3a28784783be87ba334c591573b49ad36 Mon Sep 17 00:00:00 2001 From: atlas Date: Mon, 7 Sep 2026 19:29:04 +0200 Subject: [PATCH] swarm: move the swarm UI's package to deploy, emptying swarm.ui MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same rule as the four movers before it. What makes this one different is that `package` was the LAST option under `services.hyperhive.swarm.ui` — `enable` moved in an earlier slice — so the namespace now holds nothing and survives only as its two rename entries. Two consequences worth naming: flake.nix set `swarm.ui.package` directly. Left alone the shim would have kept it working, which is exactly the trap: this repo's own flake would then be setting the option through its own deprecation shim and warning on every eval. It is repointed here. Four sibling assignments in that file name movers this commit does not touch; they move with theirs. The `cfg` alias is deleted. With the one code reader repointed it bound nothing but an empty attrset — which still evaluates, so nothing would have failed; it would just have sat there implying `swarm.ui` still held something. Three comments naming `cfg.package` are repointed with it. `uiOldPath` sets both old paths, so dropping either rename fails the eval. Its case reads the vhost's rendered `root` rather than the option, because that is the half a resolving-but-unwired shim would break. Not touched: swarm-ui.nix's description says its default is wired "the same way `swarm.controller.package` is", which is true until the controller moves. It belongs to that commit, not this one. Refs #3772. --- flake.nix | 2 +- nix/host-modules/deploy.nix | 7 ++++++ nix/host-modules/swarm-ui.nix | 40 +++++++++++++++++------------------ nix/module-eval.nix | 35 +++++++++++++++++++++++++++++- 4 files changed, 62 insertions(+), 22 deletions(-) diff --git a/flake.nix b/flake.nix index cefc5a2f..65763031 100644 --- a/flake.nix +++ b/flake.nix @@ -148,7 +148,7 @@ services.hyperhive.swarm.controller.swarmctlPackage = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.swarmctl; - services.hyperhive.swarm.ui.package = + services.hyperhive.deploy.swarm-ui.package = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.swarm-ui; services.hyperhive.swarm.nats.authPackage = diff --git a/nix/host-modules/deploy.nix b/nix/host-modules/deploy.nix index d8e818b8..034c0f28 100644 --- a/nix/host-modules/deploy.nix +++ b/nix/host-modules/deploy.nix @@ -362,6 +362,13 @@ in [ "services" "hyperhive" "swarm" "victoriametrics" "package" ] [ "services" "hyperhive" "deploy" "victoriametrics" "package" ] ) + # With this one `services.hyperhive.swarm.ui` holds nothing at all — it had + # exactly two options and both have moved, so the namespace now exists only + # as this entry and the `enable` one above it. + (lib.mkRenamedOptionModule + [ "services" "hyperhive" "swarm" "ui" "package" ] + [ "services" "hyperhive" "deploy" "swarm-ui" "package" ] + ) ]; # ⚠️ `deploy.forgejo` is declared in ./hive-ci.nix, not here, and it is the diff --git a/nix/host-modules/swarm-ui.nix b/nix/host-modules/swarm-ui.nix index dd389558..c7c7aac1 100644 --- a/nix/host-modules/swarm-ui.nix +++ b/nix/host-modules/swarm-ui.nix @@ -13,7 +13,6 @@ ... }: let - cfg = config.services.hyperhive.swarm.ui; deployCfg = config.services.hyperhive.deploy; gatewayCfg = config.services.hyperhive.gateway; autheliaCfg = config.services.hyperhive.swarm.authelia; @@ -22,11 +21,11 @@ let # this UI was left out of that overlay entirely (an operator with a # stylix-themed host saw the dashboard in their own colours but this # UI still on the default Catppuccin palette), because nothing here - # ever served a themed `colors.css` in place of `cfg.package`'s own. + # ever served a themed `colors.css` in place of `deployCfg.swarm-ui.package`'s own. # Detection + CSS-generation is shared (`./stylix-theme.nix`). # # No package-copy derivation: this vhost has exactly one location - # serving `cfg.package` (unlike hive-c0re's `servedFrontend`, which + # serving `deployCfg.swarm-ui.package` (unlike hive-c0re's `servedFrontend`, which # backs both the dashboard root AND every per-agent gateway route, so # a single swapped tree covers both) — an `= /static/colors.css` # exact-match location overriding just that one file, same idiom @@ -79,22 +78,23 @@ in '') ]; - options.services.hyperhive.swarm.ui = { - package = lib.mkOption { - type = lib.types.package; - defaultText = lib.literalExpression "hyperhive.packages.\${system}.swarm-ui"; - description = '' - Static build of the swarm UI. nginx serves this store path - directly — there is no server-side component beyond the - controller's own API. + # ⚠️ `services.hyperhive.swarm.ui` no longer exists as a namespace. `enable` + # moved in an earlier slice and `package` in this one, and those were its + # only two options — so both paths survive purely as renames in ./deploy.nix. + options.services.hyperhive.deploy.swarm-ui.package = lib.mkOption { + type = lib.types.package; + defaultText = lib.literalExpression "hyperhive.packages.\${system}.swarm-ui"; + description = '' + Static build of the swarm UI. nginx serves this store path + directly — there is no server-side component beyond the + controller's own API. - Wired by default from this flake's own package set (see - `flake.nix`), the same way `swarm.controller.package` is. There - is deliberately **no overlay** in this project, so a - `pkgs.swarm-ui` default here would name an attribute that does - not exist on any real deployment. - ''; - }; + Wired by default from this flake's own package set (see + `flake.nix`), the same way `swarm.controller.package` is. There + is deliberately **no overlay** in this project, so a + `pkgs.swarm-ui` default here would name an attribute that does + not exist on any real deployment. + ''; }; config = lib.mkIf (config.services.hyperhive.enable && deployCfg.swarm-ui.enable) { @@ -178,7 +178,7 @@ in extraConfig = gatewayCfg.lib.securityHeaders; locations = { "/" = { - root = "${cfg.package}"; + root = "${deployCfg.swarm-ui.package}"; extraConfig = '' ${swarmAuthRequest} # SPA: any path the bundle routes client-side is served the @@ -189,7 +189,7 @@ in } // lib.optionalAttrs (stylixThemeColors != null) { # Stylix theming (see the `let` block above): overrides just - # this one file from `cfg.package`'s own static root, rather + # this one file from `deployCfg.swarm-ui.package`'s own static root, rather # than copying the whole tree to change one file inside it — # nginx resolves the more specific `=` exact match over the # `/` prefix root above, so this simply doesn't exist (falling diff --git a/nix/module-eval.nix b/nix/module-eval.nix index 5f098c53..80bd56d5 100644 --- a/nix/module-eval.nix +++ b/nix/module-eval.nix @@ -16,7 +16,7 @@ # # ⚠️ **This evaluates, it does not execute** — a command line, a request or # a certificate needs something that *runs* it. A case needing a rendered -# file must stub what it drags in (`swarm.ui.package = pkgs.emptyDirectory`). +# file must stub what it drags in (`deploy.swarm-ui.package = pkgs.emptyDirectory`). { pkgs, lib, @@ -154,6 +154,14 @@ let swarm.controller.queue.clientSecretFile = "/run/secrets/ctrl-queue.secret"; }; + # The swarm UI, whose namespace this slice empties: `swarm.ui` had exactly + # two options and both have moved, so BOTH old paths are set here and the + # whole namespace now lives or dies by its two rename entries. + uiOldPath = hive { + swarm.ui.enable = true; + swarm.ui.package = pkgs.emptyDirectory; + }; + # The two stores, which had NO old-path fixture at all until this slice — # their `enable` and `retentionPeriod` shims have been uncovered since they # landed, which is precisely the "a missing shim reads as a clean tree" @@ -490,6 +498,31 @@ let # host-side half depends on: no store here, so no bind mount and no unit. # Without it a hive that merely names a token would drag the store's # container config into its evaluation. + # Reads the vhost's rendered `root`, not the option: the UI is served + # straight out of a store path, so a shim that resolves but stops + # reaching the module would leave nginx pointing at the default build. + name = "a config written against the pre-rename swarm-ui paths still serves the operator's build"; + # + # ⚠️ `unsafeDiscardStringContext` on both sides, load-bearing rather than + # tidy: interpolating a derivation carries string *context*, and this + # suite renders its results into a `buildCommand` that may not reference + # store paths. Comparing the paths as plain text is the intent — the case + # asks "does nginx point HERE", not "depend on what it points at". + ok = + let + want = builtins.unsafeDiscardStringContext "${pkgs.emptyDirectory}"; + # `or ""` is NOT enough: nginx's `locations..root` is `nullOr`, so + # a vhost that HAS the attribute set to null skips the default and + # reaches the coercion. Filter nulls, then discard context. + roots = map builtins.unsafeDiscardStringContext ( + lib.filter (r: r != null) ( + map (v: v.locations."/".root or null) (builtins.attrValues uiOldPath.services.nginx.virtualHosts) + ) + ); + in + builtins.elem want roots; + } + { # Reads the package the CONTAINER renders, not the option: a shim that # resolves but stops reaching the module would leave the store running # nixpkgs' default while the operator's override read back fine.