perf(3168): the deploy path stops compiling test binaries
crane's `buildDepsOnly` defaults `doCheck = true`, which adds
`--all-targets` and a `cargo test --no-run` — so the dep cache compiles
every dev-dependency and test harness in the tree. The checks need
exactly that. `workspaceBuild` never runs a test and never links one, and
was sitting on the same cache.
Split into two, one per audience. Not a duplication of something shared:
CI evaluates against hyperhive's own nixpkgs pin while a host overrides
it — security patches cannot wait on a lock bump upstream — so the two
closures already differ and neither substitutes for the other. Giving
each its own cache therefore costs nobody a second build; it stops the
deploy compiling artifacts only CI consumes.
Both still build from crane's dummy source, so both hashes key on
Cargo.toml/Cargo.lock: a code edit rebuilds neither, a dependency or
toolchain bump rebuilds both. That bump is the recurring cost this
targets — on a host overriding nixpkgs for security patches, it is every
patch.
⚠️ The first build after this lands is cold: the derivation hashes move.
This commit is contained in:
parent
3de7a4a1b1
commit
d7b12e8c48
2 changed files with 47 additions and 4 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
# All flake package outputs. Imported per system from flake.nix; the
|
# All flake package outputs. Imported per system from flake.nix; the
|
||||||
# shared rust build wiring (cleanSrc / cargoArtifacts /
|
# shared rust build wiring (cleanSrc / cargoArtifactsBinOnly /
|
||||||
# nativeBuildInputs) comes in via `rust` (see ../rust.nix).
|
# nativeBuildInputs) comes in via `rust` (see ../rust.nix).
|
||||||
{
|
{
|
||||||
pkgs,
|
pkgs,
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
inherit (pkgs) lib;
|
inherit (pkgs) lib;
|
||||||
inherit (rust) cleanSrc cargoArtifacts nativeBuildInputs;
|
inherit (rust) cleanSrc cargoArtifactsBinOnly nativeBuildInputs;
|
||||||
|
|
||||||
docsAttrs = import ../docs {
|
docsAttrs = import ../docs {
|
||||||
inherit pkgs self;
|
inherit pkgs self;
|
||||||
|
|
@ -43,7 +43,7 @@ let
|
||||||
};
|
};
|
||||||
|
|
||||||
# ONE compile of the whole workspace (every bin, sharing the
|
# ONE compile of the whole workspace (every bin, sharing the
|
||||||
# prebuilt `cargoArtifacts` dep cache). The per-bin packages below
|
# prebuilt `cargoArtifactsBinOnly` dep cache). The per-bin packages below
|
||||||
# are cheap copy-extractors over this, so workspace lib crates
|
# are cheap copy-extractors over this, so workspace lib crates
|
||||||
# (hive-sh4re, hive-claude, …) compile exactly once instead of once
|
# (hive-sh4re, hive-claude, …) compile exactly once instead of once
|
||||||
# per bin derivation.
|
# per bin derivation.
|
||||||
|
|
@ -52,9 +52,16 @@ let
|
||||||
# (carries the hyperhive-assets build input for the prompt-template
|
# (carries the hyperhive-assets build input for the prompt-template
|
||||||
# assertions in hive-agent::prompt::tests). Keeping them out of this
|
# assertions in hive-agent::prompt::tests). Keeping them out of this
|
||||||
# derivation means a prompt edit doesn't bust the cargo cache.
|
# derivation means a prompt edit doesn't bust the cargo cache.
|
||||||
|
#
|
||||||
|
# …and the dep cache underneath is the one WITHOUT test targets. This
|
||||||
|
# derivation has never run a test — `doCheck = false` below says so —
|
||||||
|
# but it used to sit on a cache that compiled every dev-dependency and
|
||||||
|
# test harness anyway, work whose only consumers are the checks. A
|
||||||
|
# deploy paid for it on every toolchain or dependency change.
|
||||||
workspaceBuild = craneLib.buildPackage {
|
workspaceBuild = craneLib.buildPackage {
|
||||||
src = cleanSrc;
|
src = cleanSrc;
|
||||||
inherit cargoArtifacts nativeBuildInputs;
|
cargoArtifacts = cargoArtifactsBinOnly;
|
||||||
|
inherit nativeBuildInputs;
|
||||||
pname = "hyperhive-workspace";
|
pname = "hyperhive-workspace";
|
||||||
version = "0.1.0";
|
version = "0.1.0";
|
||||||
doCheck = false;
|
doCheck = false;
|
||||||
|
|
|
||||||
36
nix/rust.nix
36
nix/rust.nix
|
|
@ -45,6 +45,23 @@ rec {
|
||||||
# `inherit cargoArtifacts;` so a workspace-only edit doesn't rebuild
|
# `inherit cargoArtifacts;` so a workspace-only edit doesn't rebuild
|
||||||
# deps. All consumers use the same `cleanSrc` so the input hash
|
# deps. All consumers use the same `cleanSrc` so the input hash
|
||||||
# stays consistent across the chain.
|
# stays consistent across the chain.
|
||||||
|
# Two dep caches, one per audience, and the split is not premature:
|
||||||
|
# crane's `buildDepsOnly` defaults `doCheck = true`, which adds
|
||||||
|
# `--all-targets` to the check and a `cargo test --no-run`, so the cache
|
||||||
|
# compiles every dev-dependency and test harness in the tree. The CHECKS
|
||||||
|
# need exactly that. A DEPLOY never runs a test binary and never links
|
||||||
|
# one, so on the deploy path that work is compiled and thrown away.
|
||||||
|
#
|
||||||
|
# They are separate rather than shared because they were never actually
|
||||||
|
# shared: CI evaluates against hyperhive's own nixpkgs pin, while a host
|
||||||
|
# overrides it (security patches cannot wait on a lock bump upstream),
|
||||||
|
# so the two closures differ and neither substitutes for the other. One
|
||||||
|
# cache per audience therefore costs nobody a second build — it just
|
||||||
|
# stops the deploy paying for artifacts only CI consumes.
|
||||||
|
#
|
||||||
|
# ⚠️ `buildDepsOnly` builds from `mkDummySrc`, so both hashes key on
|
||||||
|
# Cargo.toml/Cargo.lock rather than on `.rs` files: a code edit rebuilds
|
||||||
|
# neither, a dependency or toolchain change rebuilds both.
|
||||||
cargoArtifacts = craneLib.buildDepsOnly {
|
cargoArtifacts = craneLib.buildDepsOnly {
|
||||||
src = cleanSrc;
|
src = cleanSrc;
|
||||||
# Workspace Cargo.toml is virtual (no `[package].name`), so crane
|
# Workspace Cargo.toml is virtual (no `[package].name`), so crane
|
||||||
|
|
@ -56,4 +73,23 @@ rec {
|
||||||
version = "0.1.0";
|
version = "0.1.0";
|
||||||
inherit nativeBuildInputs;
|
inherit nativeBuildInputs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# The deploy path's cache: same deps, no test targets. `doCheck = false`
|
||||||
|
# drops crane's `--all-targets` and its `cargo test --no-run`, so
|
||||||
|
# dev-dependencies and test harnesses are never compiled here.
|
||||||
|
#
|
||||||
|
# Only `packages` consume this. Anything that needs to *run* a test —
|
||||||
|
# `checks.cargo-test` — or lint one — `checks.clippy --all-targets` —
|
||||||
|
# takes `cargoArtifacts` above instead, and would rebuild what it needs
|
||||||
|
# if it were pointed here by mistake.
|
||||||
|
cargoArtifactsBinOnly = craneLib.buildDepsOnly {
|
||||||
|
src = cleanSrc;
|
||||||
|
# Distinct pname so the two are told apart in build logs and store
|
||||||
|
# paths; a shared name would make the useful question ("which cache
|
||||||
|
# is this rebuild?") unanswerable at a glance.
|
||||||
|
pname = "hyperhive-workspace-bin";
|
||||||
|
version = "0.1.0";
|
||||||
|
doCheck = false;
|
||||||
|
inherit nativeBuildInputs;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue