Skip to content

geraschenko/cargo-ratchet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cargo-ratchet

GitHub Crates.io Docs.rs

Prevent resolved dependency versions in Cargo.lock from dropping below a committed baseline. Rebases, lockfile regeneration, and targeted cargo update invocations can silently downgrade resolved versions; cargo build --locked detects drift from the committed lockfile but does not enforce a version floor.

Usage

cargo install cargo-ratchet
cargo ratchet

The first run creates .Cargo.lock.ratchet at the workspace root; commit it alongside Cargo.lock. After changing dependencies, run cargo ratchet again and commit the updated baseline.

In CI, run:

cargo ratchet --fail-on-change

This never writes and passes only when the baseline is byte-identical to Cargo.lock. The fix for any failure is the same: run cargo ratchet locally and commit the result. Exit code is 0 on pass, nonzero otherwise.

Options

  • --fail-on-change — never write; fail unless the baseline exactly matches the lockfile.
  • --json — report violations as JSON on stdout instead of text on stderr.
  • --manifest-path <PATH> — select the workspace (the lockfile lives at its root).
  • --lockfile <PATH> — check a specific lockfile without workspace discovery.
  • --ratchet-file <PATH> — override the baseline path [default: .<lockfile name>.ratchet next to the lockfile].

What is checked

For each package name in the baseline, the highest resolved version in each lockfile is compared: removing a package is allowed, lowering its highest version is not. A name may legitimately appear at multiple versions (e.g. http 0.2 and http 1 during ecosystem transitions); only the highest per name participates.

Resolved crates.io dependency edges from those highest-version packages are compared the same way, which catches a package's resolved dependency being downgraded even when the workspace still contains the newer version elsewhere. Git, path, and alternate-registry edges are skipped because version ordering alone does not establish immutable identity there.

Why checking and advancing are one operation

Every passing check copies Cargo.lock over the baseline — that is what produces the ratchet effect; a separate advance command would be forgotten and the floor would lag. And the baseline can never advance without a passing check, so baseline updates can't slip in unchecked.

Intentional downgrades

To permit a deliberate downgrade (e.g. backing off a broken upgrade), edit .Cargo.lock.ratchet to lower the affected floor — with justification in review — then re-run cargo ratchet.

Library use

compute_violations(&baseline, &current) is a pure function from two parsed cargo_lock::Lockfiles to a list of violations; check_and_advance(&paths) and check_fail_on_change(&paths) add the file orchestration described above.

Non-goals

  • Other ecosystems' lockfiles (package-lock.json, uv.lock, flake.lock, …). The semantics here — semver ordering, crates.io release immutability, resolved-edge structure — are Cargo-specific.
  • Ratcheting git/path/alternate-registry dependency identity (commit pinning policy). Possible future expansion, separate policy.
  • Duplicate-version bans (cargo-deny covers this) or vulnerability checks (cargo-audit covers this).

About

Prevent resolved dependency versions in `Cargo.lock` from dropping below a committed baseline.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors