diff --git a/.github/scripts/check-each-crate.py b/.github/scripts/check-each-crate.py new file mode 100644 index 0000000000000..7a53e812ddfc7 --- /dev/null +++ b/.github/scripts/check-each-crate.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 + +# A script that checks each workspace crate individually. +# It's relevant to check workspace crates individually because otherwise their compilation problems +# due to feature misconfigurations won't be caught, as exemplified by +# https://github.com/paritytech/substrate/issues/12705 +# +# `check-each-crate.py target_group groups_total` +# +# - `target_group`: Integer starting from 1, the group this script should execute. +# - `groups_total`: Integer starting from 1, total number of groups. +# - `disable_forklift`: Boolean, whether to disable forklift or not. + +import subprocess, sys + +# Get all crates +output = subprocess.check_output(["cargo", "tree", "--locked", "--workspace", "--depth", "0", "--prefix", "none"]) + +# Convert the output into a proper list +crates = [] +for line in output.splitlines(): + if line != b"": + line = line.decode('utf8').split(" ") + crate_name = line[0] + # The crate path is always the last element in the line. + crate_path = line[len(line) - 1].replace("(", "").replace(")", "") + crates.append((crate_name, crate_path)) + +# Make the list unique and sorted +crates = list(set(crates)) +crates.sort() + +target_group = int(sys.argv[1]) - 1 +groups_total = int(sys.argv[2]) +disable_forklift = bool(sys.argv[3] if len(sys.argv) > 3 else False) + +print(f"Target group: {target_group}, Total groups: {groups_total}, Disable forklift: {disable_forklift}", file=sys.stderr) + +if len(crates) == 0: + print("No crates detected!", file=sys.stderr) + sys.exit(1) + +print(f"Total crates: {len(crates)}", file=sys.stderr) + +crates_per_group = len(crates) // groups_total + +# If this is the last runner, we need to take care of crates +# after the group that we lost because of the integer division. +if target_group + 1 == groups_total: + overflow_crates = len(crates) % groups_total +else: + overflow_crates = 0 + +print(f"Crates per group: {crates_per_group}", file=sys.stderr) + +# Check each crate +for i in range(0, crates_per_group + overflow_crates): + crate = crates_per_group * target_group + i + + print(f"Checking {crates[crate][0]}", file=sys.stderr) + + cmd = ["cargo", "check", "--locked"] + + cmd.insert(0, 'forklift') if not disable_forklift else None + + res = subprocess.run(cmd, cwd = crates[crate][1]) + + if res.returncode != 0: + sys.exit(1) diff --git a/.github/workflows/check-cargo-check-runtimes.yml b/.github/workflows/check-cargo-check-runtimes.yml index 322dfdb2ed9d9..c742d60629d80 100644 --- a/.github/workflows/check-cargo-check-runtimes.yml +++ b/.github/workflows/check-cargo-check-runtimes.yml @@ -131,6 +131,10 @@ jobs: # TODO: remove once migration is complete or this workflow is fully stable if: contains(github.event.label.name, 'GHA-migration') || contains(github.event.pull_request.labels.*.name, 'GHA-migration') runs-on: macOS + strategy: + fail-fast: false + matrix: + index: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] steps: - uses: actions/checkout@v4 - run: brew install protobuf rustup @@ -143,7 +147,10 @@ jobs: - name: Free space run: brew cleanup - name: Run cargo check - run: source $HOME/.cargo/env && time cargo check --workspace --locked + run: | + source $HOME/.cargo/env + PYTHONUNBUFFERED=x .github/scripts/check-each-crate.py ${{ matrix.index }} ${{ strategy.job-total }} + # time cargo check --workspace --locked confirm-required-jobs-passed: runs-on: ubuntu-latest