holger build target — design
Class:
design· Function axis:f0the holger build target (the whole) ·f1the pipeline-as-data ·f2the plan/wiring resolve ·f3the run-time build seam ·f4the local CLI verb ·f5the server RPC (remote-driven) ·f6the thin-client verb (--server, a real gRPC round-trip) Strict: this file states only what the holger build target IS — its parts and why. Sibling how-to: holger-build-thing-guide.md; zero-knowledge walkthrough: holger-build-thing-for-idiots.md.
The holger build target is dwarves' CI/CD pipeline that builds holger's three deployment executables — the tiers embedded · mini · full, each a distinctly-named binary (holger-embedded / holger-mikro / holger-full) built from holger's one holger-server-cli source tree by a mutually-exclusive fatness feature. This is the build-thing that "builds all 3 holger executables", moved out of nornir's holger notion into the forge where a CI/CD target belongs.
The division of labour — two brains, one toolbox (Law #5 / #5a)
- dwarves ORCHESTRATES. It declares the pipeline (three
Variantsteps, one per tier) and resolves each step against holger's declared build-space — a cheap, compile-free plan/wiring check. The plan + its wiring is dwarves' domain. nornir-build-thingBUILDS. At run time the forge drivesbuild_variantper tier — the realcargo build+ a content-addressed provenance attestation, zero shell. dwarves NEVER hand-rolls acargoinvocation.
holger already declares its build-space as data (holger-build-space crate + .nornir/build-variants.toml, the first consumer of nornir-build-thing). The holger build target is the other half of that arc: the forge that consumes that declaration and builds every tier.
The system as one — the function map (f0)
| part | lives in | what it is |
f1 pipeline-as-data |
crates/dwarves/src/holger_build.rs pipeline() |
a brokkr::Pipeline: one build stage, one RunKind::Variant(tier) step per tier; each publishes its tier binary as an artifact |
f2 plan/wiring resolve |
crates/dwarves/src/brokkr/resolve.rs resolve_variants |
maps every Variant step onto a target in a BuildVariantSet; VariantResolution reports resolved + missing; is_complete() iff all resolve |
f3 run-time build seam |
crates/dwarves/src/runner.rs RealRunner → nornir_build_thing::build_variant |
the heavy half: discovers holger's set, cargo builds each tier, captures provenance |
f4 local CLI verb |
crates/dwarves/src/main.rs dwarves holger-build <path> |
resolves the 3 tiers against a LOCAL holger .nornir/build-variants.toml; exit 0 iff all resolve; does NOT compile holger |
f5 server RPC |
crates/dwarves/src/server.rs dwarf.v1 ResolveHolgerBuild |
the SAME resolution over the wire: HolgerBuildRequest{holger_root} → HolgerBuildReply{tiers[], resolved, missing, complete, found}; per-tier bin·package·cargo argv. Registered on the shared nornir-service serve loop + bearer interceptor (no second server); compile-free |
f6 thin-client verb |
crates/dwarves/src/thin_client.rs resolve_holger_build + dwarves holger-build --server <addr> |
drives the f5 RPC over a REAL gRPC round-trip (the path is resolved on the SERVER); prints the same 3-tier report + exit code as f4. Reuses the ONE shared thin_client::call connect+bearer helper (no per-verb tonic client — Law #5) |
Why resolve, not just build
A Variant step only fails on an unknown target at run time, inside build_variant. resolve_variants is the front-door check that lifts that to plan time: it answers "does the holger build target still wire onto holger's declared build-space?" without compiling holger — the affordable CI assertion. If holger renames or drops a tier, the plan reports it missing and is_complete() flips false (the RED-when-broken guard). The tier names here (embedded/mini/full) are holger's real declared ones, so a live resolve_against_repo over the sibling checkout resolves identically to the fixture the test uses.
Three doors onto one resolution (f4 · f5 · f6)
The holger build target now has three doors, one resolve: the local CLI verb (f4, in-process against a local checkout), the server RPC (f5, the wire surface), and the thin-client verb (f6) — dwarves holger-build --server <addr>, which routes f4's glue through f5 over a genuine gRPC round-trip. f6 is what makes the target drivable remotely end-to-end — a client on machine A resolves holger's tiers against a dwarves-server on machine B — not merely testable via the handler.
The client side is the shared dwarves::thin_client module: call(url, token, workspace, f) is the ONE connect+bearer helper EVERY --server verb reuses (the client half of nornir_service's bearer contract — authorization: Bearer <token>), lifted into the lib so the exact path the verb runs is reachable from a live-server round-trip test (no per-verb hand-rolled tonic client — Law #5). resolve_holger_build is the one-line RPC wrapper; main.rs's thin_holger_build is just print + exit-code glue, byte-identical in shape to f4. The path argument is resolved on the SERVER's filesystem; an empty request ⇒ the server's $DWARVES_HOLGER_REPO/../holger default.
Remote-driven — one resolution, two doors (f5)
The north-star is that every surface is remote-controllable. The dwarf.v1 ResolveHolgerBuild RPC is the CLI verb's wire twin: it calls the SAME holger_build::resolve_against_repo_opt (no twin — Law #5) and returns the 3-tier resolution as data — one HolgerTier row per tier (name · step · resolved · bin · package · materialized cargo argv) plus resolved/missing counts, complete, and found. complete is the RED-when-broken predicate: a dropped/renamed tier comes back resolved=false and flips it. A checkout with no build-space returns found=false (an empty plan, not a 404 — mirroring the CLI's exit-2); a malformed descriptor is InvalidArgument. The handler is registered through the shared nornir-service serve loop + bearer-auth interceptor — no second server, no hand-rolled tonic bootstrap (Law #5). Still compile-free: the RPC never builds holger (a remote dwarves run --real over holger is the run-time path).
What stays out (the leaf/conductor line)
The actual cargo build, the provenance record, the BuildVariantSet type — all nornir-build-thing's (the reusable leaf). dwarves keeps only the target: the pipeline, its resolution against a declared set, and the CLI/run surface. The forge plans and wires; the build-thing builds.