Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check for consistent versioning of direct dependencies in the workspace #436

Open
ahollmann opened this issue Jul 18, 2022 · 9 comments
Open
Labels
enhancement New feature or request

Comments

@ahollmann
Copy link

I'm using an allow list for whitelisting dependencies in a big workspace. I have to generate a list of all direct and transitive dependencies.

Adding a depth option like it exists in cargo tree --depth 1 would simplify this use case.

I cannot judge if this option fits with other use cases or breaks features in cargo deny.

Example: deny.toml

[bans]

allow = [
    { name = "anyhow", version = "1.0.58" },
    ... all dependencies in the workspace ... 
]
@ahollmann ahollmann added the enhancement New feature or request label Jul 18, 2022
@Jake-Shadle
Copy link
Member

Maybe I'm misunderstanding, but having a depth of 1 would mean that you'd only be checking direct dependencies and no transitive dependencies at all, which would make the use of cargo-deny fairly pointless?

@ahollmann
Copy link
Author

ahollmann commented Jul 18, 2022

You are right. For license checks it wouldn't make any sense. So the command line option would be a bad idea.

For the allowed list it would be still useful. A configuration option for the allowed list would be more appropriate? Otherwise you would have to list hundreds of transitive dependencies.

Something like this:

[bans]
allow_list_depth = 1

allow = [
    { name = "anyhow", version = "1.0.58" },
    ... list only direct dependencies here ... 
]

My use case would be a big workspace with multiple developers working on individual crates. This would help keeping used dependencies and versions in sync by the CI.

@Jake-Shadle
Copy link
Member

It feels like you would get a lot more utility from checking in your Cargo.lock file and using a deny list and multiple-versions lint?

FWIW your use case sounds a bit similar to ours, a large monorepo, a dozen or so developers and around 1000 or so crates across the various platforms we target. The allow list was added for symmetry with the deny list, and the specific use case of small library crates that want really strict control over their dependencies, which is why trying to use it in a large workspace is painful.

@ahollmann
Copy link
Author

ahollmann commented Jul 19, 2022

https://github.com/rust-lang/rfcs/blob/master/text/2906-cargo-workspace-deduplicate.md

Deduplicate common dependency and metadata directives amongst a set of workspace
crates in Cargo with extensions to the [workspace] section in Cargo.toml.

This cargo RFC seems to meet my requirements. I hope it gets merged soon into cargo.

My feature request for cargo deny goes into the same direction by enforcing a version with an external tool.

We are already using Cargo.lock, but it is not the place to define common dependencies across the workspace.

Thanks for your valuable input and thanks for the work on cargo deny.

@Jake-Shadle
Copy link
Member

Ok, I think I understand now, you just want all direct dependencies in your workspace to have consistent versioning. We just use the multiple-versions lint to detect that case, but I can understand wanting a separate lint for this scenario since I think some people think the multiple-versions lint is too harsh maybe. I think in this case it would make sense to just have a separate lint that checks that specific case that can be used with or without the regular multiple-versions lint. So if used without, you can have any number of duplicate transitive dependencies, but at least on the workspace level all dependencies are consistent. The lint can then be retired if/when cargo implements the above RFC you linked.

@ahollmann
Copy link
Author

You've summarized it perfectly.

The approach with denying multiple-versions does not work, since we have no control about transitive dependencies which result in multiple versions of the same crate.

@Jake-Shadle
Copy link
Member

multiple-versions works quite well, you just have to use the skip and skip-tree fields to selectively ignore old versions, then cargo-deny warns when you have skips that no longer match anything in the graph so you can keep the configuration relatively clean.

skip = [
    # very common dependency.
    { name = "cfg-if", version = "0.1.10" },

    # Used by core-graphics and core-video-sys
    { name = "core-foundation", version = "<0.9.1" },
    { name = "core-foundation-sys", version = "<0.9.1" },

    # used by core-video-sys 0.1.4 which winit relies on. TODO
    { name = "core-graphics", version = "<0.22.2" },

    # ark-ml -> tract-onnx -> tract-hir -> tranct-core -> tranct-linalg ->
    # liquid -> liquid-core -> pest_derive -> pest_generator -> pest_meta ->
    # sha-1
    { name = "block-buffer", version = "=0.7" },
    { name = "digest", version = "=0.8" },
    { name = "sha-1", version = "=0.8" },

    # ... -> sha-1 -> block-buffer (see above)
    { name = "generic-array", version = "=0.12" },

    # winit, wayland, etc
    { name = "nix", version = "=0.22" },
    { name = "memmap2", version = "=0.3.1" },

    # ash-window using old, PR: https://github.com/MaikKlein/ash/pull/505
    # Several crates have not moved to the recent 0.4.2 version
    { name = "raw-window-handle", version = "0.3.4" },

    # prost, strum, system-deps, wiggle-generate are on older version
    { name = "heck", version = "=0.3" },

    # a lot of crates use the older parking_lot
    { name = "parking_lot", version = "=0.11" },
    { name = "parking_lot_core", version = "=0.8" },

    { name = "tokio-util", version = "=0.6" },

    # minidump-common -> range-map -> num-traits uses an old version, and
    # unfortunately range-map seems unmaintained
    { name = "num-traits", version = "=0.1.43" },

    # metrics-util not upgraded yet
    { name = "ordered-float", version = "=2" },

    # wasmtime uses an older version than backtrace
    { name = "object", version = "=0.27.1" },

    # wasmtime uses a fairly outdated version
    { name = "wasmparser", version = "=0.83.0" },

    # clap -> indexmap -> hashbrown is an older version than that used by dashmap
    { name = "hashbrown", version = "=0.11.2" },

    # several crates still use this older version
    { name = "nix", version = "=0.23.1" },

    # winit not upgraded yet
    { name = "smithay-client-toolkit", version = "=0.15" },

    # we depend on macaw/perchance via Cervo and it's part of this workspace, so we need to add an exception here to allow multiple sources.
    { name = "macaw", version = "0.17.0" },
    { name = "perchance", version = "0.3.1" },
]
skip-tree = [
    # old version transitively used by ndk-glue
    { name = "darling", version = "=0.13.4" },

    # many crates use different versions, lots of churn.
    # our tracking issue discussing that with Microsoft: https://github.com/microsoft/windows-rs/issues/1720
    { name = "windows-sys", version = "=0.36" },
]

@ahollmann
Copy link
Author

ahollmann commented Jul 20, 2022

Thanks!

multiple-versions works indeed quite well! Somehow I wasn't aware how to use it properly.

The titel got misleading.

I could replace it with: Check for consistent versioning of direct dependencies in the workspace.

@ahollmann ahollmann changed the title Add depth option Check for consistent versioning of direct dependencies in the workspace Jul 21, 2022
@Jake-Shadle
Copy link
Member

Now that cargo supports workspace inheritance I think the addition of this feature becomes much less interesting, I guess it could still be useful in some cases, but not enough to do myself, though PRs are welcome.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants