Watch
0
0
Fork
You've already forked hyperhive
0

glue: forge's controller-dependent settings move out of the forge module

This commit is contained in:
atlas 2026-10-13 08:47:07 +02:00 • committed by mara
commit 4a3f21fc2b
6 changed files with 59 additions and 18 deletions

View file

@ -219,7 +219,7 @@ Set `actionsFromSelf = false` there to resolve actions from `data.forgejo.org`
and seed no mirror. and seed no mirror.
The option defaults to whether the forge's host also runs the swarm controller The option defaults to whether the forge's host also runs the swarm controller
(`services.hyperhive.deploy.swarm-controller.enable`): on when it does, off (`services.hyperhive.deploy.swarm-controller.enable`; set by `glue-forge-controller.nix`): on when it does, off
otherwise. Setting it `true` on a forge host without the controller leaves otherwise. Setting it `true` on a forge host without the controller leaves
the actions unresolved, because nothing seeds the mirrors; evaluation the actions unresolved, because nothing seeds the mirrors; evaluation
warns about it. warns about it.
@ -228,7 +228,7 @@ warns about it.
The **swarm controller** seeds the mirror in its swarm-wide forge-objects The **swarm controller** seeds the mirror in its swarm-wide forge-objects
pass (`swarm-controller/src/forge/objects.rs`), beside the orgs it ensures. pass (`swarm-controller/src/forge/objects.rs`), beside the orgs it ensures.
The nix module forwards the effective mirror list as `glue-forge-controller.nix` forwards the effective mirror list as
`SWARM_CONTROLLER_FORGE_MIRRORS` in the `swarm-controller` service `SWARM_CONTROLLER_FORGE_MIRRORS` in the `swarm-controller` service
environment (JSON-encoded `[{upstream, dest}]` list). It reads the list of environment (JSON-encoded `[{upstream, dest}]` list). It reads the list of
the host the controller runs on: mirrors declared on any other host aren't the host the controller runs on: mirrors declared on any other host aren't

View file

@ -31,6 +31,7 @@
./glue-bao-ui-oidc-client.nix ./glue-bao-ui-oidc-client.nix
./glue-controller-bao-identity.nix ./glue-controller-bao-identity.nix
./glue-controller-oidc-client.nix ./glue-controller-oidc-client.nix
./glue-forge-controller.nix
./glue-forge-oidc-client.nix ./glue-forge-oidc-client.nix
./glue-grafana-oidc-client.nix ./glue-grafana-oidc-client.nix
./glue-hive-otel-authelia.nix ./glue-hive-otel-authelia.nix

View file

@ -0,0 +1,29 @@
# Glue: wire the forge and the swarm-controller together when one host runs both.
#
# ONE PAIRING PER FILE — forge ← swarm-controller, and nothing else. Deleting
# this leaves the controller seeding no pull-mirrors and the forge resolving
# workflow actions from `data.forgejo.org`.
#
# ⚠️ Gated on BOTH services being here: the mirrors reach a controller on this
# host only, and the forge's own `config` block hangs off
# `deploy.forgejo.enable`. The forge's `mirrors` warning covers the split case.
{
lib,
config,
...
}:
let
deployCfg = config.services.hyperhive.deploy;
in
{
config = lib.mkIf (deployCfg.forgejo.enable && deployCfg.swarm-controller.enable) {
# The controller seeds the `actions/*` mirrors, so a forge beside one can
# resolve actions from itself. `mkDefault`: an operator's explicit value wins.
services.hyperhive.deploy.forgejo.actionsFromSelf = lib.mkDefault true;
# JSON-encoded list of { upstream, dest }, seeded by the controller's
# forge-objects pass (`swarm-controller/src/forge/objects.rs`).
systemd.services.swarm-controller.environment.SWARM_CONTROLLER_FORGE_MIRRORS =
builtins.toJSON deployCfg.forgejo.effectiveMirrors;
};
}

View file

