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
|
||||
# shared rust build wiring (cleanSrc / cargoArtifacts /
|
||||
# shared rust build wiring (cleanSrc / cargoArtifactsBinOnly /
|
||||
# nativeBuildInputs) comes in via `rust` (see ../rust.nix).
|
||||
{
|
||||
pkgs,
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
}:
|
||||
let
|
||||
inherit (pkgs) lib;
|
||||
inherit (rust) cleanSrc cargoArtifacts nativeBuildInputs;
|
||||
inherit (rust) cleanSrc cargoArtifactsBinOnly nativeBuildInputs;
|
||||
|
||||
docsAttrs = import ../docs {
|
||||
inherit pkgs self;
|
||||
|
|
@ -43,7 +43,7 @@ let
|
|||
};
|
||||
|
||||
# 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
|
||||
# (hive-sh4re, hive-claude, …) compile exactly once instead of once
|
||||
# per bin derivation.
|
||||
|
|
@ -52,9 +52,16 @@ let
|
|||
# (carries the hyperhive-assets build input for the prompt-template
|
||||
# assertions in hive-agent::prompt::tests). Keeping them out of this
|
||||
# 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 {
|
||||
src = cleanSrc;
|
||||
inherit cargoArtifacts nativeBuildInputs;
|
||||
cargoArtifacts = cargoArtifactsBinOnly;
|
||||
inherit nativeBuildInputs;
|
||||
pname = "hyperhive-workspace";
|
||||
version = "0.1.0";
|
||||
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
|
||||
# deps. All consumers use the same `cleanSrc` so the input hash
|
||||
# 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 {
|
||||
src = cleanSrc;
|
||||
# Workspace Cargo.toml is virtual (no `[package].name`), so crane
|
||||
|
|
@ -56,4 +73,23 @@ rec {
|
|||
version = "0.1.0";
|
||||
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