rust-lang/rust-semverver

rust-semverver is a tool to check semver-compliance in Rust library crates

the tool has been developed as a student project during the Google Summer of Code 2017

rust-semverver

rust-semverver is a tool to check semver-compliance in Rust library crates. The core of .

Details on the work done during GSoC 2017 can be found here.

Background

The approach taken is to compile both versions of the crate to rlibs and to link them as dependencies of a third, empty, dummy crate. Then, a custom compiler driver is run on the said dummy and all necessary analysis is performed in that context, where type information and other resources are available.

More information on the inner workings of the tool can be found here.

Installation

The tool is implemented as a cargo plugin. As of now, it can be obtained from this git repository and compiled from source or installed from crates.io. Keep in mind that only the pinned version(in [rust-toolchain]) of the nightly toolchain is supported at any given time.

It's recommended to use nightly-2021-07-23 toolchain. You can install it by using rustup install nightly-2021-07-23 if you already have rustup. Then you can do:

You'd also need cmake for some dependencies, and a few common libraries (if you hit build failures because of missing system-wide dependencies, please open an issue, so they can be added here).

Manual installation and more details

At this point, the current development version can be invoked using cargo semver in any directory your project resides in. If you prefer not to install to ~/.cargo/bin, you can invoke it like so after building with a regular cargo build:

If you have built using cargo build --release instead, change the path to point to the release subdirectory of the target directory.

Usage

By default, running cargo semver in directory with a Cargo project will try to compare the local version to the one last published on crates.io, and display warnings or errors for all changes found.

Invoking cargo semver -h gives you the latest help message, which outlines how to use the cargo plugin:

This means that you can compare any two crates' specified versions, as long as they are available on crates.io or present on your filesystem.

CI setup

Assuming you use a CI provider that gives you access to cargo, you can use the following snippet to check your build for semver compliance, and enforce that version bumps are carried out correctly with regards to the current version of your crate on crates.io:

Make sure you do the above with access to a nightly toolchain. Check your CI provider's documentation on how to do that.

JSON output

By passing the -j flag, all output on standard out is formatted as a machine-readable JSON blob. This can be useful for integration with other tools, and always generates all possible output (ignoring other output-related flags). The output format is defined as follows:

The top level object contains the keys old_version, new_version and changes. The former two hold a version number in the format major.minor.patch, the latter an object describing changes between the crate versions, which contains two arrays in the keys path_changes and changes.

The path_changes array contains objects describing item additions and removals, which have the following keys:

  • name: The name of the item.
  • def_span: An object describing the location of the item in one of the crates.
  • additions: An array of spans that describe locations where the item has been added.
  • removals: An array of spans that describe locations where the item has been removed.

An example object might look like this:

The changes array contains objects describing all other changes, which have the following keys:

  • name: The name of the item
  • max_category: the most severe change category for this item, as a string.
    • Possible values are Patch, NonBreaking, TechnicallyBreaking, and Breaking.
  • new_span: an object describing the location of the item in the new crate (see example).
  • changes: an array of 2-element sequences containing an error message and an optional sub-span (null if none is present)

An example object might look like this:

For reference, all objects describing spans have the same keys:

  • file: A file name.
  • line_lo: The line the span starts on.
  • line_hi: The line the span ends on.
  • col_lo: The column the span starts on.
  • col_hi: The column the span ends on.

Functionality

The guideline used to implement semver compatibility is the API evolution RFC, which applies the principles of semantic versioning to the Rust language's semantics. According to the RFC, most changes are already recognized correctly, even though some type checks still behave incorrectly in edge-cases. A longterm goal is to fix this in the compiler.

At the time of writing, the following types of changes are recognized and classified correctly:

  • items moving from pub to non-pub and vice-versa
  • items changing their kind, i.e. from a struct to an enum
  • additions and removals of region parameters to and from an item's declaration
  • additions and removals of (possibly defaulted) type parameters to and from an item's declaration
  • changes to the variance of type and region parameters
  • additions and removals of enum variants
  • additions and removals of enum variant- or struct fields
  • changes from tuple structs or variants to struct variants and vice-versa
  • changes to a function or method's constness
  • additions and removals of a self-parameter on methods
  • additions and removals of (possibly defaulted) trait items
  • correct handling of "sealed" traits
  • changes to the unsafety of a trait
  • type changes of all toplevel items, as well as associated items in inherent impls and trait definitions
  • additions and removals of inherent impls or methods contained therein
  • additions and removals of trait impls

Keep in mind however that the results presented to the user are merely an approximation of the required versioning policy.

Contributing

Please see CONTRIBUTING.md.

License

rust-semverver is distributed under the terms of the 3-clause BSD license.

See LICENSE for details.

Issues

Collection of the latest Issues

theduke

theduke

Comment Icon0

The JSON output currently seems to only include the spans for changes, not type of change it is.

I'm writing a CI integration that should warn about breaking changes, so having some kind of descriptor would be very useful.

Proposal: add a change field that holds an enum with values like function_added, trait_renamed, struct_deleted, ...

theduke

theduke

Comment Icon0

It would be incredibly useful to have Git integration that allows comparing with a specific Git tag or commit.

This can of course be done manually with a second repo clone in a different path, but a convenient cargo semver --git=v0.2.0 would make that a lot more convenient.

kornelski

kornelski

bug
Comment Icon1

thread 'rustc' panicked at 'assertion failed: !value.has_escaping_bound_vars()', /rustc/027187094ee05011d6602f5742f550851ccc7fd6/compiler/rustc_middle/src/ty/sty.rs:968:9

To reproduce (using 57f2b1f394afb9876b1e1b4dbf1517d7137cd353):

ehuss

ehuss

bug
Comment Icon1

Tried to run cargo semver on the toml-rs crate and got an error:

Details:

  • rust-semverver built from 0bdee60f1d18f17ba48602c500cd1ad9ea83a867 using nightly-2020-12-20
  • Test against a5dc85d0a38cc55033a367b0f24c7a8c23f314e6 of toml-rs (compared against 0.5.8)
  • Running on x86_64-apple-darwin
JohnTitor

JohnTitor

Comment Icon5

