flake: replace naersk with crane (#538)

Framework swap, no public API change.

- naersk input → crane (`github:ipetkov/crane`); crane is stateless, no
  nixpkgs.follows needed.
- `forAllSystems` exposes `craneLib = crane.mkLib pkgs`,
  `cargoArtifacts = craneLib.buildDepsOnly` (built once, reused), and
  a shared `nativeBuildInputs = [ pkgs.librsvg pkgs.git ]` consumed by
  buildDepsOnly + buildPackage + cargoClippy so the three derivations
  see the same toolchain shape.
- `packages.default = craneLib.buildPackage` (was naersk-lib.buildPackage)
  with explicit `pname = "hyperhive-workspace"; version = "0.1.0";` —
  the virtual workspace Cargo.toml has no [package].name so crane
  needs the hint.
- `checks.clippy = craneLib.cargoClippy` (was naersk + overrideAttrs
  hack). Crane parses `cargoClippyExtraArgs = "--workspace --all-targets
  -- -D warnings"` correctly; naersk's `mode = "clippy"` used to mangle
  the `--` separator which is why the old wiring went through
  overrideAttrs. The whole hack — including `doCheck = false`,
  `copyTarget = false`, and the swapped buildPhase/installPhase — is
  now gone.
- librsvg native dep (#424) preserved on all three derivations. Added
  pkgs.git too — naersk auto-included it; crane is more minimal, so
  hive-c0re's `lifecycle::tests::setup_proposed_*` (which shell out to
  `git init`+commit) need it explicit to pass under `cargo test` in
  the sandbox.
- build.rs + hive-c0re/Cargo.toml comments updated from "naersk
  derivation" to "crane derivation".
- 3 doc-list-indentation lints in hive-sh4re/src/lib.rs cleaned up
  (replaced `+`-at-line-start with `and`/`/` so doc continuations
  don't trigger `clippy::doc_lazy_continuation`).

Validated locally: `nix build .#default --fallback` succeeds, all
117 tests pass, all four bins in `result/bin/`.
This commit is contained in:
iris 2026-05-28 20:33:30 +02:00 committed by Mara
commit 4b6c733afb
5 changed files with 88 additions and 111 deletions

63
flake.lock generated
View file

@ -1,45 +1,17 @@
{
"nodes": {
"fenix": {
"inputs": {
"nixpkgs": [
"naersk",
"nixpkgs"
],
"rust-analyzer-src": "rust-analyzer-src"
},
"crane": {
"locked": {
"lastModified": 1752475459,
"narHash": "sha256-z6QEu4ZFuHiqdOPbYss4/Q8B0BFhacR8ts6jO/F/aOU=",
"owner": "nix-community",
"repo": "fenix",
"rev": "bf0d6f70f4c9a9cf8845f992105652173f4b617f",
"lastModified": 1779130139,
"narHash": "sha256-BLrtr42azquO7MdGFU5a7KiMl3YpFlTeIXqy1fT5GlQ=",
"owner": "ipetkov",
"repo": "crane",
"rev": "edb38893982a3338972bb4a2ec7ce7c29ba10fd9",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "fenix",
"type": "github"
}
},
"naersk": {
"inputs": {
"fenix": "fenix",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1778151388,
"narHash": "sha256-lldMJPUeouEjO8/7aLuwhcsIw29vVihm2ZALzjiqfec=",
"owner": "nix-community",
"repo": "naersk",
"rev": "efdddff9ff4d8e7d0056d57ec67dac50f75ab8f6",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "naersk",
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
@ -77,29 +49,12 @@
},
"root": {
"inputs": {
"naersk": "naersk",
"crane": "crane",
"nixpkgs": "nixpkgs",
"nixpkgs-unstable": "nixpkgs-unstable",
"treefmt-nix": "treefmt-nix"
}
},
"rust-analyzer-src": {
"flake": false,
"locked": {
"lastModified": 1752428706,
"narHash": "sha256-EJcdxw3aXfP8Ex1Nm3s0awyH9egQvB2Gu+QEnJn2Sfg=",
"owner": "rust-lang",
"repo": "rust-analyzer",
"rev": "591e3b7624be97e4443ea7b5542c191311aa141d",
"type": "github"
},
"original": {
"owner": "rust-lang",
"ref": "nightly",
"repo": "rust-analyzer",
"type": "github"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": [

116
flake.nix
View file

@ -4,10 +4,10 @@
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
naersk = {
url = "github:nix-community/naersk";
inputs.nixpkgs.follows = "nixpkgs";
};
# Crane (replaces naersk #538). Stateless — no nixpkgs input to
# follow; `crane.mkLib pkgs` returns the lib at whatever pkgs we
# pass it (we use the project's pinned nixpkgs).
crane.url = "github:ipetkov/crane";
treefmt-nix = {
url = "github:numtide/treefmt-nix";
inputs.nixpkgs.follows = "nixpkgs";
@ -19,7 +19,7 @@
self,
nixpkgs,
nixpkgs-unstable,
naersk,
crane,
treefmt-nix,
}:
let
@ -45,22 +45,59 @@
inherit system;
pkgs = nixpkgs.legacyPackages.${system};
treefmt-eval = treefmt-nix.lib.evalModule pkgs treefmt-config;
naersk-lib = pkgs.callPackage naersk { };
craneLib = crane.mkLib pkgs;
# Build the workspace's dependency tree once, cached as
# its own derivation. `buildPackage` and `cargoClippy`
# both reuse this via `inherit cargoArtifacts;` so a
# workspace-only edit doesn't rebuild deps. Same
# `nativeBuildInputs` as the workspace build itself —
# build.rs runs during dep-build too (any deps with a
# build.rs need rsvg too if they transitively pull it
# in; harmless if they don't).
cargoArtifacts = craneLib.buildDepsOnly {
src = ./.;
# Workspace Cargo.toml is virtual (no `[package].name`),
# so crane can't auto-derive a name. Spell it out
# explicitly here and below — keeps the derivation name
# stable across crane bumps + silences the placeholder
# warning. Same `pname` everywhere so dep + workspace +
# clippy share a clean naming family.
pname = "hyperhive-workspace";
version = "0.1.0";
inherit nativeBuildInputs;
};
# Shared between buildDepsOnly + buildPackage + cargoClippy
# so the three derivations see the same toolchain shape.
# librsvg: hive-c0re/build.rs invokes `rsvg-convert` to
# render branding/agent-configs.svg → PNG that the daemon
# `include_bytes!`s (#424); SVG stays source-of-truth.
# git: naersk used to auto-include it; crane is more
# minimal, so we add it explicitly so hive-c0re's
# `lifecycle::tests::setup_proposed_*` (which shell out to
# `git init` + commit) pass under `cargo test` in the
# sandbox.
nativeBuildInputs = [
pkgs.librsvg
pkgs.git
];
}
);
in
{
packages = forAllSystems (
{ pkgs, naersk-lib, ... }:
{
default = naersk-lib.buildPackage {
pkgs,
craneLib,
cargoArtifacts,
nativeBuildInputs,
...
}:
{
default = craneLib.buildPackage {
src = ./.;
# librsvg ships `rsvg-convert`, which hive-c0re/build.rs
# invokes to render branding/agent-configs.svg into the
# PNG it embeds via `include_bytes!` (#424). Keeps the
# raster out of git — SVG stays source-of-truth, PNG is
# a build artifact in $OUT_DIR.
nativeBuildInputs = [ pkgs.librsvg ];
inherit cargoArtifacts nativeBuildInputs;
pname = "hyperhive-workspace";
version = "0.1.0";
meta.description = "hyperhive workspace (hive-c0re, hive-ag3nt, hive-m1nd)";
};
# Bundled browser assets — see ./nix/frontend.nix. Output is
@ -201,43 +238,28 @@
checks = forAllSystems (
{
treefmt-eval,
pkgs,
naersk-lib,
craneLib,
cargoArtifacts,
nativeBuildInputs,
...
}:
{
formatting = treefmt-eval.config.build.check self;
# Clippy as a check: reuse naersk's vendored-deps environment but
# replace the build phase with `cargo clippy --workspace --all-targets
# -- -D warnings`. Naersk's own `mode = "clippy"` mangles the `--`
# separator, so we go through overrideAttrs instead.
clippy =
(naersk-lib.buildPackage {
src = ./.;
# Skip the actual build; we only care about the clippy lint.
doCheck = false;
copyTarget = false;
# hive-c0re/build.rs needs rsvg-convert on PATH (#424);
# mirror the runtime derivation's nativeBuildInputs so
# clippy's vendored-deps build phase doesn't break on
# the missing tool.
nativeBuildInputs = [ pkgs.librsvg ];
}).overrideAttrs
(old: {
name = "${old.name}-clippy";
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ pkgs.clippy ];
buildPhase = ''
runHook preBuild
cargo clippy --workspace --all-targets -- -D warnings
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out
touch $out/.clippy-passed
runHook postInstall
'';
});
# Clippy as a check via crane's first-class `cargoClippy`
# builder. Reuses the shared `cargoArtifacts` (deps already
# built) and runs `cargo clippy --workspace --all-targets
# -- -D warnings` directly — no `overrideAttrs` hack needed,
# because crane parses `cargoClippyExtraArgs` correctly
# (naersk's `mode = "clippy"` used to mangle the `--`
# separator, which is why the old wiring went through
# overrideAttrs).
clippy = craneLib.cargoClippy {
src = ./.;
inherit cargoArtifacts nativeBuildInputs;
pname = "hyperhive-workspace";
version = "0.1.0";
cargoClippyExtraArgs = "--workspace --all-targets -- -D warnings";
};
}
);
};

View file

@ -4,7 +4,7 @@ edition.workspace = true
version.workspace = true
# Render branding/agent-configs.svg → $OUT_DIR/agent-configs.png at
# compile time (#424). build.rs shells out to `rsvg-convert`
# (librsvg, pulled in via flake.nix' naersk nativeBuildInputs); the
# (librsvg, pulled in via flake.nix' crane nativeBuildInputs); the
# baked PNG is included via include_bytes! from forge.rs so no
# raster gets checked into git.
build = "build.rs"

View file

@ -5,7 +5,7 @@
//! artifact.
//!
//! Uses `rsvg-convert` from PATH (librsvg, already available in
//! nixpkgs and added to the naersk derivation's `nativeBuildInputs`
//! nixpkgs and added to the crane derivation's `nativeBuildInputs`
//! in `flake.nix`). For dev builds outside Nix, install librsvg via
//! your system package manager (Debian/Ubuntu: `librsvg2-bin`,
//! macOS: `brew install librsvg`).
@ -43,7 +43,7 @@ fn main() {
"failed to invoke rsvg-convert: {e}\n\
install librsvg (Debian/Ubuntu: librsvg2-bin, macOS: brew install librsvg, \
NixOS: pkgs.librsvg). The Nix derivation already pulls it in via \
flake.nix naersk-lib.buildPackage.nativeBuildInputs.",
flake.nix craneLib.buildPackage.nativeBuildInputs.",
),
}
}

View file

@ -23,8 +23,8 @@ pub enum HostRequest {
/// `hive-c0re request-spawn` CLI both go through this. The
/// previously-mirrored manager-side `RequestSpawn` was removed
/// (#442) — managers now go through the two-step `request_init_config`
/// + `request_apply_commit` flow so the spawn captures the manager's
/// customised config.
/// and `request_apply_commit` flow so the spawn captures the
/// manager's customised config.
RequestSpawn { name: String },
/// Stop a managed container (graceful).
Kill { name: String },
@ -957,8 +957,8 @@ pub enum ManagerRequest {
/// per-target fan-out once immediately without touching
/// `next_fire_at_unix` on recurring schedules; one-shots are
/// consumed by the manual fire. Authorization mirrors
/// `CancelSchedule`: the manager can fire its own schedules
/// + any owned by a sub-agent in its subtree per topology.json;
/// `CancelSchedule`: the manager can fire its own schedules and
/// any owned by a sub-agent in its subtree per topology.json;
/// the operator surface bypasses the check.
FireScheduleNow { id: i64 },
/// Edit an existing schedule's mutable fields (#474). Partial
@ -1013,9 +1013,9 @@ pub struct SchedulePromptPayload {
}
/// Schedule row shape on the wire — mirror of
/// `scheduled_prompts::Schedule` but in the public crate so dashboard
/// + agent surfaces can deserialize without depending on
/// hive-c0re-internal types. Kept structurally identical to the
/// `scheduled_prompts::Schedule` but in the public crate so the
/// dashboard and agent surfaces can deserialize without depending
/// on hive-c0re-internal types. Kept structurally identical to the
/// in-process type; the conversion is field-by-field in
/// `manager_server` / `dashboard`.
#[derive(Debug, Clone, Serialize, Deserialize)]