Most of our repositories contain multiple crates which are part of the same workspace. We also have a number of inter-repository dependencies (e.g. digest depends on crypto-common). In such cases instead of using path while specifying dependency in the crate's Cargo.toml we use dependency patching (e.g. see here).
Currently we commit workspace's Cargo.lock and update it periodically using Dependabot. It allows us to isolate CI failures caused by upstream dependencies. It also reduces CI times a bit since we don't need to generate lock files from scratch. We use the same Cargo.lock for both MSRV and stable tests. MSRV tests use versions manually provided in the CI config.
Additionally, we have minimal-versions jobs which test crates separately from the repository workspace using unstable -Z minimal-versions option. Unfortunately, testing it outside of workspace means that dependency patching defined on the workspace level does not works and we have to manually disable such jobs while patching is present.
In the new releases we plan to rely on the MSRV-aware resolver meaning that we can update MSRV in patch releases, which can lead to mixed-MSRV workspaces. Considering how the MSRV-aware resolver works by default (it selects dependency versions compatible with the declared MSRV), it may be problematic.
Imagine a repo with crates A and B with MSRV equal to 1.85, now in a new version of A we want to use dependency C with MSRV 1.90. We bump MSRV of crate A accordingly, but now we have a problem: the resolver is unable to generate Cargo.lock compatible with MSRV of crate B.
Going forward, I think we should test at least 3 scenarios for all crates:
- Stable toolchain with latest semver-compatible dependencies (i.e. generated with
cargo update --ignore-rust-version)
- MSRV toolchain acquired from the
rust-version field with latest MSRV-compatible dependencies
- Nightly toolchain with minimal semver-compatible version (i.e. generated with
-Z minimal-versions)
This list would require the following changes:
- If we want to continue committing Cargo.lock we should add
.cargo/config.toml to every repository with incompatible-rust-versions = "allow" to satisfy 1.
- To satisfy 2 we would need to add extraction of the
rust-version value (see this URLO thread) and to exclude the crate from the repo workspace.
Unresolved questions:
- Should we continue to commit Cargo.lock? I don't remember many cases of upstream dependencies breaking CI, so it may not be important. We could replace it with a cron job which would test freshest upstream dependencies periodically.
- Should we test on Nightly and/or Beta with latest semver-compatible dependencies?
- Should we use MSRV toolchain to run tests
minimal-versions jobs (i.e. use Nightly to generate lock file and switch to MSRV toolchain for cargo test)?
- How to deal with
patch issues in 2 and 3?
Most of our repositories contain multiple crates which are part of the same workspace. We also have a number of inter-repository dependencies (e.g.
digestdepends oncrypto-common). In such cases instead of usingpathwhile specifying dependency in the crate's Cargo.toml we use dependency patching (e.g. see here).Currently we commit workspace's Cargo.lock and update it periodically using Dependabot. It allows us to isolate CI failures caused by upstream dependencies. It also reduces CI times a bit since we don't need to generate lock files from scratch. We use the same Cargo.lock for both MSRV and stable tests. MSRV tests use versions manually provided in the CI config.
Additionally, we have
minimal-versionsjobs which test crates separately from the repository workspace using unstable-Z minimal-versionsoption. Unfortunately, testing it outside of workspace means that dependency patching defined on the workspace level does not works and we have to manually disable such jobs while patching is present.In the new releases we plan to rely on the MSRV-aware resolver meaning that we can update MSRV in patch releases, which can lead to mixed-MSRV workspaces. Considering how the MSRV-aware resolver works by default (it selects dependency versions compatible with the declared MSRV), it may be problematic.
Imagine a repo with crates A and B with MSRV equal to 1.85, now in a new version of A we want to use dependency C with MSRV 1.90. We bump MSRV of crate A accordingly, but now we have a problem: the resolver is unable to generate Cargo.lock compatible with MSRV of crate B.
Going forward, I think we should test at least 3 scenarios for all crates:
cargo update --ignore-rust-version)rust-versionfield with latest MSRV-compatible dependencies-Z minimal-versions)This list would require the following changes:
.cargo/config.tomlto every repository withincompatible-rust-versions = "allow"to satisfy 1.rust-versionvalue (see this URLO thread) and to exclude the crate from the repo workspace.Unresolved questions:
minimal-versionsjobs (i.e. use Nightly to generate lock file and switch to MSRV toolchain forcargo test)?patchissues in 2 and 3?