(I'm not sure where to discuss this so opening an issue here.) It'd be great if we could make a new release at some point. Currently, libc uses git revisions but I'd like to use a version number instead. https://crates.io/crates/semverver shows only one owner (team), rust-lang-nursery's semver-owners team. But given this is under the rust-lang org now, I think we should add rust-lang-owner as a crate owner like other crates under rust-lang org. And if @Xanewok doesn't have the right to publish, they should also have it (or we could even create a new team and give it the permission).

Xanewok

Xanewok

Comment Icon9

In an effort to streamline reviewing, this repository was moved to the rust-lang organization (from legacy the rust-dev-tools one) in order to use the @bors bot (similar to other repos under rust-lang org). While this should be now complete, there remains a question who should be reviewing the PRs :sweat_smile:

@Manishearth has helped me as an interim reviewer but we discussed on Discord that it'd be good to establish others instead as reviewers.

@ibabushkin @gnzlbg @JohnTitor do you have time and would like to review any new PRs? If not, do you have an idea who could?

Disclaimer: I'm trying to integrate semverver into https://github.com/paritytech/cargo-unleash for automatic workspace package publishing, hence why I'm interested in refreshing semverver a bit :slightly_smiling_face:

eddyb

eddyb

Comment Icon2

As long as we provide an opt-out, it should be possible for cargo publish to build the most recent semver-compatible version of a crate (as downloaded from crates.io), alongside the about-to-publish version (which I believe already always gets built), and compare them for incompatibilities.

cc @ehuss (I don't know where to suggest this on the Cargo side)

ibabushkin

ibabushkin

Comment Icon0

We currently have a number of issues related to our use of cargo that all manifest as some sort of advanced cargo feature interfering with our (rather hacky) way of talking to cargo.

The currently prominent issues: #67, #91. Also, best-effort integration with cargo's newly stabilized offline mode would be quite useful at times.

We have multiple ways of addressing these -- either update our interaction with cargo to support all these features cleanly, or approach the issues from a different angle, for example using something like escargot and cargo-metadata which we already make use of. The main drawback of such an approach would be that it's probably quite hard to get all the features we need from outside cargo. At the same time, not depending on cargo has its benefits, as long as our implementation for, say, finding build artifacts is stable across cargo versions. Most importantly, changes to cargo will no longer cause as much breakage to semverver as in the past.

gnzlbg

gnzlbg

Comment Icon17

The project currently does not build on nightly.

Would it be possible to send email notifications automatically when this happens ? (e.g. via a travis-ci cron job?)

whentze

whentze

Comment Icon2

The usage message for cargo semver states:

usage: cargo semver [options] [-- cargo options]

However, additional options after -- are not passed on to cargo. We should either make that work again or fix the usage message.

ibabushkin

ibabushkin

Comment Icon6

Since librustc_save_analysis is actually a somewhat stable API, a lot of breakage could be avoided (and at the same time, some issues with the checks could be easily addressed).

However, since the API operates essentially on an AST level, a number of issues has to be solved:

  • item correspondence has to be reestablished on an AST level, which is less than ideal (and might be even bad for performance).
  • no existing type check machinery can be reused, we would fall back to completely reimplementing our own reasoning about types and lifetimes on an API level. At the same time, technical issues would become relatively straightforward to solve.

To summarize, I believe such a change will cause a shift from relatively complex, but also somewhat compact functionality to much more code which will become possibly a bit simpler and tailored to our domain.

cc @Manishearth @gnzlbg you guys might be interested. While this could solve a number of problems on the backend side, we'd be reimplementing a lot of functionality that is already there.

dbkaplun

dbkaplun

Comment Icon2

Hello,

It would be great if cargo semver had a subcommand that could automate a chunk of the publishing process and update the version in Cargo.toml. This would make make deployment less error-prone by reducing human interaction.

Thanks for considering!

ibabushkin

ibabushkin

enhancement
Comment Icon1

Currently, we just disambiguate the crates compiled as dependencies of the old and new crate version. This has some issues, however: unchanged types from the two copies of a dependency aren't recognized as the same type, and various smaller issues appear.

A clean solution would be to determine the dependencies of both the old and the new crate, and to compile only one copy of each crate, preferably in a place where we don't interfere with any other tools and can reuse a maximum amount of work already done by cargo for previous compilations. After that, we can proceed to recursively determine matching crates and check them, until we reach the root crates. At this point we'd have all information needed to determine the change category of unchanged types from different crates.

ibabushkin

ibabushkin

bug
Comment Icon1

Multiple items get assigned the same span. This can be solved in a multitude of ways:

  • allow a set of items to be assigned the same span and output all their changes - breaks ordering, tests, and is generally hard to manage correctly.
  • serialize macro backtraces and use the correct span at all times, possibly computing the macro's span too. (that's the right way)
ibabushkin

ibabushkin

bug
Comment Icon1

Basically, the regions test has some examples for things that behave incorrectly. We can't fix this in user code, so we depend on changes in the compiler.

ibabushkin

ibabushkin

enhancement
Comment Icon0

Since any solution to #8 would require us to reason about the versions of our dependencies, we need to be able to check them as well, using our usual set of tools.

Versions

Find the latest versions by id

Information - Updated Apr 12, 2022

Stars: 417
Forks: 30
Issues: 24

serde-json for no_std programs

MIT license (LICENSE-MIT or

serde-json for no_std programs

macOS/iOS Security framework for Rust

MIT license (LICENSE-MIT or

macOS/iOS Security framework for Rust

OpenGliderNetwork client for Rust based on actix

MIT license (LICENSE-MIT or

OpenGliderNetwork client for Rust based on actix

A video game for programmers set in space

MIT license (LICENSE-MIT or

A video game for programmers set in space

Simple SQL migration manager for your project

MIT license (LICENSE-MIT or

Simple SQL migration manager for your project

TODO_README_DESCRIPTION

(LICENSE-MIT or Semantic Versioning 2

TODO_README_DESCRIPTION

CBOR Event library

MIT license (LICENSE-MIT or

CBOR Event library

HAL for the STM32WB55 family of microcontrollers

MIT license (LICENSE-MIT or

HAL for the STM32WB55 family of microcontrollers

Sqllogictest is a testing framework to verify the correctness of an SQL database

(LICENSE-MIT or Developer Certificate of Origin

Sqllogictest is a testing framework to verify the correctness of an SQL database

Computes floating point numbers using eisel-lemire algorithm

This program is licensed under the MIT license

Computes floating point numbers using eisel-lemire algorithm
Facebook Instagram Twitter GitHub Dribbble
Privacy