Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Configure your repository

This walkthrough uses example/widgets, a placeholder GitHub repository. Replace it with your repository and select the branch that actually releases. The TOML fragments below belong in existing manifests; they are not complete standalone Cargo projects.

Workspace inputs

Track the workspace and package manifests, publication configuration, lockfile and build-toolchain selection. Prepare a consistent lockfile before collecting release evidence. Publication verifies the committed resolution rather than repairing it.

Choose package inclusion rules using the released-content model. For example:

# Workspace Cargo.toml
[workspace.package]
include = ["src/**/*"]
# packages/widget/Cargo.toml, within [package]
include.workspace = true

Packages needing additional compile-time inputs declare a complete allow-list of their own.

Declare groups and consumer contracts

The library uses its exact-version implementation:

# packages/widget/Cargo.toml
[dependencies]
widget_impl = { path = "../widget_impl", version = "=1.4.0" }

[package.metadata.cargo_check_external_types]
allowed_external_types = ["widget_impl::*"]

The implementation is published so Cargo can resolve it, but does not promise an independently supported API:

# packages/widget_impl/Cargo.toml
[package.metadata.release-plan]
private-api = true

A helper can share alignment without being published:

# packages/widget-fixtures/Cargo.toml
[package]
name = "widget-fixtures"
version = "1.4.0"
publish = false

[dependencies]
widget_impl = { path = "../widget_impl", version = "=1.4.0" }

The exact edges join all these members. Do not add a separate workspace group table. An ordinary version = "1.4.0" requirement names the same declared version but does not create an exact-version group.

Verify external-type exposure

Every library’s allow-list describes types outside that crate which its public API may expose. Use defining crate paths, including implementation paths reached through re-exports. A crate-level glob is useful for your own implementation partition; list other external types narrowly so accidental exposure remains visible.

An omitted allow-list declares no external exposure; it does not mean exposure is unknown. cargo-release-plan check reads declarations but does not compile and verify them. Adopt cargo-check-external-types as a required API-validation gate.

Pin the checker and its matching rustdoc nightly together. The revision below provides the workspace and multi-target checking required by this gate. Select a published release only when it supports those operations; take the matching nightly from its rust-toolchain.toml, independently of your application’s compiler.

$ErrorActionPreference = "Stop"
$PSNativeCommandUseErrorActionPreference = $true
$ExternalTypesRevision = "705a0941997ebeb3bfb1a7f14070ba342f79d879"
$ExternalTypesNightly = "nightly-2026-03-20"
rustup toolchain install $ExternalTypesNightly --profile minimal
cargo install cargo-check-external-types --locked --force `
    --git https://github.com/awslabs/cargo-check-external-types `
    --rev $ExternalTypesRevision
cargo "+$ExternalTypesNightly" check-external-types --all-features --skip-unsupported `
    --manifest-path Cargo.toml

The explicit reinstall establishes the selected revision even when another build has the same package version; it costs a rebuild rather than relying on version-only reuse. An automated installer can avoid that cost by verifying Cargo’s recorded source revision before deciding whether to reinstall.

The workspace invocation checks each eligible library using its own allow-list, including implementation packages. A dynamically discovered package subset is an optional CI optimization, not a manually maintained library list. Cover the relevant feature and platform surfaces; an all-features run on Linux cannot prove a Windows-only signature. Review unused entries in context because some are needed only on another target. Avoid overlapping patterns.

Feed these checks into your required status alongside tests, builds and release checks. A successful version check cannot substitute for this prerequisite.

Configure publication

Commit .cargo/release_plan.toml at the selected workspace root:

schema-version = 1
repository = "example/widgets"
release-branch = "main"
targets = [
    "x86_64-unknown-linux-gnu",
    "x86_64-pc-windows-msvc",
]

This example selects native Linux and Windows x64 binaries. A library-only workspace can use targets = []. The full supported target set and precedence are in the configuration reference.

--config is workspace-relative, even when invoking from elsewhere. For a nested workspace:

$WorkspaceManifest = Join-Path "components" "widgets" "Cargo.toml"
$Configuration = Join-Path ".cargo" "release_plan.toml"
cargo release-plan check --manifest-path $WorkspaceManifest --config $Configuration

This reads components\widgets\.cargo\release_plan.toml. Artifact paths inside publication files are instead repository-relative so different jobs can transport them without sharing absolute checkout paths.

Describe the binary archive

widget-cli is the package; widget is its executable:

# packages/widget-cli/Cargo.toml
[package]
name = "widget-cli"
version = "2.0.0"
repository = "https://github.com/example/widgets"

[[bin]]
name = "widget"
path = "src/main.rs"

[dependencies]
widget = { path = "../widget", version = "1.4.0" }

[package.metadata.binstall]
pkg-url = "{ repo }/releases/download/{ name }-v{ version }/{ name }-v{ version }-{ target }.zip"
bin-dir = "{ bin }{ binary-ext }"
pkg-fmt = "zip"

Binary packages must declare one executable that builds with Cargo’s default features. Check that selection in your own build validation; the offline release check does not resolve features or compile. Publication uses the explicit native Cargo build to check feature requirements and buildability. Repository and binstall layout must match publication configuration. Package release-targets can narrow the workspace selection:

[package.metadata.release-plan]
release-targets = ["x86_64-pc-windows-msvc"]

Use this only for a genuinely restricted package. Binary packages must retain at least one selected target.

Validate the inputs without querying a registry:

cargo release-plan check --config (Join-Path ".cargo" "release_plan.toml")

Configuration changes are often released manifest changes too. Continue with local planning rather than fixing a failing version check by hand-incrementing isolated packages.