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

Version 0.7.0 #8

Merged
merged 14 commits into from
Jul 27, 2023
2 changes: 1 addition & 1 deletion .github/workflows/install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:

steps:
- name: Cargo install
run: cargo install --git ${{ github.server_url }}/${{ github.repository }} zepter --rev $GITHUB_SHA --locked
run: cargo install --git ${{ github.server_url }}/${{ github.repository }} zepter --rev $GITHUB_SHA --locked -q

- name: CLI works
run: zepter --version && zepter --help
23 changes: 23 additions & 0 deletions .github/workflows/msrv.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: MSRV

on:
push:
branches: [ "master", "dev" ]
pull_request:
branches: [ "master" ]

env:
CARGO_TERM_COLOR: always

jobs:
build:
runs-on: self-hosted

steps:
- uses: actions/checkout@v3
with:
fetch-depth: 1
- name: Install MRRV
run: cargo install cargo-msrv --locked -q
- name: Verify MSRV
run: cargo msrv verify
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ env:

jobs:
build:
runs-on: ubuntu-latest
runs-on: self-hosted

steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
[package]
name = "zepter"
version = "0.6.2"
version = "0.7.0"
edition = "2021"
authors = [ "Oliver Tale-Yazdi" ]
description = "Check if features are correctly propagated in your workspace."
license = "GPL-3.0-only"
repository = "https://github.com/ggwpez/zepter"
rust-version = "1.65"

[[bin]]
name = "zepter"
Expand Down
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# Zepter