@ -219,8 +219,7 @@ in
actionsFromSelf = lib.mkOption { actionsFromSelf = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = deployCfg.swarm-controller.enable; default = false;
defaultText = lib.literalExpression "config.services.hyperhive.deploy.swarm-controller.enable";
example = false; example = false;
description = '' description = ''
Resolve a workflow's `uses: <org>/<action>@vN` against this forge Resolve a workflow's `uses: <org>/<action>@vN` against this forge
@ -230,8 +229,9 @@ in
have something to resolve to. A CI job's actions then need no have something to resolve to. A CI job's actions then need no
external DNS; only the mirrors' re-sync does. external DNS; only the mirrors' re-sync does.
Defaults to on when this host runs the swarm-controller, which seeds Defaults to on when this host also runs the swarm-controller, which
the mirrors, and off otherwise. Setting it `true` on a host without seeds the mirrors (set by `glue-forge-controller.nix`), and off
otherwise. Setting it `true` on a host without
the controller leaves both actions unresolved: nothing seeds the the controller leaves both actions unresolved: nothing seeds the
mirrors, and the warning about unseeded mirrors fires. mirrors, and the warning about unseeded mirrors fires.
@ -240,6 +240,16 @@ in
''; '';
}; };
effectiveMirrors = lib.mkOption {
type = lib.types.listOf lib.types.attrs;
internal = true;
readOnly = true;
description = ''
{option}`mirrors` plus the `actions/*` mirrors {option}`actionsFromSelf`
adds; what `glue-forge-controller.nix` forwards to the controller.
'';
};
# The other half of the SSO pair: the client *id* is swarm-wide (it has # The other half of the SSO pair: the client *id* is swarm-wide (it has
# to match authelia's register), the secret is a path on this host. The # to match authelia's register), the secret is a path on this host. The
# design note for the login source itself is with the id. # design note for the login source itself is with the id.
@ -1238,17 +1248,11 @@ in
]; ];
}; };
# Forward the declared pull-mirrors to the swarm-controller, which seeds # The mirrors reach a controller on THIS host only (see
# them in its swarm-wide forge-objects pass # ../glue-forge-controller.nix); a controller elsewhere reads its own
# (`swarm-controller/src/forge/objects.rs`), beside the orgs they live in. # host's list, so the warning below says so at eval rather than leaving
# JSON-encoded list of { upstream, dest }; `[]` when nothing to seed. # it to be noticed as a missing repo.
# services.hyperhive.deploy.forgejo.effectiveMirrors = effectiveMirrors;
# ⚠️ This host's `mirrors` reach a controller on THIS host only. A
# controller elsewhere reads its own host's list, so mirrors declared
# here would never be seeded; the warning below says so at eval rather
# than leaving it to be noticed as a missing repo.
systemd.services.swarm-controller.environment.SWARM_CONTROLLER_FORGE_MIRRORS =
lib.mkIf deployCfg.swarm-controller.enable (builtins.toJSON effectiveMirrors);
warnings = lib.optional (effectiveMirrors != [ ] && !deployCfg.swarm-controller.enable) '' warnings = lib.optional (effectiveMirrors != [ ] && !deployCfg.swarm-controller.enable) ''
services.hyperhive.deploy.forgejo.mirrors (or the actions/* mirrors services.hyperhive.deploy.forgejo.mirrors (or the actions/* mirrors
deploy.forgejo.actionsFromSelf adds) is set on a host that does not run the deploy.forgejo.actionsFromSelf adds) is set on a host that does not run the

View file

@ -564,6 +564,13 @@ let
!forgeOnly.services.hyperhive.deploy.forgejo.actionsFromSelf !forgeOnly.services.hyperhive.deploy.forgejo.actionsFromSelf
&& actionsUrlOf forgeOnly == null && actionsUrlOf forgeOnly == null
&& forgeOnly.warnings == [ ] && forgeOnly.warnings == [ ]
&& !(
(forgeOnly.systemd.services.swarm-controller.environment or { }) ? SWARM_CONTROLLER_FORGE_MIRRORS
)
&& !(
(mirrorsNoController.systemd.services.swarm-controller.environment or { })
? SWARM_CONTROLLER_FORGE_MIRRORS
)
&& forgeWithController.services.hyperhive.deploy.forgejo.actionsFromSelf && forgeWithController.services.hyperhive.deploy.forgejo.actionsFromSelf
&& actionsUrlOf forgeWithController == "self" && actionsUrlOf forgeWithController == "self"
&& lib.elem "actions/checkout" (map (m: m.dest) (mirrorsOf forgeWithController)); && lib.elem "actions/checkout" (map (m: m.dest) (mirrorsOf forgeWithController));

View file

@ -117,7 +117,7 @@ Do **not** push directly to `main` — agents have read-only access.
"; ";
/// The operator-declared pull-mirrors (nix `deploy.forgejo.mirrors`, plus the /// The operator-declared pull-mirrors (nix `deploy.forgejo.mirrors`, plus the
/// `actions/*` entries `deploy.forgejo.actionsFromSelf` adds), JSON-encoded by `hive-forge/default.nix`. /// `actions/*` entries `deploy.forgejo.actionsFromSelf` adds), JSON-encoded by `glue-forge-controller.nix`.
/// Absent or empty means no mirrors. /// Absent or empty means no mirrors.
const MIRRORS_ENV: &str = "SWARM_CONTROLLER_FORGE_MIRRORS"; const MIRRORS_ENV: &str = "SWARM_CONTROLLER_FORGE_MIRRORS";