Watch
0
0
Fork
You've already forked hyperhive
0

nightly vm test: the builder's meta build finds a prebuilt agent in an offline store

This commit is contained in:
atlas 2026-11-01 20:21:35 +01:00
commit 4d85ec4c21
3 changed files with 508 additions and 2 deletions

View file

@ -8,3 +8,7 @@ Pure string rendering, with no IO and no environment reads. The caller passes
the hyperhive pin, the agents with their pins, and the values every agent
container gets. swarm-controller calls `render_flake`; hive-c0re reads the
pins of the flake it renders (`pinned_rev`, `builds_agent_at`).
`testdata/meta-flake.nix.in` is the render for one archetype agent with a
placeholder for the hyperhive pin. A unit test keeps it equal to `render_flake`'s
output, and the `swarm-builder-offline` VM test (`nix/vm-tests/`) serves it.

View file

@ -543,6 +543,29 @@ mod tests {
.unwrap()
}
/// `testdata/meta-flake.nix.in` is the flake `nix/vm-tests/swarm-builder-offline.nix`
/// evaluates and serves, with `@HYPERHIVE_URL@` where the pin goes. It must be
/// what [`render_flake`] renders for one archetype agent.
#[test]
fn the_vm_test_fixture_is_what_render_flake_renders() {
let archetype = ArchetypeRef {
source: "hyperhive".to_owned(),
name: "reviewer".to_owned(),
};
let flake = render_flake(
"@HYPERHIVE_URL@",
&[spec("rev1", Some(archetype), None)],
&[],
false,
)
.unwrap();
assert_eq!(
flake,
include_str!("../testdata/meta-flake.nix.in"),
"update the fixture to the rendered flake"
);
}
#[test]
fn a_rendered_flake_names_the_commit_each_input_is_pinned_to() {
let flake = rendered();

View file

@ -0,0 +1,85 @@
{
description = "hyperhive deployed agents";
inputs = {
hyperhive.url = "@HYPERHIVE_URL@";
nixpkgs.follows = "hyperhive/nixpkgs";
};
outputs =
{ self, hyperhive, ... }@inputs:
let
mkAgent = { name, port, archetype ? null }:
let
base = hyperhive.nixosConfigurations.agent-base;
# Every flake an archetype can come from, by its source name.
archetypeSources = { inherit hyperhive; };
agentModule =
if archetype == null then
inputs."agent-${name}".nixosModules.default
else
(archetypeSources.${archetype.source}
or (throw "agent ${name}: archetype source ${archetype.source} is not an input of this hive's meta flake")
).hyperhiveArchetypes.${archetype.name}.module
or (throw "agent ${name}: this hive's ${archetype.source} input has no archetype ${archetype.name}; update that input");
service = "hive-agent";
in
base.extendModules {
modules = [
agentModule
{
# The harness service inside the container runs as a
# non-root unix user named after the agent (`damocles`,
# `iris`, `root`, …). UID auto-assigned by NixOS; the
# per-agent override here is what makes
# `services.hyperhive.agent.user.name` match the agent's identity
# instead of the harness default of `"agent"`.
services.hyperhive.agent.user.name = name;
# Without this an agent container is called `nixos` and ships
# every log line under that: nixpkgs sets the hostname from the
# attr name in the `containers.<name>` submodule, and an
# agent's system is its own `nixosSystem` off this flake, which
# never evaluates that option. The machine name, not the
# logical one — it is what `container.name` on our metrics and
# nspawn itself already call this container, so logs join to
# both without a prefix transform.
networking.hostName = "h-${name}";
programs.git.config.user = {
name = name;
email = "${name}@hyperhive.local";
};
# Container-wide env: every service + co-process daemon can
# resolve the agent's durable state dir without hard-coding it.
# `environment.variables` only writes /etc/environment (login
# shells); `systemd.globalEnvironment` is the analogue for
# systemd units so forge-avatar-sync /
# hive-matrix-daemon etc. can read `$HYPERHIVE_STATE_DIR`
# without each service having to redeclare it.
environment.variables = {
HIVE_LABEL = name;
HYPERHIVE_STATE_DIR = "/agents/${name}/state";
HYPERHIVE_HARNESS_DIR = "/agents/${name}/harness";
};
systemd.globalEnvironment = {
HIVE_LABEL = name;
HYPERHIVE_STATE_DIR = "/agents/${name}/state";
HYPERHIVE_HARNESS_DIR = "/agents/${name}/harness";
};
systemd.services.${service}.environment = {
HIVE_PORT = toString port;
HIVE_LABEL = name;
HYPERHIVE_STATE_DIR = "/agents/${name}/state";
HYPERHIVE_HARNESS_DIR = "/agents/${name}/harness";
};
}
# Tells the harness the agent has no config repo of its own.
(if archetype == null then { } else {
systemd.services.${service}.environment.HIVE_ARCHETYPE = archetype.name;
})
];
};
in
{
nixosConfigurations = {
rev1 = mkAgent { name = "rev1"; port = 8297; archetype = { source = "hyperhive"; name = "reviewer"; }; };
};
};
}