pipelines/release.runa.ron
// release.runa.ron — the nordisk constellation release, expressed as DATA.
//
// This is the release pipeline the dwarves forge reads: `dwarves run
// pipelines/release.runa.ron` loads + validates this file through runa's validator
// (DAG cycle / unknown-`needs` check), topo-orders the stage DAG, and dispatches
// every step as a concurrent jera job through the shared Scheduler
// (`crate::runa_exec` / `crate::runa_backend`). No shell, no Groovy — the whole
// release is a typed `dwarves_runa::Pipeline` of typed `dwarves_runa::Step`s.
//
// ⛔ SAFETY INVARIANT — a runa pipeline NEVER `--execute`s / publishes to crates.io.
// The forge's in-process release backend hard-codes `execute: false`: BOTH the
// `ReleaseDoctor` step (plan) AND the `PublishCrates` step (rehearsal gate) run the
// dwarves release engine in DRY-RUN — they compute the deps-first publish waves and
// print the cascade, but upload nothing. The real, irreversible crates.io publish
// stays the human-gated `dwarves workspace-release --execute` path, off this file.
//
// To run against a real constellation checkout:
// DWARVES_REPO_ROOT=/path/to/workspace dwarves run pipelines/release.runa.ron
// (else the repo root defaults to this file's directory). A `Build{variant: "*"}`
// fans out over the repo's DISCOVERED `.nornir/build-variants.toml` set as a matrix.
Pipeline(
name: "constellation-release",
// The release pipeline is startable by hand and on a release push to main; it is
// NEVER a blind auto-publish — the publishing step is a dry-run rehearsal only.
triggers: [
Manual,
Push(branch: "main"),
],
stages: [
// ── lint: the format + clippy gate, both typed steps — `Lint(tool: Fmt)` is
// `cargo fmt --check`, clippy runs with `-D warnings`. (This used to be
// `Xtask(cmd: "fmt-check")`, a verb the xtask never had: MEASURED on dwarf
// 2026-10-16, `xtask: unknown verb fmt-check`.)
Stage(
name: "lint",
steps: [
Lint(tool: Fmt),
Lint(tool: Clippy, deny_warnings: true),
],
),
// ── build: forge every declared deployment variant via build-thing IN-PROCESS
// (a real `cargo build` against the discovered set — zero shell). `"*"` is
// the whole-set matrix: it fans out over the repo's discovered variants as N
// concurrent jera jobs (one per variant); with no declared set it is a single
// build job.
Stage(
name: "build",
needs: ["lint"],
steps: [
Build(variant: "*"),
],
),
// ── test: the fast test matrix, gated behind a green build.
Stage(
name: "test",
needs: ["build"],
steps: [
Nextest(all_features: true),
],
),
// ── doctor: kick off the release. The `ReleaseDoctor` step drives the
// in-process dwarves release engine in DRY-RUN — discover the workspace
// members, plan the deps-first publish waves, print the cascade. Nothing is
// uploaded; this is the pre-publish gate matrix as a pipeline step.
Stage(
name: "doctor",
needs: ["test"],
steps: [
ReleaseDoctor,
],
),
// ── rehearse: the Gate-B local publish REHEARSAL. `PublishCrates` from a runa
// pipeline is ALSO a dry-run through the same in-process engine (execute is
// hard-forced false) — it rehearses the publish waves without touching
// crates.io. The real publish is the human-run `--execute` path, never this.
Stage(
name: "rehearse",
needs: ["doctor"],
steps: [
PublishCrates,
],
),
],
)