[![Rust](https://github.com/ggwpez/zepter/actions/workflows/rust.yml/badge.svg)](https://github.com/ggwpez/zepter/actions/workflows/rust.yml)
[![crates.io](https://img.shields.io/crates/v/zepter.svg)](https://crates.io/crates/zepter)
![MSRV](https://img.shields.io/badge/MSRV-1.65-informational)
[![docs.rs](https://img.shields.io/docsrs/zepter)](https://docs.rs/zepter/latest/zepter)

# Zepter

Analyze and fix feature propagation in your Rust workspace. The goal for this tool is to automatically lint and fix feature propagation in CI runs.
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

Expand Down Expand Up @@ -32,7 +33,7 @@ crate "frame-support"
Found 3 issues and fixed 0 issues.
```

Without the `-p` it will detect many more problems. You can verify this for the [frame-support](https://github.com/paritytech/substrate/blob/ce2cee35f8f0fc5968ea6ffaffa6660dcd008804/frame/support/Cargo.toml#L71) which is indeed missing the feature for `sp-runtime` while that is clearly [sp-runtime](https://github.com/paritytech/substrate/blob/0b6aec52a90870c999856cd37f7d04789cdd8dfc/primitives/runtime/Cargo.toml#L43) it 🤔.
Without the `-p` it will detect many more problems. You can verify this for the [frame-support](https://github.com/paritytech/substrate/blob/ce2cee35f8f0fc5968ea6ffaffa6660dcd008804/frame/support/Cargo.toml#L71) which is indeed missing the feature for `sp-runtime` while [sp-runtime](https://github.com/paritytech/substrate/blob/0b6aec52a90870c999856cd37f7d04789cdd8dfc/primitives/runtime/Cargo.toml#L43) clearly supports it 🤔.

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

Expand All @@ -45,25 +46,25 @@ This can be fixed by appending the `--fix` flag, which results in this diff:
+]
```

The auto-fix always enables the features of optional dependencies as optionally features. This is a noninvasive default, but may not correctly enable the dependency itself.
The auto-fix always enables the features of optional dependencies as optional features. This is a noninvasive default, but may not correctly enable the dependency itself.

## 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:
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` expresses that the precondition never enables the this.
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 that there are multiple.
Only the first path is shown in case there are multiple.

## Example - Dependency tracing

Expand All @@ -75,7 +76,7 @@ Let's find out how `node-cli` depends on `snow` (example on commit `dd6aedee3b8d
zepter trace node-cli snow
```

It reports that `snow` is pulled in from libp2p - good do know. In this case all paths are displayed.
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
Expand All @@ -85,7 +86,7 @@ node-cli -> try-runtime-cli -> substrate-rpc-client -> sc-rpc-api -> sc-chain-sp

- [x] Add feature information to the enabled deps
- [ ] Allow manual skipping of dev dependencies (currently always skipped)
- [ ] Introduce filters for versions and features for argument `to`
- [ ] Introduce filters for versions and features for arguments `to``
- [x] Optimize `shortest_path` function
- [ ] Create lint rules which can be used to validate that certain constraints in the work-space hold

Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[toolchain]
channel = "nightly-2023-05-04"
channel = "nightly-2023-07-24"
components = [ "rustfmt", "clippy" ]
profile = "minimal"
98 changes: 84 additions & 14 deletions src/autofix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ impl AutoFixer {
// line …]`.
let values = feature.iter().cloned().collect::<Vec<_>>();
feature.clear();
feature.set_trailing("");
feature.set_trailing_comma(false); // We need to add this manually later on.

for value in values.into_iter() {
if value.as_str().map_or(false, |s| s.is_empty()) {
Expand All @@ -57,8 +59,8 @@ impl AutoFixer {
panic!("Empty value in feature");
}
let mut value: Value = v.into();
// Working around `feature = []`.
value = value.decorated("\n\t", "\n");
let suffix = if feature.is_empty() { "\n" } else { ",\n" };
value = value.decorated("\n\t", suffix);
feature.push_formatted(value);

Ok(())
Expand All @@ -67,8 +69,8 @@ impl AutoFixer {
pub fn save(&mut self) -> Result<(), String> {
if let (Some(doc), Some(path)) = (self.doc.take(), &self.manifest) {
std::fs::write(path, doc.to_string())
.map_err(|e| format!("Failed to write manifest: {e}"))?;
log::info!("Wrote manifest to {}", path.display());
.map_err(|e| format!("Failed to write manifest: {:?}: {:?}", path.display(), e))?;
log::info!("Modified manifest {:?}", path.display());
}
Ok(())
}
Expand All @@ -83,19 +85,86 @@ impl ToString for AutoFixer {
#[cfg(test)]
mod tests {
use super::*;
use rstest::*;

#[test]
fn add_to_feature_works() {
let before = r#"
#[rstest]
#[case(
r#"
[features]
runtime-benchmarks = ["sp-runtime/runtime-benchmarks"]
"#,
r#"
[features]
runtime-benchmarks = [
"sp-runtime/runtime-benchmarks",
"frame-support/runtime-benchmarks",
]
std = [
"frame-system/std"
]
"#
)]
#[case(
r#"
[features]
runtime-benchmarks = [
"sp-runtime/runtime-benchmarks"
]
"#,
r#"
[features]
runtime-benchmarks = [
"sp-runtime/runtime-benchmarks",
"frame-support/runtime-benchmarks",
]
std = [
"frame-system/std"
]
"#
)]
#[case(
r#"
[features]
runtime-benchmarks = [
"sp-runtime/runtime-benchmarks",
]
"#,
r#"
[features]
runtime-benchmarks = [
"sp-runtime/runtime-benchmarks",
"frame-support/runtime-benchmarks",
]
std = [
"frame-system/std"
]
"#
)]
#[case(
r#"
[features]
runtime-benchmarks = []
"#,
r#"
[features]
runtime-benchmarks = [
"frame-support/runtime-benchmarks"
]
std = [
"frame-system/std"
]
"#
)]
#[case(
r#"
[package]
name = "something"

[features]
runtime-benchmarks = []
std = ["frame-support/std"]
"#;

let after = r#"
"#,
r#"
[package]
name = "something"

Expand All @@ -105,10 +174,11 @@ runtime-benchmarks = [
]
std = [
"frame-support/std",
"frame-system/std"
"frame-system/std",
]
"#;

"#
)]
fn add_to_feature_works(#[case] before: &str, #[case] after: &str) {
let mut fixer = AutoFixer::from_raw(before).unwrap();
fixer
.add_to_feature("runtime-benchmarks", "frame-support/runtime-benchmarks")
Expand All @@ -123,7 +193,7 @@ std = [
let after = r#"[features]
std = [
"AAA",
"BBB"
"BBB",
]
"#;
let mut fixer = AutoFixer::from_raw(before).unwrap();
Expand Down
Loading
Loading