cargo-public-api
cargo-public-api copied to clipboard
Automatically finding semver-breaks for crates-io crates
Just heads up that I'm really liking this project! I'm interested in integrating public_items into https://lib.rs, e.g. list of versions like this https://lib.rs/crates/cc/versions to show which releases were significant, and automatically generate API changelog for crates.
For this I think it would be better to diff an internal simplified representation of types, rather than textual output (of cargo-public-items), so for example if someone adds a struct, I can show the diff as a new struct, not X new fields. But while implementing that I've run into the problem of recursive types — it's unfortunately not possible to "flatten" rustdoc's types to remove the index indirection.
Happy to hear you like the project! The whole reason I started this project was because I was missing a tool to easily diff changes to the public API of different versions of a crate. So in that sense it is a good fit for the use case you describe for lib.rs.
I completely agree that it long-term make sense to introduce a new type and return a Vec of that rather than a Vec of Strings. I have actually experimented with that already. In 7c6f96839f (which is on a temporary branch where lots of things are broken) the library produces a Vec<PublicItem> instead of Vec<String>, with the long-term intention of supporting things like more flexible sorting/grouping of items, to enable generating "smarter" diffs, like for example whole structs at once. I felt it was too early to complicate the API with that though. It's hard to figure out what that API would look like exactly when not even basic type info is included in the output of an item. Something that I am also experimenting with getting in place.
The roadmap for this project is roughly:
- Fix Enselic/public-api#11 by traversing items from the root rather than only considering items with crate_id 0 Update 2022-03-13: Done
- Wait for https://github.com/rust-lang/rust/issues/92945 to get fixed, which is a quite serious problem for
public_itemsuse cases (at least before full type info is available). There is an open PR to resolve it, so I expect that to be resolved quite soon. Update 2022-03-13: Still not resolved upstream, but since type info is included for tuples now, this is not that important anymore. - Add complete type info to each item, which is actually quite a bit of work to fully support. Update 2022-03-13: There are certainly work left to do, but for a wide variety of crates, the type info that is given is pretty broad and complete
- Make
cargo public-itemsmore robust, e.g. support workspaced crates Update 2022-03-13: Workspaced crates are supported, as well as rudementary diffs between public APIs for different git commits of a crate. - Expand regression tests with more real-world crates to make sure the tool works on a wide variety of crates. Currently I only test against syntect v4.6.0. Update 2022-03-13: More tests are in place
- At this point I think we are in a good position to explore what the
PublicItemtype discussed above would look like exactly.
This is obviously just a rough sketch. In any case, I am happy to stay in touch and collaborate further on e.g. integrating with lib.rs when the time is right.
I would say this project is now at a point where starting to experiment with integrating with lib.rs could make sense. I have still not figured out a good way to "diff whole structs at once", but diffing as a concept is supported.
There is quite a bit of value in being able to say "public API was removed between version X and version Y", for example.
Here is how public_items can be used to diff two different versions of a crate, as long as you have the rustdoc JSON for both versions of the crate:
https://github.com/Enselic/public_items/blob/e14d12ac4fd589acfc822aa9bbb2c82b472bf027/examples/public_api_diff.rs#L1-L22
The output of the above program is:
PublicItemsDiff {
removed: [],
changed: [
ChangedPublicItem {
old: pub fn public_items::sorted_public_items_from_rustdoc_json_str(rustdoc_json_str: &str) -> Result<Vec<PublicItem>>,
new: pub fn public_items::sorted_public_items_from_rustdoc_json_str(rustdoc_json_str: &str, options: Options) -> Result<Vec<PublicItem>>,
},
],
added: [
pub fn public_items::Options::clone(&self) -> Options,
pub fn public_items::Options::default() -> Self,
pub fn public_items::Options::fmt(&self, f: &mut $crate::fmt::Formatter<'_>) -> $crate::fmt::Result,
pub struct public_items::Options,
pub struct field public_items::Options::with_blanket_implementations: bool,
],
}
The code (and the entire git history) of this project has been moved to https://github.com/Enselic/cargo-public-api/tree/main/public-api. Note that only the code has moved. The crate/library/package still exist, and is in use and works the same as before.
See https://github.com/Enselic/public-api/issues/95 for why this was done.
I'm moving this issue too now.
I'm not entirely sure what needs to happen for this issue to be considered resolved.
The current status in terms of this tool and its libraries is that out of 240769 crates, only 3 were found to have an ICE when building rustdoc JSON, and those ICEs are soon fixed. See https://github.com/rust-lang/rust/issues/99919 and linked issues/crater runs for more details. And there are by now no known bugs or limitations on the rustdoc JSON processing and diffing of this tool.
So I would say this tool and its libraries are ready for wide use, including integration on lib.rs.
You did mention this in the issue description:
for example if someone adds a struct, I can show the diff as a new struct, not X new fields
and I agree that would be nice, but I don't think that is a blocker for lib.rs integration. Besides, I think that enhancement can be considered tracked in #37 and #38.
Maybe we can close this issue? If not, could you elaborate a bit more on what stops you from integrating with lib.rs?
(I don't think it makes sense to track the integration itself with lib.rs in this issue tracker.)
Big thanks in advance for any input.
Thanks for implementing this. Sorry for holding this up. I just haven't found time to do the integration on my side.
I think it's fine to close. If I run into something, I'll open new issues.