feat(ci): add script to sort cargo deps (#62)

This PR introduces a new script in `./operator/scripts` that allows us
to sort cargo dependencies alphabetically, it is based in my
[gist](https://gist.github.com/gonzamontiel/b4594c62685175f99760442ad2e2dd98).

I modified it so we can run it both in `--fix` and `--check` modes.

To sort a single cargo file, you can do:

```
./scripts/sort-cargo-deps.sh  /path/to/Cargo.toml
```

Btw, make sure you are in the operator folder and you have exec
permissions:

```
cd operator
chmod +x ./scripts/sort-cargo-deps.sh
```
But what I recommend is that you format every Cargo.toml just in case,
like this:
```
find . -name "Cargo.toml" -exec ./scripts/sort-cargo-deps.sh {} \;
```

The CI will run 

```
find . -name "Cargo.toml" -exec ./scripts/sort-cargo-deps.sh {} check \;
```

---------

Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
This commit is contained in:
Gonza Montiel 2025-05-06 19:22:01 +02:00 committed by GitHub
parent 591330f018
commit e16420f266
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 134 additions and 26 deletions

View file

@ -48,7 +48,7 @@ jobs:
fi
cargo-fmt:
needs: [setup]
needs: [ setup ]
if: needs.setup.outputs.node_changed == 'true'
name: "Check format with rustfmt"
runs-on: ubuntu-latest
@ -73,7 +73,7 @@ jobs:
run: cargo fmt --all -- --check
check-rust-lint:
needs: [setup]
needs: [ setup ]
if: needs.setup.outputs.node_changed == 'true'
name: "Check lint with clippy"
runs-on: ubuntu-latest
@ -110,3 +110,20 @@ jobs:
run: SKIP_WASM_BUILD=1 env -u RUSTFLAGS cargo clippy --features try-runtime,runtime-benchmarks --locked
env:
RUSTFLAGS: -D warnings
check-cargo-sort:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ env.WORKING_DIR }}
steps:
- name: Check out the repository to the runner
uses: actions/checkout@v4
- name: Make script executable
run: chmod +x scripts/sort-cargo-deps.sh
- name: Run the script on all Cargo.toml files
run: find . -name "Cargo.toml" -print0 | xargs -0 -n1 -I{} bash -c 'scripts/sort-cargo-deps.sh "{}" check' || exit 1

View file

