When you maintain public crates, accidentally shipping a breaking change in a patch or minor release erodes trust. cargo-semver-checks lints your API diff against the last published version and catches violations before cargo publish.
cargo install cargo-semver-checks
Run from your crate directory:
cargo semver-checks
This compares your local code against the latest version on crates.io. If you've removed a public function, changed a signature, or removed a trait impl, it flags it.
# Compare against a specific published version
cargo semver-checks --baseline-version 0.5.0
# Compare against a git rev
cargo semver-checks --baseline-rev v0.5.0
cargo-semver-checks runs lints — each one detects a specific kind of breaking change:
| Category | Examples |
|---|---|
| Removals | Public function/struct/enum/trait removed |
| Signature changes | Parameter added, return type changed |
| Trait changes | Required method added, impl removed |
| Type changes | Struct field made private, enum variant removed |
| Generics | Type parameter added/removed, bound tightened |
| Re-exports | Public re-export removed |
Add it to your publish checklist, right after tests and before cargo publish --dry-run:
#!/bin/bash
set -e
cargo test
cargo clippy -- -D warnings
cargo semver-checks # ← catches breaking changes
cargo publish --dry-run
[doc("Check semver compliance against crates.io")]
semver-check:
cargo semver-checks
[doc("Full pre-publish validation")]
pre-publish: test clippy semver-check
cargo publish --dry-run
Suppose you rename a function in rfconversions:
// Before (v0.7.2)
pub fn db_to_linear(db: f64) -> f64 { ... }
// After (local)
pub fn decibels_to_linear(db: f64) -> f64 { ... }
Running cargo semver-checks:
--- failure: function_missing ---
Description: A publicly-visible function has been removed or renamed.
Changed: rfconversions::db_to_linear
Removed in: (local)
Previously in: 0.7.2
This tells you: bump the major version, or add a deprecated alias.
Instead of breaking, keep the old name as a deprecated alias:
pub fn decibels_to_linear(db: f64) -> f64 {
10f64.powf(db / 10.0)
}
#[deprecated(since = "0.8.0", note = "renamed to decibels_to_linear")]
pub fn db_to_linear(db: f64) -> f64 {
decibels_to_linear(db)
}
Now cargo semver-checks passes — no breaking change. Downstream users get a compiler warning guiding them to migrate.
For workspace roots with multiple crates:
# Check all crates in workspace
cargo semver-checks --workspace
# Check a specific crate
cargo semver-checks -p gainlineup
Add to GitHub Actions:
- name: Check semver
uses: obi1kenobi/cargo-semver-checks-action@v2
This blocks PRs that introduce unintentional breaking changes.
Cargo.toml — it compares against the published version--baseline-version when you want to check against an older release#[deprecated] for graceful migrations