Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

CI check against Rust feature bleed #12341

Merged
merged 25 commits into from
Oct 19, 2022
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion frame/try-runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"]}
frame-support = { version = "4.0.0-dev", default-features = false, features = [ "try-runtime" ], path = "../support" }
frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
sp-api = { version = "4.0.0-dev", default-features = false, path = "../../primitives/api" }
sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" }
sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" }
Expand All @@ -28,3 +28,6 @@ std = [
"sp-runtime/std",
"sp-std/std",
]
try-runtime = [
"frame-support/try-runtime",
]
1 change: 1 addition & 0 deletions frame/try-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
//! Supporting types for try-runtime, testing and dry-running commands.

#![cfg_attr(not(feature = "std"), no_std)]
#![cfg(features = "try-runtime")]

pub use frame_support::traits::TryStateSelect;
use frame_support::weights::Weight;
Expand Down
8 changes: 8 additions & 0 deletions scripts/ci/gitlab/pipeline/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ test-dependency-rules:
script:
- ./scripts/ci/gitlab/ensure-deps.sh

test-rust-features:
stage: check
extends:
- .kubernetes-env
alvicsam marked this conversation as resolved.
Show resolved Hide resolved
- .test-refs-no-trigger-prs-only
script:
- bash ./scripts/ci/gitlab/rust-features.sh .

test-prometheus-alerting-rules:
stage: check
extends: .kubernetes-env
Expand Down
107 changes: 107 additions & 0 deletions scripts/ci/gitlab/rust-features.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/bin/bash

# This file is part of Substrate.
# Copyright (C) 2022 Parity Technologies (UK) Ltd.
# SPDX-License-Identifier: Apache-2.0
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

#######################################################################
#
# This script checks that no crate enables a specific feature in its
# `default` feature set. It's important to check that since features
# are used to gate specific functionality which should only be enabled
# if the feature is present.
#
# Invocation scheme:
# ./rust-features.sh <CARGO-ROOT-PATH>
#
# The steps of this script:
# 1. Check that all required dependencies are installed.
# 2. Check that all rules are fullfilled for the whole workspace. If not:
# 4. Check all crates to find the offending ones.
# 5. Print all offending crates and exit with failure.
#
#######################################################################

set -eu

# Check that cargo, grep and egrep are installed.
command -v cargo >/dev/null 2>&1 || { echo >&2 "cargo is required but not installed. Aborting."; exit 1; }
command -v grep >/dev/null 2>&1 || { echo >&2 "grep is required but not installed. Aborting."; exit 1; }
command -v egrep >/dev/null 2>&1 || { echo >&2 "egrep is required but not installed. Aborting."; exit 1; }

SUBSTRATE_ROOT=$1
declare -a RULES=(
"default,std never implies runtime-benchmarks"
"default,std never implies try-runtime"
)

function check_does_not_imply() {
ENABLED=$1
STAYS_DISABLED=$2
echo "πŸ“ Checking that $ENABLED does not imply $STAYS_DISABLED ..."

RET=0
# Check if the forbidden feature is enabled anywhere in the workspace.
cargo tree --no-default-features --locked --workspace -e features --features "$ENABLED" | grep -q "feature \"$STAYS_DISABLED\"" || RET=$?
if [ $RET -ne 0 ]; then
echo "βœ… $ENABLED does not imply $STAYS_DISABLED in the workspace"
return
else
echo "❌ $ENABLED implies $STAYS_DISABLED in the workspace"
fi

# Find all Cargo.toml files but exclude the root one since we know that it is broken.
CARGOS=`find $SUBSTRATE_ROOT -name Cargo.toml -not -path "$SUBSTRATE_ROOT/Cargo.toml"`
FAILED=0
PASSED=0
# number of all cargos
echo "πŸ” Checking individual crates - this takes some time."

for CARGO in $CARGOS; do
RET=0
OUTPUT=$(cargo tree --no-default-features --locked -e features --features $ENABLED --manifest-path $CARGO 2>&1 || true)
IS_NOT_SUPPORTED=$(echo $OUTPUT | grep -q "not supported for packages in this workspace" || echo $?)

if [ $IS_NOT_SUPPORTED -eq 0 ]; then
# This case just means that the pallet does not support the
# requested feature which is fine.
PASSED=$((PASSED+1))
elif echo "$OUTPUT" | grep -q "feature \"$STAYS_DISABLED\""; then
echo "❌ Violation in $CARGO enabled by dependency"
# Best effort hint for which dependency needs to be fixed.
echo "$OUTPUT" | grep -w "feature \"$STAYS_DISABLED\"" | head -n 1
FAILED=$((FAILED+1))
else
PASSED=$((PASSED+1))
fi
done

TOTAL=$((PASSED + FAILED))
echo "Checked $TOTAL crates in total of which $FAILED failed and $PASSED passed."
echo "Exiting with code 1"
exit 1
}

cd "$SUBSTRATE_ROOT"

for RULE in "${RULES[@]}"; do
read -a splits <<< "$RULE"
ENABLED=${splits[0]}
STAYS_DISABLED=${splits[3]}
# Split ENABLED at , and check each one.
IFS=',' read -ra ENABLED_SPLIT <<< "$ENABLED"
for ENABLED_SPLIT in "${ENABLED_SPLIT[@]}"; do
check_does_not_imply "$ENABLED_SPLIT" "$STAYS_DISABLED"
done
done