Watch
0
0
Fork
You've already forked hyperhive
0

seed a hyperhive/hyperhive mirror so update_meta finds it on a fresh swarm

This commit is contained in:
atlas 2026-11-09 12:19:46 +01:00
commit a6b5bafa83
4 changed files with 173 additions and 15 deletions

View file

@ -1,8 +1,9 @@
# 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`.
# this leaves the controller seeding no pull-mirrors, the forge resolving
# workflow actions from `data.forgejo.org` and a fresh swarm without the hyperhive
# repo its meta flake pins.
#
# ⚠️ Gated on BOTH services being here: the mirrors reach a controller on this
# host only, and the forge's own `config` block hangs off
@ -21,6 +22,12 @@ in
# resolve actions from itself. `mkDefault`: an operator's explicit value wins.
services.hyperhive.deploy.forgejo.actionsFromSelf = lib.mkDefault true;
# The meta flake pins the hyperhive repo on this forge, and a fresh forge has
# none. The controller creates the mirror only if `hyperhive/hyperhive` is
# absent, so a swarm that hosts the real repo is not touched.
services.hyperhive.deploy.forgejo.hyperhiveUpstream =
lib.mkDefault "https://forge.darkest.space/hyperhive/hyperhive";
# 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 =

View file

@ -143,11 +143,17 @@ let
"checkout"
"upload-artifact"
];
# The swarm-controller reads the hyperhive repo from this forge (the pin of
# the meta flake), so a swarm that has no copy mirrors it.
hyperhiveMirrors = lib.optional (deployCfg.forgejo.hyperhiveUpstream != null) {
upstream = deployCfg.forgejo.hyperhiveUpstream;
dest = "hyperhive/hyperhive";
};
# Minus any dest the operator already declared, which would duplicate it.
effectiveMirrors =
deployCfg.forgejo.mirrors
++ lib.optionals actionsFromSelf (
lib.filter (a: !(lib.any (m: m.dest == a.dest) deployCfg.forgejo.mirrors)) actionMirrors
++ lib.filter (a: !(lib.any (m: m.dest == a.dest) deployCfg.forgejo.mirrors)) (
lib.optionals actionsFromSelf actionMirrors ++ hyperhiveMirrors
);
# Share host netns — forgejo's HTTP / SSH listeners then look
@ -266,7 +272,8 @@ in
With {option}`services.hyperhive.deploy.forgejo.actionsFromSelf`
enabled (the default on a host that runs the swarm-controller),
`actions/checkout` and `actions/upload-artifact` mirrors are appended
to this list.
to this list, and so is `hyperhive/hyperhive` with
{option}`services.hyperhive.deploy.forgejo.hyperhiveUpstream`.
'';
};
@ -293,13 +300,33 @@ in
'';
};
hyperhiveUpstream = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "https://forge.darkest.space/hyperhive/hyperhive";
description = ''
Clone URL of the hyperhive repo to pull-mirror to `hyperhive/hyperhive`
on this forge, or `null` for no mirror. The swarm-controller pins the
meta flake's `hyperhive` input to a commit of that repo and every
build fetches it from there, so without it the first agent's
`update_meta` step fails and no agent container is built.
Defaults to `https://forge.darkest.space/hyperhive/hyperhive` when this
host also runs the swarm-controller, which seeds the mirror (set by
`glue-forge-controller.nix`), and to `null` otherwise. The controller
creates the mirror only when `hyperhive/hyperhive` does not exist: a
swarm that already holds the repo as a normal repo keeps it unchanged. A `hyperhive/hyperhive` entry in
{option}`services.hyperhive.deploy.forgejo.mirrors` takes precedence.
'';
};
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.
adds and the `hyperhive/hyperhive` mirror {option}`hyperhiveUpstream` adds; what `glue-forge-controller.nix` forwards to the controller.
'';
};
};
@ -1375,8 +1402,8 @@ in
# it to be noticed as a missing repo.
services.hyperhive.deploy.forgejo.effectiveMirrors = effectiveMirrors;
warnings = lib.optional (effectiveMirrors != [ ] && !deployCfg.swarm-controller.enable) ''
services.hyperhive.deploy.forgejo.mirrors (or the actions/* mirrors
deploy.forgejo.actionsFromSelf adds) is set on a host that does not run the
services.hyperhive.deploy.forgejo.mirrors (or the actions/* and hyperhive mirrors
deploy.forgejo.actionsFromSelf and hyperhiveUpstream add) is set on a host that does not run the
swarm-controller. The controller seeds mirrors from its own host's list,
so these are not seeded: declare them on the swarm-controller's host.
'';

View file

@ -118,11 +118,13 @@ let
upstream = "https://example.invalid/tool";
dest = "mirrors/tool";
};
hyperhiveElsewhere = "https://example.invalid/hyperhive";
controllerWithMirrors = hiveWithController {
deploy.swarm-controller.enable = true;
deploy.forgejo.enable = true;
deploy.forgejo.mirrors = [ aMirror ];
deploy.forgejo.actionsFromSelf = false;
deploy.forgejo.hyperhiveUpstream = null;
deploy.swarm-controller.configOrgAvatarPng = "/etc/marker-avatar.png";
};
mirrorsNoController = hive {
@ -139,6 +141,7 @@ let
deploy.forgejo.enable = true;
deploy.forgejo.mirrors = [ aMirror ];
deploy.forgejo.actionsFromSelf = true;
deploy.forgejo.hyperhiveUpstream = hyperhiveElsewhere;
};
# The controller with every shared service on another host, and the same
@ -1371,6 +1374,7 @@ let
"mirrors/tool"
"actions/checkout"
"actions/upload-artifact"
"hyperhive/hyperhive"
]
&& actionsUrlOf controllerWithSelfActions == "self"
&& mirrorsOf controllerWithMirrors == [ aMirror ]
@ -1401,6 +1405,28 @@ let
&& actionsUrlOf forgeWithController == "self"
&& lib.elem "actions/checkout" (map (m: m.dest) (mirrorsOf forgeWithController));
}
{
# The meta flake pins the hyperhive repo on the swarm forge, and a fresh
# forge has none, so the controller seeds a mirror of it: by default,
# with another upstream when the option says so, and not at all when it
# is null (controllerWithMirrors) or without the controller (forgeOnly).
name = "a forge beside the controller mirrors hyperhive/hyperhive unless told not to";
ok =
let
mirrorsOf =
m: builtins.fromJSON m.systemd.services.swarm-controller.environment.SWARM_CONTROLLER_FORGE_MIRRORS;
hyperhiveOf = m: lib.filter (e: e.dest == "hyperhive/hyperhive") (mirrorsOf m);
in
hyperhiveOf forgeWithController == [
{
upstream = "https://forge.darkest.space/hyperhive/hyperhive";
dest = "hyperhive/hyperhive";
}
]
&& map (e: e.upstream) (hyperhiveOf controllerWithSelfActions) == [ hyperhiveElsewhere ]
&& hyperhiveOf controllerWithMirrors == [ ]
&& forgeOnly.services.hyperhive.deploy.forgejo.hyperhiveUpstream == null;
}
{
name = "the org avatar lands on the controller's unit, not hive-c0re's";
ok =

View file

@ -115,6 +115,9 @@ pkgs.testers.runNixOSTest (
deploy.hive-controller.enable = true;
deploy.hive-controller.hiveName = hive;
deploy.bao.seal = "shamir";
# The test pushes its own hyperhive/hyperhive; a mirror of the
# upstream could not be created offline and would race the push.
deploy.forgejo.hyperhiveUpstream = null;
swarm.domain = swarmDomain;
swarm.hives.${hive} = { };
};