release / deps — guide
Class:
guide· how to USEdwarves release+dwarves deps. What it IS: release-deps-consume-design.md.
Two ACT verbs backed by the shared edda leaves (nornir-release, nornir-depgraph). Both need the release feature:
cargo build -p dwarves --features release
# or run in place:
cargo run -p dwarves --features release --bin dwarves -- release .
dwarves release <workspace> — plan the publish waves
dwarves release .
Prints the deps-first publish waves for the workspace (each wave may publish in parallel; a dependency is always in an earlier wave than its consumers), skips publish = false members, and states the source-drift SKIP contract:
release plan for . (7 publishable crate(s), 3 wave(s)):
wave 0: edda-leaf-a, edda-leaf-b
wave 1: nornir-release
wave 2: nornir
skip contract: a crate skips republish ONLY when already published AND its
source is byte-identical (nornir-release `can_skip_republish`); the live drift
assessment + the actual publish are nornir's warehouse-coupled cascade (gRPC).
It is a dry-run planner — it does not publish. The live drift check + the actual cargo publish are nornir's warehouse-coupled cascade (dwarves reaches them over gRPC). Exit is non-zero if the workspace has a dependency cycle.
The pre-flight SIZE gate — --check-size / --max-upload-mib
crates.io refuses an oversized upload with a bare HTTP 503 carrying no size and no reason (cargo: failed to get a 200 OK response, got 503) — indistinguishable from an outage. So the size is measured HERE, in the same pass as the skip/drift verdicts and before anything uploads.
dwarves release . # prints the limit + where the number came from
dwarves release . --check-size # + packages every crate now and weighs the .crate
dwarves release . --execute # the size pass runs automatically, pre-upload
dwarves release . --max-upload-mib 20 # a granted increase, or another registry's limit
dwarves release . --only korp --check-size # scope it — one `cargo package` per crate
size gate: crates.io upload limit 10.0 MiB (source: crates.io server config `max_upload_size` = 10 MiB, read 2026-09-02; …)
size: korp@0.1.0 packages to 7.0 MiB (592 file(s)) — within 10.0 MiB
Over the limit, the whole cascade is refused before any upload (the drift halt's shape) with the biggest directories and files in the .crate named, plus the two honest remedies: shrink it (exclude/include) or get the limit raised and pass --max-upload-mib. Exit code 1.
The limit is never a magic number. Precedence, highest first: --max-upload-mib → DWARVES_MAX_UPLOAD_BYTES_<ALIAS> → DWARVES_MAX_UPLOAD_BYTES → the documented CRATES_IO_MAX_UPLOAD_BYTES constant (10 MiB, with its date and source, applied only when the target is crates.io). A --registry <alias> with no override has an honestly UNKNOWN limit and refuses nothing.
If a 503 still arrives mid-cascade it is translated with what was measured: over the limit ⇒ named as the size refusal and not retried; within it ⇒ read as transient and retried like a 429; never measured ⇒ said plainly, with --check-size named.
The same pass also prints which uncommitted files are actually IN each .crate, so cargo's "N files in the working directory contain changes" stops being a hunt through Cargo.lock churn and other lanes' work.
dwarves deps <dir> — the suite dependency graph
dwarves deps /path/to/repos # a directory of side-by-side repos
Builds the cross-repo dependency graph (each subdir with a Cargo.toml is a repo) and prints the deps-first build order + node/edge counts — the same graph nornir's dep view renders, from the same nornir-depgraph leaf:
suite deps under /path/to/repos — 3 repo(s), 2 direct edge(s):
build order (deps-first): leaf → mid → app
Without the feature
$ dwarves deps .
`dwarves deps` needs the depgraph leaf: rebuild with --features release