Zepter

Rust crates.io MSRV docs.rs

Analyze and fix feature propagation in your Rust workspace. The goal of this tool is to automatically lint and fix feature propagation in CI runs.

Install

bash cargo install -f zepter --locked

Example - Fixing feature propagation

Let's check that the runtime-benchmarks feature is properly passed down to all the dependencies of the frame-support crate in the workspace of [Substrate]. You can use commit 395853ac15 to verify it yourself:

bash zepter lint propagate-feature --feature runtime-benchmarks -p frame-support --workspace

The output reveals that some dependencies expose the feature but don't get it passed down:

pre crate 'frame-support' feature 'runtime-benchmarks' must propagate to: frame-system sp-runtime sp-staking Found 3 issues and fixed 0 issues.

Without the -p it will detect many more problems. You can verify this for the frame-support which is indeed missing the feature for sp-runtime while sp-runtime clearly supports it 🤔.

This can be fixed by appending the --fix flag, which results in this diff:

patch -runtime-benchmarks = [] +runtime-benchmarks = [ + "frame-system/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "sp-staking/runtime-benchmarks", +]

The auto-fix can be configured to enable specific optional dependencies as non-optional via --feature-enables-dep="runtime-benchmarks:frame-benchmarking" for example. In this case the frame-benchmarking dependency would enabled as non-optional if the runtime-benchmarks feature is enabled.

Example - Feature tracing

Let's say you want to ensure that specific features are never enabled by default. For this example, we will use the try-runtime feature of [Substrate]. Check out branch oty-faulty-feature-demo and try:

bash zepter lint never-implies --precondition default --stays-disabled try-runtime --offline --workspace

The precondition defines the feature on the left side of the implication and stays-disabled expressing that the precondition never enables this.

Errors correctly with: pre Feature 'default' implies 'try-runtime' via path: frame-benchmarking/default -> frame-benchmarking/std -> frame-system/std -> frame-support/wrong -> frame-support/wrong2 -> frame-support/try-runtime

Only the first path is shown in case there are multiple.

Example - Dependency tracing

Recently there was a build error in the Substrate master CI which was caused by a downstream dependency snow. To investigate this, it is useful to see how Substrate depends on it.

Let's find out how node-cli depends on snow (example on commit dd6aedee3b8d5):

bash zepter trace node-cli snow

It reports that snow is pulled in from libp2p - good to know. In this case, all paths are displayed.

pre node-cli -> try-runtime-cli -> substrate-rpc-client -> sc-rpc-api -> sc-chain-spec -> sc-telemetry -> libp2p -> libp2p-webrtc -> libp2p-noise -> snow

Testing

UI and integration tests are run with the normal cargo test.
Environment overwrites exist for: - OVERWRITE: Update the cout and diff locks. - UI_FILTER: Regex to selectively run files. - KEEP_GOING: Print FAILED but don't abort. TODO: It's buggy

Roadmap