@ -28,8 +28,8 @@ resolver = "2"
datahaven-runtime = { path = "./runtime", default-features = false }
datahaven-runtime-common = { path = "./runtime/common", default-features = false }
dhp-bridge = { path = "./primitives/bridge", default-features = false }
pallet-validator-set = { path = "./pallets/validator-set", default-features = false }
pallet-outbound-commitment-store = { path = "./pallets/outbound-commitment-store", default-features = false }
pallet-validator-set = { path = "./pallets/validator-set", default-features = false }
# Crates.io (wasm)
alloy-core = { version = "0.8.15", default-features = false }
@ -162,20 +162,20 @@ xcm-executor = { git = "https://github.com/paritytech/polkadot-sdk", branch = "s
# Snowbridge
bp-relayers = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412", default-features = false }
bridge-hub-common = { path = "primitives/snowbridge/bridge-hub-common", default-features = false }
snowbridge-merkle-tree = { path = "primitives/snowbridge/merkle-tree", default-features = false }
snowbridge-pallet-system = { path = "pallets/system", default-features = false }
snowbridge-beacon-primitives = { path = "primitives/snowbridge/beacon", default-features = false }
snowbridge-core = { path = "primitives/snowbridge/core", default-features = false }
snowbridge-ethereum = { path = "primitives/snowbridge/ethereum", default-features = false }
snowbridge-inbound-queue-primitives = { path = "primitives/snowbridge/inbound-queue", default-features = false }
snowbridge-merkle-tree = { path = "primitives/snowbridge/merkle-tree", default-features = false }
snowbridge-outbound-queue-primitives = { path = "primitives/snowbridge/outbound-queue", default-features = false }
snowbridge-outbound-queue-v2-runtime-api = { path = "pallets/outbound-queue-v2/runtime-api", default-features = false }
snowbridge-pallet-ethereum-client = { path = "pallets/ethereum-client", default-features = false }
snowbridge-pallet-ethereum-client-fixtures = { path = "pallets/ethereum-client/fixtures", default-features = false }
snowbridge-pallet-outbound-queue = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412", default-features = false }
snowbridge-pallet-inbound-queue-v2 = { path = "pallets/inbound-queue-v2", default-features = false }
snowbridge-pallet-inbound-queue-v2-fixtures = { path = "pallets/inbound-queue-v2/fixtures", default-features = false }
snowbridge-pallet-outbound-queue = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412", default-features = false }
snowbridge-pallet-outbound-queue-v2 = { path = "pallets/outbound-queue-v2", default-features = false }
snowbridge-pallet-system = { path = "pallets/system", default-features = false }
snowbridge-pallet-system-v2 = { path = "pallets/system-v2", default-features = false }
snowbridge-system-v2-runtime-api = { path = "pallets/system-v2/runtime-api", default-features = false }
snowbridge-test-utils = { path = "primitives/snowbridge/test-utils", default-features = false }

View file

@ -10,9 +10,9 @@ targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
codec = { workspace = true, features = ["derive"] }
scale-info = { workspace = true, features = ["derive"] }
frame-support = { workspace = true }
frame-system = { workspace = true }
scale-info = { workspace = true, features = ["derive"] }
sp-core = { workspace = true }
[features]
@ -31,4 +31,4 @@ try-runtime = [
runtime-benchmarks = [
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
]
]

View file

@ -18,9 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"]
exclude-from-umbrella = true
[dependencies]
codec = { features = [
"derive",
], workspace = true }
codec = { features = ["derive"], workspace = true }
snowbridge-core.workspace = true
sp-api.workspace = true
sp-std.workspace = true
@ -29,9 +27,9 @@ xcm.workspace = true
[features]
default = ["std"]
std = [
"codec/std",
"snowbridge-core/std",
"sp-api/std",
"sp-std/std",
"xcm/std",
"codec/std",
"snowbridge-core/std",
"sp-api/std",
"sp-std/std",
"xcm/std",
]

View file

@ -77,4 +77,4 @@ try-runtime = [
]
[lib]
test = false
test = false

View file

@ -18,9 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"]
exclude-from-umbrella = true
[dependencies]
codec = { features = [
"derive",
], workspace = true }
codec = { features = ["derive"], workspace = true }
snowbridge-core.workspace = true
sp-api.workspace = true
sp-std.workspace = true
@ -29,9 +27,9 @@ xcm.workspace = true
[features]
default = ["std"]
std = [
"codec/std",
"snowbridge-core/std",
"sp-api/std",
"sp-std/std",
"xcm/std",
"codec/std",
"snowbridge-core/std",
"sp-api/std",
"sp-std/std",
"xcm/std",
]

View file

@ -46,6 +46,7 @@ pallet-message-queue = { workspace = true }
pallet-mmr = { workspace = true }
pallet-multisig = { workspace = true }
pallet-offences = { workspace = true }
pallet-outbound-commitment-store = { workspace = true }
pallet-parameters = { workspace = true }
pallet-preimage = { workspace = true }
pallet-scheduler = { workspace = true }
@ -93,7 +94,6 @@ sp-version = { features = ["serde"], workspace = true }
xcm = { workspace = true }
xcm-builder = { workspace = true }
xcm-executor = { workspace = true }
pallet-outbound-commitment-store = { workspace = true }
[build-dependencies]
substrate-wasm-builder = { optional = true, workspace = true, default-features = true }

View file

@ -0,0 +1,95 @@
#!/usr/bin/env bash
set -euo pipefail
# Use first argument as file path, default to Cargo.toml
FILE="${1:-Cargo.toml}"
MODE="${2:-fix}" # "fix" (default) or "check"
# Check if file exists
if [[ ! -f "$FILE" ]]; then
echo "Error: File '$FILE' not found"
exit 1
fi
TMP_FILE="$(mktemp)"
SECTION_REGEX='^\[.*dependencies.*\]$'
process_file() {
local in_section=0
local section_content=""
local current_group=""
local current_comment=""
while IFS= read -r line || [[ -n "$line" ]]; do
# Handle section headers
if [[ "$line" =~ $SECTION_REGEX ]]; then
if [[ -n "$section_content" ]]; then
echo -n "$section_content" | LC_ALL=C sort -f
fi
in_section=1
section_content=""
current_group=""
echo "$line"
continue
fi
# Inside a dependencies section
if [[ $in_section -eq 1 ]]; then
# New section starts
if [[ "$line" =~ ^\[[^]]+\] ]]; then
if [[ -n "$section_content" ]]; then
echo -n "$section_content" | LC_ALL=C sort -f
fi
in_section=0
section_content=""
current_group=""
echo "$line"
# Empty line - flush current group
elif [[ -z "$line" ]]; then
if [[ -n "$section_content" ]]; then
echo -n "$section_content" | LC_ALL=C sort -f
echo
fi
section_content=""
current_group=""
# Comment line - start new group
elif [[ "$line" =~ ^[[:space:]]*# ]]; then
if [[ -n "$section_content" && "$current_group" != "$line" ]]; then
echo -n "$section_content" | LC_ALL=C sort -f
section_content=""
fi
current_group="$line"
section_content="$line"$'\n'
# Dependency line
else
if [[ -z "$current_group" ]]; then
current_group="default"
fi
section_content+="$line"$'\n'
fi
else
echo "$line"
fi
done < "$FILE"
if [[ -n "$section_content" ]]; then
echo -n "$section_content" | LC_ALL=C sort -f
fi
}
process_file > "$TMP_FILE"
if [[ "$MODE" == "check" ]]; then
if ! diff -q "$TMP_FILE" "$FILE" > /dev/null; then
echo "Error: $FILE is not sorted. Please run the script to sort it."
diff "$FILE" "$TMP_FILE"
rm "$TMP_FILE"
exit 1
else
echo "Check passed: $FILE is properly sorted."
rm "$TMP_FILE"
fi
else
mv "$TMP_FILE" "$FILE"
fi