Skip to main content

shipper_core/
lib.rs

1//! # shipper-core
2//!
3//! A reliability layer around `cargo publish` for Rust workspaces — library only.
4//!
5//! `shipper-core` provides deterministic, resumable crate publishing with
6//! comprehensive safety checks and evidence collection. It makes `cargo publish`
7//! safe to start and safe to re-run for multi-crate workspaces.
8//!
9//! This crate contains **no CLI code**. The `shipper` CLI lives in the
10//! [`shipper-cli`](https://crates.io/crates/shipper-cli) crate, and the
11//! installable binary is published as
12//! [`shipper`](https://crates.io/crates/shipper) — which is what users
13//! should `cargo install`.
14//!
15//! ## Features
16//!
17//! - **Deterministic ordering** — Crates publish in a reproducible order based on the
18//!   dependency graph, ensuring dependencies are always published before dependents.
19//! - **Preflight verification** — Catch issues before publishing: git cleanliness,
20//!   registry reachability, dry-run compilation, version existence, and ownership checks.
21//! - **Readiness verification** — Confirm crates are visible on the registry after
22//!   publishing, with configurable polling and backoff strategies.
23//! - **Resumable execution** — Interrupted publishes can be resumed from where they
24//!   left off, with state persisted to disk.
25//! - **Evidence capture** — Receipts and event logs provide audit trails for every
26//!   publish operation, including attempt counts, durations, and error classifications.
27//! - **Parallel publishing** — Independent crates can be published concurrently for
28//!   faster workspace releases (opt-in via [`types::ParallelConfig`]).
29//! - **Multiple authentication methods** — Supports token-based authentication and
30//!   GitHub Trusted Publishing.
31//!
32//! ## Pipeline
33//!
34//! The core flow is **plan → preflight → publish → (resume if interrupted)**:
35//!
36//! 1. [`plan::build_plan`] reads the workspace via `cargo_metadata`, filters
37//!    publishable crates, and topologically sorts them.
38//! 2. [`engine::run_preflight`] validates git cleanliness, registry
39//!    reachability, dry-run, version existence, and optional ownership.
40//! 3. [`engine::run_publish`] executes the plan with retry/backoff,
41//!    verifying registry visibility after each crate.
42//! 4. [`engine::run_resume`] reloads persisted state and continues from
43//!    the first pending or failed package.
44//!
45//! ## Example
46//!
47//! ```ignore
48//! use std::path::PathBuf;
49//! use shipper_core::{plan, engine, types};
50//!
51//! // Build a publish plan from the workspace
52//! let spec = types::ReleaseSpec {
53//!     manifest_path: PathBuf::from("Cargo.toml"),
54//!     registry: types::Registry::crates_io(),
55//!     selected_packages: None,
56//! };
57//! let workspace = plan::build_plan(&spec)?;
58//!
59//! // Configure runtime options (all fields must be provided)
60//! let opts = types::RuntimeOptions { /* ... */ };
61//! ```
62//!
63//! ## Key Types
64//!
65//! - `ReleaseSpec` — Input specification (manifest path, registry, package filter)
66//! - `ReleasePlan` — Deterministic, SHA256-identified publish plan
67//! - `RuntimeOptions` — All runtime knobs (retry, readiness, policy, etc.)
68//! - `Receipt` — Audit receipt with evidence for each published crate
69//! - `PreflightReport` — Preflight assessment with finishability verdict
70//! - `PublishPolicy` — Policy presets for safety vs. speed tradeoffs
71//!
72//! ## Modules
73//!
74//! - [`plan`] — Workspace analysis and topological plan generation
75//! - [`engine`] — Core publish, preflight, and resume logic
76//! - [`engine::parallel`] — Wave-based parallel publishing engine
77//! - [`types`] — Domain types: specs, plans, options, receipts, errors
78//! - [`config`] — Configuration file (`.shipper.toml`) loading and merging
79//! - [`auth`] — Token resolution and authentication detection
80//! - [`registry`] — Registry API and sparse-index client
81//! - [`state`] — Layer 3 persistence: state, events, receipts
82//! - [`git`] — Git operations (cleanliness check, context capture)
83//! - [`lock`] — Distributed lock to prevent concurrent publishes
84//! - [`store`] — `StateStore` trait for pluggable persistence backends
85//! - [`cargo`] — Workspace metadata via `cargo_metadata`
86//! - [`cargo_failure`] — Cargo publish failure classification heuristics
87//! - [`webhook`] — Webhook notifications for publish events
88//!
89//! ## Stability
90//!
91//! The library API is subject to change before v1.0.0. Breaking changes will be
92//! documented in the [changelog](https://github.com/effortlessmetrics/shipper/blob/main/CHANGELOG.md).
93//!
94//! ## CLI Usage
95//!
96//! For command-line usage, `cargo install shipper --locked` or see the
97//! [`shipper-cli`](https://crates.io/crates/shipper-cli) crate if you
98//! need to embed the CLI frontend programmatically.
99
100/// Layer-1 absorbed building blocks (previously standalone microcrates).
101pub(crate) mod ops;
102
103/// Token resolution: `CARGO_REGISTRY_TOKEN` → `CARGO_REGISTRIES_<NAME>_TOKEN`
104/// → `$CARGO_HOME/credentials.toml`.
105///
106/// Facade re-exporting the crate-private `ops::auth` module so external
107/// consumers keep using `shipper::auth::*` after the `shipper-auth`
108/// microcrate absorption.
109pub mod auth {
110    pub use crate::ops::auth::{
111        AuthInfo, CARGO_HOME_ENV, CARGO_REGISTRIES_TOKEN_PREFIX, CARGO_REGISTRY_TOKEN_ENV,
112        CRATES_IO_REGISTRY, CREDENTIALS_FILE, TokenSource, cargo_home_path, detect_auth_type,
113        has_token, is_trusted_publishing_available, list_configured_registries, mask_token,
114        resolve_auth_info, resolve_token,
115    };
116}
117
118/// Workspace metadata and publish execution via cargo.
119///
120/// Absorbed from the former `shipper-cargo` microcrate into
121/// [`crate::ops::cargo`]. The historical public path `shipper::cargo`
122/// is preserved for backward compatibility.
123pub use crate::ops::cargo;
124
125/// Configuration file (`.shipper.toml`) loading and merging.
126pub mod config;
127
128/// Core publish, preflight, and resume logic.
129pub mod engine;
130
131/// Git operations (cleanliness check, context capture).
132pub mod git;
133
134/// Distributed lock to prevent concurrent publishes.
135///
136/// Re-export of [`crate::ops::lock`] (absorbed from the `shipper-lock`
137/// microcrate during the decrating effort — see
138/// `docs/decrating-plan.md` §6 Phase 2). The historical public path
139/// `shipper::lock` is preserved for backward compatibility.
140pub use crate::ops::lock;
141
142/// Workspace analysis and topological plan generation.
143pub mod plan;
144
145/// Cargo registry API and sparse-index client.
146/// Re-exported from the [`shipper_registry`] crate (see [`crate::registry`]).
147pub use shipper_registry as registry;
148
149/// Layer 2: runtime context (pure data). Houses `runtime::policy`, `runtime::execution`, etc.
150pub mod runtime;
151
152/// Layer 3: persistence. State, events, receipts.
153pub mod state;
154
155/// `StateStore` trait for pluggable persistence backends.
156///
157/// Absorbed from the former `shipper-store` microcrate. The implementation
158/// now lives under `state/store/` to reflect the layered architecture;
159/// the public path `shipper::store` is preserved for backward compatibility.
160#[path = "state/store/mod.rs"]
161pub mod store;
162
163/// Domain types: specs, plans, options, receipts, errors.
164pub mod types;
165
166/// Configurable retry strategies with backoff and jitter.
167/// Re-exported from shipper-retry microcrate.
168pub use shipper_retry as retry;
169
170/// Cargo publish failure classification heuristics.
171/// Re-exported from shipper-cargo-failure microcrate.
172pub use shipper_cargo_failure as cargo_failure;
173
174/// Webhook notifications for publish events.
175pub mod webhook;
176
177/// State file encryption module.
178pub mod encryption;
179
180/// Property-based tests for shipper invariants.
181#[cfg(test)]
182mod property_tests;
183
184/// Stress tests for concurrent operations.
185#[cfg(test)]
186mod stress_tests;