Release & Versioning
Rust uses SemVer in Cargo.toml. Applications tag git releases; libraries publish to crates.io with changelog entries and API stability promises.
Recipe
# Install release helper
cargo install cargo-release
# Bump patch version, update lock, tag
cargo release patch --execute# Cargo.toml
[package]
name = "my-lib"
version = "0.3.2"
rust-version = "1.97"When to reach for this:
- Publishing workspace crates
- Shipping CLI tools with
--versionoutput - Coordinating breaking API changes across dependents
Working Example
# Binary service: git tag drives deploy
git tag v2.1.0
git push origin v2.1.0
# CI builds container ghcr.io/acme/api:2.1.0// Expose version in CLI
const VERSION: &str = env!("CARGO_PKG_VERSION");
fn main() {
println!("my-cli {VERSION}");
}What this demonstrates:
CARGO_PKG_VERSIONembeds compile-time version- Git tags align with container tags
cargo-releaseautomates manifest + git tag
Deep Dive
SemVer Rules for Rust APIs
| Change | Bump |
|---|---|
| Breaking public trait/struct | Major (1.0+) or minor (0.x) |
| New API additive | Minor |
| Bugfix, internal | Patch |
#[non_exhaustive] and sealed traits soften evolution for libraries.
Changelogs
Maintain CHANGELOG.md with Keep a Changelog format. Link sections to GitHub compare URLs.
Workspace Releases
Release internal crates in dependency order or use release-plz for coordinated bumps.
Gotchas
- Breaking change in patch - downstream breakage. Fix: CI with
cargo semver-checks. - Forgot to publish all workspace members - version skew. Fix: release checklist per crate.
- 0.x crate treated as stable - SemVer allows breaks on minor. Fix: document stability policy.
- Git tag without lockfile update - non-reproducible tag builds. Fix: commit lock with tag.
- Yanked crate left in lock -
cargo buildfails. Fix:cargo update -p cratepromptly.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
release-plz | Multi-crate workspaces | Single binary repo |
| Manual version bump | Full control | Frequent releases |
| Calendar versioning | SaaS deploy only | Published libraries |
FAQs
When to hit 1.0?
When public API contract is stable and breaking changes will trigger major bumps with migration notes.
Pre-release versions?
Use 1.2.0-alpha.1 in Cargo.toml for crates.io pre-releases.
Binary-only repo versioning?
Git tags and container tags matter more than crates.io; still embed CARGO_PKG_VERSION.
How to deprecate APIs?
#[deprecated(since = "0.4.0", note = "use new_fn")] plus changelog entry.
Related
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.