diff --git a/.github/actions/set-up-gh/action.yml b/.github/actions/set-up-gh/action.yml new file mode 100644 index 000000000000..db6bfbd5008f --- /dev/null +++ b/.github/actions/set-up-gh/action.yml @@ -0,0 +1,36 @@ +name: 'install gh' +description: 'Install the gh cli in a debian based distro and switches to the PR branch.' +inputs: + pr-number: + description: "Number of the PR" + required: true + GH_TOKEN: + description: "GitHub token" + required: true +outputs: + branch: + description: 'Branch name for the PR' + value: ${{ steps.branch.outputs.branch }} +runs: + using: "composite" + steps: + - name: Instal gh cli + shell: bash + # Here it would get the script from previous step + run: | + (type -p wget >/dev/null || (apt update && apt-get install wget -y)) \ + && mkdir -p -m 755 /etc/apt/keyrings \ + && wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \ + && chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null \ + && apt update \ + && apt install gh -y + git config --global --add safe.directory '*' + - run: gh pr checkout ${{ inputs.pr-number }} + shell: bash + env: + GITHUB_TOKEN: ${{ inputs.GH_TOKEN }} + - name: Export branch name + shell: bash + run: echo "branch=$(git rev-parse --abbrev-ref HEAD)" >> "$GITHUB_OUTPUT" + id: branch diff --git a/.github/commands/example/example.yml b/.github/commands/example/example.yml new file mode 100644 index 000000000000..e434b5b5585d --- /dev/null +++ b/.github/commands/example/example.yml @@ -0,0 +1,3 @@ +name: example +description: This command is just used for examples +commandStart: 'echo "Hello World!"' diff --git a/.github/commands/print/print.yml b/.github/commands/print/print.yml new file mode 100644 index 000000000000..c57272d755e4 --- /dev/null +++ b/.github/commands/print/print.yml @@ -0,0 +1,3 @@ +name: print +description: This command is used to create a file +commandStart: "touch file.txt" diff --git a/.github/workflows/cmd-action.yml b/.github/workflows/cmd-action.yml new file mode 100644 index 000000000000..5797aca892af --- /dev/null +++ b/.github/workflows/cmd-action.yml @@ -0,0 +1,68 @@ +name: Command-Action + +on: + pull_request: + issue_comment: + types: [created] + +jobs: + cmd-check: + runs-on: ubuntu-latest + outputs: + commands: ${{ steps.cmd.outputs.commands }} + branch: ${{ steps.branch.outputs.branch }} + name: Bot + steps: + - uses: actions/checkout@v4 + - run: gh pr checkout ${{ github.event.issue.number || github.event.pull_request.number }} + env: + GITHUB_TOKEN: ${{ github.token }} + - uses: paritytech/cmd-action@parse-comment + id: cmd + with: + commands-directory: ".github/commands" + GITHUB_TOKEN: ${{ github.token }} + - name: Export branch name + run: echo "branch=$(git rev-parse --abbrev-ref HEAD)" >> "$GITHUB_OUTPUT" + id: branch + - name: Print commands + if: ${{ github.event.issue.pull_request }} + run: echo "Commands are $CMD" + env: + CMD: ${{ steps.cmd.outputs.commands }} + + cmd: + needs: [cmd-check] + continue-on-error: true + # We set the current machine here (to differ between ours and generic ones) + runs-on: ubuntu-latest + strategy: + matrix: + command: ${{ fromJson(needs.cmd-check.outputs.commands) }} + container: + image: node:20 + steps: + - name: Download repo + uses: actions/checkout@v4.1.1 + with: + ref: ${{ needs.cmd-check.outputs.branch }} + - name: Generate script + # Here it would get the script from previous step + run: bash -c $COMMAND + env: + COMMAND: ${{ matrix.command }} + - name: Report failure + if: ${{ failure() }} + run: echo "Command failed!" + - run: git status + # - uses: stefanzweifel/git-auto-commit-action@v5 + # - name: Push changes + # run: | + # git config --global --add safe.directory /__w/cmd-action/cmd-action + # git config --system user.name command-bot + # git config --system user.email "github@users.noreply.github.com" + # git add . + # git commit -m "changes" + # git push origin $BRANCH + # env: + # BRANCH: ${{ github.head_ref || github.ref_name }} diff --git a/.github/workflows/command-bench-all.yml b/.github/workflows/command-bench-all.yml new file mode 100644 index 000000000000..6a564301fe36 --- /dev/null +++ b/.github/workflows/command-bench-all.yml @@ -0,0 +1,97 @@ +name: Command Bench All + +on: + workflow_dispatch: + inputs: + pr: + description: Number of the Pull Request + required: true + benchmark: + description: Pallet benchmark + type: choice + required: true + options: + - pallet + - substrate + - polkadot + - cumulus + pallet: + description: Pallet + required: false + type: string + default: pallet_name + target_dir: + description: Target directory + type: choice + options: + - substrate + - polkadot + - cumulus + runtime: + description: Runtime + type: choice + options: + - rococo + - westend + - asset-hub-kusama + - asset-hub-polkadot + - asset-hub-rococo + - asset-hub-westend + - bridge-hub-kusama + - bridge-hub-polkadot + - bridge-hub-rococo + - bridge-hub-westend + - collectives-polkadot + - collectives-westend + - coretime-rococo + - coretime-westend + - contracts-rococo + - glutton-kusama + - glutton-westend + - people-rococo + - people-westend + + +jobs: + set-image: + runs-on: ubuntu-latest + outputs: + IMAGE: ${{ steps.set_image.outputs.IMAGE }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - id: set_image + run: cat .github/env >> $GITHUB_OUTPUT + cmd-bench-all: + needs: [set-image] + runs-on: ubuntu-latest + container: + image: ${{ needs.set-image.outputs.IMAGE }} + steps: + - name: Download repo + uses: actions/checkout@v4 + - name: Install gh cli + id: gh + uses: ./.github/actions/set-up-gh + with: + pr-number: ${{ inputs.pr }} + GH_TOKEN: ${{ github.token }} + - name: Run bench + run: | + "./scripts/bench-all.sh" "${{ inputs.benchmark }}" --runtime "${{ inputs.runtime }}" --pallet "${{ inputs.pallet }}" --target_dir "${{ inputs.target_dir }}" + - name: Report failure + if: ${{ failure() }} + run: gh pr comment ${{ inputs.pr }} --body "
${{ github.workflow }}
failed. See logs here."
+ env:
+ RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
+ GH_TOKEN: ${{ github.token }}
+ - run: git pull --rebase
+ - uses: stefanzweifel/git-auto-commit-action@v5
+ with:
+ commit_message: cmd-action - ${{ github.workflow }}
+ branch: ${{ steps.gh.outputs.branch }}
+ - name: Report succeed
+ run: gh pr comment ${{ inputs.pr }} --body "${{ github.workflow }}
completed 🎉. See logs here."
+ env:
+ RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
+ GH_TOKEN: ${{ github.token }}
diff --git a/.github/workflows/command-bench.yml b/.github/workflows/command-bench.yml
new file mode 100644
index 000000000000..b4317f92d6e7
--- /dev/null
+++ b/.github/workflows/command-bench.yml
@@ -0,0 +1,122 @@
+name: Command Bench
+
+on:
+ workflow_dispatch:
+ inputs:
+ pr:
+ description: Number of the Pull Request
+ required: true
+ benchmark:
+ description: Pallet benchmark
+ type: choice
+ required: true
+ options:
+ - substrate-pallet
+ - polkadot-pallet
+ - cumulus-assets
+ - cumulus-collectives
+ - cumulus-coretime
+ - cumulus-bridge-hubs
+ - cumulus-contracts
+ - cumulus-glutton
+ - cumulus-starters
+ - cumulus-people
+ - cumulus-testing
+ subcommand:
+ description: Subcommand
+ type: choice
+ required: true
+ options:
+ - pallet
+ - xcm
+ runtime:
+ description: Runtime
+ type: choice
+ options:
+ - dev
+ - rococo
+ - westend
+ - asset-hub-westend
+ - asset-hub-rococo
+ - collectives-westend
+ - coretime-rococo
+ - coretime-westend
+ - bridge-hub-rococo
+ - bridge-hub-westend
+ - contracts-rococo
+ - glutton-westend
+ - glutton-westend-dev-1300
+ - seedling
+ - shell
+ - people-westend
+ - people-rococo
+ - penpal
+ - rococo-parachain
+ pallet:
+ description: Pallet
+ type: string
+ default: pallet_name
+ target_dir:
+ description: Target directory
+ type: choice
+ options:
+ - substrate
+ - polkadot
+ - cumulus
+ runtime_dir:
+ description: Runtime directory
+ type: choice
+ options:
+ - people
+ - collectives
+ - coretime
+ - bridge-hubs
+ - contracts
+ - glutton
+ - starters
+ - testing
+
+
+jobs:
+ set-image:
+ runs-on: ubuntu-latest
+ outputs:
+ IMAGE: ${{ steps.set_image.outputs.IMAGE }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - id: set_image
+ run: cat .github/env >> $GITHUB_OUTPUT
+ cmd-bench:
+ needs: [set-image]
+ runs-on: ubuntu-latest
+ container:
+ image: ${{ needs.set-image.outputs.IMAGE }}
+ steps:
+ - name: Download repo
+ uses: actions/checkout@v4
+ - name: Install gh cli
+ id: gh
+ uses: ./.github/actions/set-up-gh
+ with:
+ pr-number: ${{ inputs.pr }}
+ GH_TOKEN: ${{ github.token }}
+ - name: Run bench
+ run: |
+ "./scripts/bench.sh" "${{ inputs.benchmark }}" --runtime "${{ inputs.runtime }}" --pallet "${{ inputs.pallet }}" --target_dir "${{ inputs.target_dir }}" --subcommand "${{ inputs.subcommand }}" --runtime_dir "${{ inputs.runtime_dir }}"
+ - name: Report failure
+ if: ${{ failure() }}
+ run: gh pr comment ${{ inputs.pr }} --body "${{ github.workflow }}
failed. See logs here."
+ env:
+ RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
+ GH_TOKEN: ${{ github.token }}
+ - run: git pull --rebase
+ - uses: stefanzweifel/git-auto-commit-action@v5
+ with:
+ commit_message: cmd-action - ${{ github.workflow }}
+ branch: ${{ steps.gh.outputs.branch }}
+ - name: Report succeed
+ run: gh pr comment ${{ inputs.pr }} --body "${{ github.workflow }}
completed 🎉. See logs here."
+ env:
+ RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
+ GH_TOKEN: ${{ github.token }}
diff --git a/.github/workflows/command-fmt.yml b/.github/workflows/command-fmt.yml
new file mode 100644
index 000000000000..d415007d9383
--- /dev/null
+++ b/.github/workflows/command-fmt.yml
@@ -0,0 +1,54 @@
+name: Command FMT
+
+on:
+ workflow_dispatch:
+ inputs:
+ pr:
+ description: Number of the Pull Request
+ required: true
+
+jobs:
+ set-image:
+ runs-on: ubuntu-latest
+ outputs:
+ IMAGE: ${{ steps.set_image.outputs.IMAGE }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - id: set_image
+ run: cat .github/env >> $GITHUB_OUTPUT
+ cmd-fmt:
+ needs: [set-image]
+ runs-on: ubuntu-latest
+ container:
+ image: ${{ needs.set-image.outputs.IMAGE }}
+ steps:
+ - name: Download repo
+ uses: actions/checkout@v4
+ - name: Install gh cli
+ id: gh
+ uses: ./.github/actions/set-up-gh
+ with:
+ pr-number: ${{ inputs.pr }}
+ GH_TOKEN: ${{ github.token }}
+ - name: Run FMT
+ run: |
+ # format toml.
+ # since paritytech/ci-unified:bullseye-1.73.0-2023-11-01-v20231204 includes taplo-cli
+ taplo format --config .config/taplo.toml
+ - name: Report failure
+ if: ${{ failure() }}
+ run: gh pr comment ${{ inputs.pr }} --body "${{ github.workflow }}
failed. See logs here."
+ env:
+ RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
+ GH_TOKEN: ${{ github.token }}
+ - run: git pull --rebase
+ - uses: stefanzweifel/git-auto-commit-action@v5
+ with:
+ commit_message: cmd-action - ${{ github.workflow }}
+ branch: ${{ steps.gh.outputs.branch }}
+ - name: Report succeed
+ run: gh pr comment ${{ inputs.pr }} --body "${{ github.workflow }}
completed 🎉. See logs here."
+ env:
+ RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
+ GH_TOKEN: ${{ github.token }}
diff --git a/.github/workflows/command-sync.yml b/.github/workflows/command-sync.yml
new file mode 100644
index 000000000000..b51a2e584b4b
--- /dev/null
+++ b/.github/workflows/command-sync.yml
@@ -0,0 +1,68 @@
+name: Command Sync
+
+on:
+ workflow_dispatch:
+ inputs:
+ pr:
+ description: Number of the Pull Request
+ required: true
+ chain:
+ description: Chain
+ type: choice
+ required: true
+ options:
+ - westend
+ - rococo
+ sync-type:
+ description: Sync type
+ type: choice
+ required: true
+ options:
+ - warp
+ - full
+ - fast
+ - fast-unsafe
+
+jobs:
+ set-image:
+ runs-on: ubuntu-latest
+ outputs:
+ IMAGE: ${{ steps.set_image.outputs.IMAGE }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - id: set_image
+ run: cat .github/env >> $GITHUB_OUTPUT
+ cmd-sync:
+ needs: [set-image]
+ runs-on: ubuntu-latest
+ container:
+ image: ${{ needs.set-image.outputs.IMAGE }}
+ steps:
+ - name: Download repo
+ uses: actions/checkout@v4
+ - name: Install gh cli
+ id: gh
+ uses: ./.github/actions/set-up-gh
+ with:
+ pr-number: ${{ inputs.pr }}
+ GH_TOKEN: ${{ github.token }}
+ - name: Run sync
+ run: |
+ "./scripts/sync.sh" --chain "${{ inputs.chain }}" --type "${{ inputs.sync-type }}"
+ - name: Report failure
+ if: ${{ failure() }}
+ run: gh pr comment ${{ inputs.pr }} --body "${{ github.workflow }}
failed. See logs here."
+ env:
+ RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
+ GH_TOKEN: ${{ github.token }}
+ - run: git pull --rebase
+ - uses: stefanzweifel/git-auto-commit-action@v5
+ with:
+ commit_message: cmd-action - ${{ github.workflow }}
+ branch: ${{ steps.gh.outputs.branch }}
+ - name: Report succeed
+ run: gh pr comment ${{ inputs.pr }} --body "${{ github.workflow }}
completed 🎉. See logs here."
+ env:
+ RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
+ GH_TOKEN: ${{ github.token }}
diff --git a/.github/workflows/command-update-ui.yml b/.github/workflows/command-update-ui.yml
new file mode 100644
index 000000000000..60db225e980d
--- /dev/null
+++ b/.github/workflows/command-update-ui.yml
@@ -0,0 +1,55 @@
+name: Command Update UI
+
+on:
+ workflow_dispatch:
+ inputs:
+ pr:
+ description: Number of the Pull Request
+ required: true
+ rust-version:
+ description: Version of rust. Example 1.70
+ required: false
+
+jobs:
+ set-image:
+ runs-on: ubuntu-latest
+ outputs:
+ IMAGE: ${{ steps.set_image.outputs.IMAGE }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - id: set_image
+ run: cat .github/env >> $GITHUB_OUTPUT
+ cmd-update-ui:
+ needs: [set-image]
+ runs-on: ubuntu-latest
+ container:
+ image: ${{ needs.set-image.outputs.IMAGE }}
+ steps:
+ - name: Download repo
+ uses: actions/checkout@v4
+ - name: Install gh cli
+ id: gh
+ uses: ./.github/actions/set-up-gh
+ with:
+ pr-number: ${{ inputs.pr }}
+ GH_TOKEN: ${{ github.token }}
+ - name: Run update-ui
+ run: |
+ "./scripts/update-ui-tests.sh" "${{ inputs.rust-version }}"
+ - name: Report failure
+ if: ${{ failure() }}
+ run: gh pr comment ${{ inputs.pr }} --body "${{ github.workflow }}
failed. See logs here."
+ env:
+ RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
+ GH_TOKEN: ${{ github.token }}
+ - run: git pull --rebase
+ - uses: stefanzweifel/git-auto-commit-action@v5
+ with:
+ commit_message: cmd-action - ${{ github.workflow }}
+ branch: ${{ steps.gh.outputs.branch }}
+ - name: Report succeed
+ run: gh pr comment ${{ inputs.pr }} --body "${{ github.workflow }}
completed 🎉. See logs here."
+ env:
+ RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
+ GH_TOKEN: ${{ github.token }}
diff --git a/file.txt b/file.txt
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/scripts/bench-all.sh b/scripts/bench-all.sh
new file mode 100755
index 000000000000..e5512e26bbad
--- /dev/null
+++ b/scripts/bench-all.sh
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+
+set -eu -o pipefail
+shopt -s inherit_errexit
+shopt -s globstar
+
+. "$(realpath "$(dirname "${BASH_SOURCE[0]}")/command-utils.sh")"
+
+get_arg optional --pallet "$@"
+PALLET="${out:-""}"
+
+if [[ ! -z "$PALLET" ]]; then
+ . "$(dirname "${BASH_SOURCE[0]}")/lib/bench-all-pallet.sh" "$@"
+else
+ . "$(dirname "${BASH_SOURCE[0]}")/bench.sh" --subcommand=all "$@"
+fi
diff --git a/scripts/bench.sh b/scripts/bench.sh
new file mode 100755
index 000000000000..2f4ef7ec6a14
--- /dev/null
+++ b/scripts/bench.sh
@@ -0,0 +1,117 @@
+#!/bin/bash
+# Initially based on https://github.com/paritytech/bench-bot/blob/cd3b2943d911ae29e41fe6204788ef99c19412c3/bench.js
+
+# Most external variables used in this script, such as $GH_CONTRIBUTOR, are
+# related to https://github.com/paritytech/try-runtime-bot
+
+# This script relies on $GITHUB_TOKEN which is probably a protected GitLab CI
+# variable; if this assumption holds true, it is implied that this script should
+# be ran only on protected pipelines
+
+set -eu -o pipefail
+shopt -s inherit_errexit
+
+# realpath allows to reuse the current
+BENCH_ROOT_DIR=$(realpath "$(dirname "${BASH_SOURCE[0]}")")
+
+. "$(realpath "$(dirname "${BASH_SOURCE[0]}")/command-utils.sh")"
+
+repository_name="$(basename "$PWD")"
+
+get_arg optional --target_dir "$@"
+target_dir="${out:-""}"
+
+get_arg optional --noexit "$@"
+noexit="${out:-""}"
+
+output_path="."
+
+profile="production"
+
+if [[ "$repository_name" == "polkadot-sdk" ]]; then
+ output_path="./$target_dir"
+fi
+
+cargo_run_benchmarks="cargo run --quiet --profile=${profile}"
+
+echo "Repository: $repository_name"
+echo "Target Dir: $target_dir"
+echo "Output Path: $output_path"
+
+cargo_run() {
+ echo "Running $cargo_run_benchmarks" "${args[@]}"
+
+ # if not patched with PATCH_something=123 then use --locked
+ if [[ -z "${BENCH_PATCHED:-}" ]]; then
+ cargo_run_benchmarks+=" --locked"
+ fi
+
+ $cargo_run_benchmarks "${args[@]}"
+}
+
+
+main() {
+
+ # Remove the "github" remote since the same repository might be reused by a
+ # GitLab runner, therefore the remote might already exist from a previous run
+ # in case it was not cleaned up properly for some reason
+ &>/dev/null git remote remove github || :
+
+ tmp_dirs=()
+ cleanup() {
+ exit_code=$?
+ # Clean up the "github" remote at the end since it contains the
+ # $GITHUB_TOKEN secret, which is only available for protected pipelines on
+ # GitLab
+ &>/dev/null git remote remove github || :
+ rm -rf "${tmp_dirs[@]}"
+ echo "Done, exit: $exit_code"
+ exit $exit_code
+ }
+
+ # avoid exit if --noexit is passed
+ if [ -z "$noexit" ]; then
+ trap cleanup EXIT
+ fi
+
+ # set -x
+
+ get_arg required --subcommand "$@"
+ local subcommand="${out:-""}"
+
+ case "$subcommand" in
+ runtime|pallet|xcm)
+ echo 'Running bench_pallet'
+ . "$BENCH_ROOT_DIR/lib/bench-pallet.sh" "$@"
+ ;;
+ overhead)
+ echo 'Running bench_overhead'
+ . "$BENCH_ROOT_DIR/lib/bench-overhead.sh" "$@"
+ ;;
+ all)
+ echo "Running all-$target_dir"
+ . "$BENCH_ROOT_DIR/lib/bench-all-${target_dir}.sh" "$@"
+ ;;
+ *)
+ die "Invalid subcommand $subcommand to process_args"
+ ;;
+ esac
+
+ # set +x
+
+ # in case we used diener to patch some dependency during benchmark execution,
+ # revert the patches so that they're not included in the diff
+ git checkout --quiet HEAD Cargo.toml
+
+ # Save the generated weights to GitLab artifacts in case commit+push fails
+ echo "Showing weights diff for command"
+ git diff -P | tee -a "${ARTIFACTS_DIR}/weights.patch"
+ echo "Wrote weights patch to \"${ARTIFACTS_DIR}/weights.patch\""
+
+
+ # instead of using `cargo run --locked`, we allow the Cargo files to be updated
+ # but avoid committing them. It is so `cmd_runner_apply_patches` can work
+ git restore --staged Cargo.*
+}
+
+main "$@"
diff --git a/scripts/command-utils.sh b/scripts/command-utils.sh
new file mode 100644
index 000000000000..252e4c86480e
--- /dev/null
+++ b/scripts/command-utils.sh
@@ -0,0 +1,80 @@
+#!/usr/bin/env bash
+
+if [ "${LOADED_UTILS_SH:-}" ]; then
+ return
+else
+ export LOADED_UTILS_SH=true
+fi
+
+export ARTIFACTS_DIR="$PWD/.git/.artifacts"
+
+die() {
+ if [ "${1:-}" ]; then
+ >&2 echo "$1"
+ fi
+ exit 1
+}
+
+get_arg() {
+ local arg_type="$1"
+ shift
+
+ local is_required
+ case "$arg_type" in
+ required|required-many)
+ is_required=true
+ ;;
+ optional|optional-many) ;;
+ *)
+ die "Invalid is_required argument \"$2\" in get_arg"
+ ;;
+ esac
+
+ local has_many_values
+ if [ "${arg_type: -6}" == "-many" ]; then
+ has_many_values=true
+ fi
+
+ local option_arg="$1"
+ shift
+
+ local args=("$@")
+
+ unset out
+ out=()
+
+ local get_next_arg
+ for arg in "${args[@]}"; do
+ if [ "${get_next_arg:-}" ]; then
+ out+=("$arg")
+ unset get_next_arg
+ if [ ! "${has_many_values:-}" ]; then
+ break
+ fi
+ # --foo=bar (get the value after '=')
+ elif [ "${arg:0:$(( ${#option_arg} + 1 ))}" == "$option_arg=" ]; then
+ out+=("${arg:$(( ${#option_arg} + 1 ))}")
+ if [ ! "${has_many_values:-}" ]; then
+ break
+ fi
+ # --foo bar (get the next argument)
+ elif [ "$arg" == "$option_arg" ]; then
+ get_next_arg=true
+ fi
+ done
+
+ # arg list ended with --something but no argument was provided next
+ if [ "${get_next_arg:-}" ]; then
+ die "Expected argument after \"${args[-1]}"\"
+ fi
+
+ if [ "${out[0]:-}" ]; then
+ if [ ! "${has_many_values:-}" ]; then
+ out="${out[0]}"
+ fi
+ elif [ "${is_required:-}" ]; then
+ die "Argument $option_arg is required, but was not found"
+ else
+ unset out
+ fi
+}
diff --git a/scripts/lib/bench-all-cumulus.sh b/scripts/lib/bench-all-cumulus.sh
new file mode 100755
index 000000000000..f4c2a35c6b6b
--- /dev/null
+++ b/scripts/lib/bench-all-cumulus.sh
@@ -0,0 +1,139 @@
+#!/usr/bin/env bash
+# originally moved from https://github.com/paritytech/cumulus/blob/445f9277ab55b4d930ced4fbbb38d27c617c6658/scripts/benchmarks-ci.sh
+
+# default RUST_LOG is warn, but could be overridden
+export RUST_LOG="${RUST_LOG:-error}"
+
+THIS_DIR=$(dirname "${BASH_SOURCE[0]}")
+. "$THIS_DIR/../command-utils.sh"
+
+POLKADOT_PARACHAIN="./target/$profile/polkadot-parachain"
+
+run_cumulus_bench() {
+ local artifactsDir="$ARTIFACTS_DIR"
+ local category=$1
+ local runtimeName=$2
+ local paraId=${3:-}
+
+ local benchmarkOutput="$output_path/parachains/runtimes/$category/$runtimeName/src/weights"
+ local benchmarkRuntimeChain
+ if [[ ! -z "$paraId" ]]; then
+ benchmarkRuntimeChain="${runtimeName}-dev-$paraId"
+ else
+ benchmarkRuntimeChain="$runtimeName-dev"
+ fi
+
+ local benchmarkMetadataOutputDir="$artifactsDir/$runtimeName"
+ mkdir -p "$benchmarkMetadataOutputDir"
+
+ # Load all pallet names in an array.
+ echo "[+] Listing pallets for runtime $runtimeName for chain: $benchmarkRuntimeChain ..."
+ local pallets=($(
+ $POLKADOT_PARACHAIN benchmark pallet --list --chain="${benchmarkRuntimeChain}" |\
+ tail -n+2 |\
+ cut -d',' -f1 |\
+ sort |\
+ uniq
+ ))
+
+ if [ ${#pallets[@]} -ne 0 ]; then
+ echo "[+] Benchmarking ${#pallets[@]} pallets for runtime $runtimeName for chain: $benchmarkRuntimeChain, pallets:"
+ for pallet in "${pallets[@]}"; do
+ echo " [+] $pallet"
+ done
+ else
+ echo "$runtimeName pallet list not found in benchmarks-ci.sh"
+ exit 1
+ fi
+
+ for pallet in "${pallets[@]}"; do
+ # (by default) do not choose output_file, like `pallet_assets.rs` because it does not work for multiple instances
+ # `benchmark pallet` command will decide the output_file name if there are multiple instances
+ local output_file=""
+ local extra_args=""
+ # a little hack for pallet_xcm_benchmarks - we want to force custom implementation for XcmWeightInfo
+ if [[ "$pallet" == "pallet_xcm_benchmarks::generic" ]] || [[ "$pallet" == "pallet_xcm_benchmarks::fungible" ]]; then
+ output_file="xcm/${pallet//::/_}.rs"
+ extra_args="--template=$output_path/templates/xcm-bench-template.hbs"
+ fi
+ $POLKADOT_PARACHAIN benchmark pallet \
+ $extra_args \
+ --chain="${benchmarkRuntimeChain}" \
+ --wasm-execution=compiled \
+ --pallet="$pallet" \
+ --no-storage-info \
+ --no-median-slopes \
+ --no-min-squares \
+ --extrinsic='*' \
+ --steps=50 \
+ --repeat=20 \
+ --json \
+ --header="$output_path/file_header.txt" \
+ --output="${benchmarkOutput}/${output_file}" >> "$benchmarkMetadataOutputDir/${pallet//::/_}_benchmark.json"
+ done
+}
+
+
+echo "[+] Compiling benchmarks..."
+cargo build --profile $profile --locked --features=runtime-benchmarks -p polkadot-parachain-bin
+
+# Run benchmarks for all pallets of a given runtime if runtime argument provided
+get_arg optional --runtime "$@"
+runtime="${out:-""}"
+
+if [[ $runtime ]]; then
+ paraId=""
+ case "$runtime" in
+ asset-*)
+ category="assets"
+ ;;
+ collectives-*)
+ category="collectives"
+ ;;
+ coretime-*)
+ category="coretime"
+ ;;
+ bridge-*)
+ category="bridge-hubs"
+ ;;
+ contracts-*)
+ category="contracts"
+ ;;
+ people-*)
+ category="people"
+ ;;
+ glutton-*)
+ category="glutton"
+ paraId="1300"
+ ;;
+ *)
+ echo "Unknown runtime: $runtime"
+ exit 1
+ ;;
+ esac
+
+ run_cumulus_bench $category $runtime $paraId
+
+else # run all
+ # Assets
+ run_cumulus_bench assets asset-hub-rococo
+ run_cumulus_bench assets asset-hub-westend
+
+ # Collectives
+ run_cumulus_bench collectives collectives-westend
+
+ # Coretime
+ run_cumulus_bench coretime coretime-rococo
+ run_cumulus_bench coretime coretime-westend
+
+ # People
+ run_cumulus_bench people people-rococo
+ run_cumulus_bench people people-westend
+
+ # Bridge Hubs
+ run_cumulus_bench bridge-hubs bridge-hub-rococo
+ run_cumulus_bench bridge-hubs bridge-hub-westend
+
+ # Glutton
+ run_cumulus_bench glutton glutton-westend 1300
+fi
diff --git a/scripts/lib/bench-all-pallet.sh b/scripts/lib/bench-all-pallet.sh
new file mode 100644
index 000000000000..e6908045ddbd
--- /dev/null
+++ b/scripts/lib/bench-all-pallet.sh
@@ -0,0 +1,96 @@
+#!/usr/bin/env bash
+
+set -eu -o pipefail
+shopt -s inherit_errexit
+shopt -s globstar
+
+. "$(dirname "${BASH_SOURCE[0]}")/../command-utils.sh"
+
+get_arg required --pallet "$@"
+PALLET="${out:-""}"
+
+REPO_NAME="$(basename "$PWD")"
+BASE_COMMAND="$(dirname "${BASH_SOURCE[0]}")/../../bench/bench.sh --noexit=true --subcommand=pallet"
+
+WEIGHT_FILE_PATHS=( $(find . -type f -name "${PALLET}.rs" -path "**/weights/*" | sed 's|^\./||g') )
+
+# convert pallet_ranked_collective to ranked-collective
+CLEAN_PALLET=$(echo $PALLET | sed 's/pallet_//g' | sed 's/_/-/g')
+
+# add substrate pallet weights to a list
+SUBSTRATE_PALLET_PATH=$(ls substrate/frame/$CLEAN_PALLET/src/weights.rs || :)
+if [ ! -z "${SUBSTRATE_PALLET_PATH}" ]; then
+ WEIGHT_FILE_PATHS+=("$SUBSTRATE_PALLET_PATH")
+fi
+
+# add trappist pallet weights to a list
+TRAPPIST_PALLET_PATH=$(ls pallet/$CLEAN_PALLET/src/weights.rs || :)
+if [ ! -z "${TRAPPIST_PALLET_PATH}" ]; then
+ WEIGHT_FILE_PATHS+=("$TRAPPIST_PALLET_PATH")
+fi
+
+COMMANDS=()
+
+if [ "${#WEIGHT_FILE_PATHS[@]}" -eq 0 ]; then
+ echo "No weights files found for pallet: $PALLET"
+ exit 1
+else
+ echo "Found weights files for pallet: $PALLET"
+fi
+
+for f in ${WEIGHT_FILE_PATHS[@]}; do
+ echo "- $f"
+ # f examples:
+ # cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_balances.rs
+ # polkadot/runtime/rococo/src/weights/pallet_balances.rs
+ # runtime/trappist/src/weights/pallet_assets.rs
+ TARGET_DIR=$(echo $f | cut -d'/' -f 1)
+
+ if [ "$REPO_NAME" == "polkadot-sdk" ]; then
+ case $TARGET_DIR in
+ cumulus)
+ TYPE=$(echo $f | cut -d'/' -f 2)
+ # Example: cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_balances.rs
+ if [ "$TYPE" == "parachains" ]; then
+ RUNTIME=$(echo $f | cut -d'/' -f 5)
+ RUNTIME_DIR=$(echo $f | cut -d'/' -f 4)
+ COMMANDS+=("$BASE_COMMAND --runtime=$RUNTIME --runtime_dir=$RUNTIME_DIR --target_dir=$TARGET_DIR --pallet=$PALLET")
+ fi
+ ;;
+ polkadot)
+ # Example: polkadot/runtime/rococo/src/weights/pallet_balances.rs
+ RUNTIME=$(echo $f | cut -d'/' -f 3)
+ COMMANDS+=("$BASE_COMMAND --runtime=$RUNTIME --target_dir=$TARGET_DIR --pallet=$PALLET")
+ ;;
+ substrate)
+ # Example: substrate/frame/contracts/src/weights.rs
+ COMMANDS+=("$BASE_COMMAND --target_dir=$TARGET_DIR --runtime=dev --pallet=$PALLET")
+ ;;
+ *)
+ echo "Unknown dir: $TARGET_DIR"
+ exit 1
+ ;;
+ esac
+ fi
+
+ if [ "$REPO_NAME" == "trappist" ]; then
+ case $TARGET_DIR in
+ runtime)
+ TYPE=$(echo $f | cut -d'/' -f 2)
+ if [ "$TYPE" == "trappist" || "$TYPE" == "stout" ]; then
+ # Example: runtime/trappist/src/weights/pallet_assets.rs
+ COMMANDS+=("$BASE_COMMAND --target_dir=trappist --runtime=$TYPE --pallet=$PALLET")
+ fi
+ ;;
+ *)
+ echo "Unknown dir: $TARGET_DIR"
+ exit 1
+ ;;
+ esac
+ fi
+done
+
+for cmd in "${COMMANDS[@]}"; do
+ echo "Running command: $cmd"
+ . $cmd
+done
diff --git a/scripts/lib/bench-all-polkadot.sh b/scripts/lib/bench-all-polkadot.sh
new file mode 100644
index 000000000000..ac52e00140e3
--- /dev/null
+++ b/scripts/lib/bench-all-polkadot.sh
@@ -0,0 +1,88 @@
+#!/bin/bash
+
+# Runs all benchmarks for all pallets, for a given runtime, provided by $1
+# Should be run on a reference machine to gain accurate benchmarks
+# current reference machine: https://github.com/paritytech/polkadot/pull/6508/files
+# original source: https://github.com/paritytech/polkadot/blob/b9842c4b52f6791fef6c11ecd020b22fe614f041/scripts/run_all_benches.sh
+
+get_arg required --runtime "$@"
+runtime="${out:-""}"
+
+# default RUST_LOG is error, but could be overridden
+export RUST_LOG="${RUST_LOG:-error}"
+
+echo "[+] Compiling benchmarks..."
+cargo build --profile $profile --locked --features=runtime-benchmarks -p polkadot
+
+POLKADOT_BIN="./target/$profile/polkadot"
+
+# Update the block and extrinsic overhead weights.
+echo "[+] Benchmarking block and extrinsic overheads..."
+OUTPUT=$(
+ $POLKADOT_BIN benchmark overhead \
+ --chain="${runtime}-dev" \
+ --wasm-execution=compiled \
+ --weight-path="$output_path/runtime/${runtime}/constants/src/weights/" \
+ --warmup=10 \
+ --repeat=100 \
+ --header="$output_path/file_header.txt"
+)
+if [ $? -ne 0 ]; then
+ echo "$OUTPUT" >> "$ERR_FILE"
+ echo "[-] Failed to benchmark the block and extrinsic overheads. Error written to $ERR_FILE; continuing..."
+fi
+
+
+# Load all pallet names in an array.
+PALLETS=($(
+ $POLKADOT_BIN benchmark pallet --list --chain="${runtime}-dev" |\
+ tail -n+2 |\
+ cut -d',' -f1 |\
+ sort |\
+ uniq
+))
+
+echo "[+] Benchmarking ${#PALLETS[@]} pallets for runtime $runtime"
+
+# Define the error file.
+ERR_FILE="${ARTIFACTS_DIR}/benchmarking_errors.txt"
+# Delete the error file before each run.
+rm -f $ERR_FILE
+
+# Benchmark each pallet.
+for PALLET in "${PALLETS[@]}"; do
+ echo "[+] Benchmarking $PALLET for $runtime";
+
+ output_file=""
+ if [[ $PALLET == *"::"* ]]; then
+ # translates e.g. "pallet_foo::bar" to "pallet_foo_bar"
+ output_file="${PALLET//::/_}.rs"
+ fi
+
+ OUTPUT=$(
+ $POLKADOT_BIN benchmark pallet \
+ --chain="${runtime}-dev" \
+ --steps=50 \
+ --repeat=20 \
+ --no-storage-info \
+ --no-median-slopes \
+ --no-min-squares \
+ --pallet="$PALLET" \
+ --extrinsic="*" \
+ --execution=wasm \
+ --wasm-execution=compiled \
+ --header="$output_path/file_header.txt" \
+ --output="$output_path/runtime/${runtime}/src/weights/${output_file}" 2>&1
+ )
+ if [ $? -ne 0 ]; then
+ echo "$OUTPUT" >> "$ERR_FILE"
+ echo "[-] Failed to benchmark $PALLET. Error written to $ERR_FILE; continuing..."
+ fi
+done
+
+# Check if the error file exists.
+if [ -f "$ERR_FILE" ]; then
+ echo "[-] Some benchmarks failed. See: $ERR_FILE"
+else
+ echo "[+] All benchmarks passed."
+fi
diff --git a/scripts/lib/bench-all-substrate.sh b/scripts/lib/bench-all-substrate.sh
new file mode 100644
index 000000000000..eeb18cdd8bbb
--- /dev/null
+++ b/scripts/lib/bench-all-substrate.sh
@@ -0,0 +1,148 @@
+#!/usr/bin/env 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 has three parts which all use the Substrate runtime:
+# - Pallet benchmarking to update the pallet weights
+# - Overhead benchmarking for the Extrinsic and Block weights
+# - Machine benchmarking
+#
+# Should be run on a reference machine to gain accurate benchmarks
+# current reference machine: https://github.com/paritytech/substrate/pull/5848
+
+# Original source: https://github.com/paritytech/substrate/blob/ff9921a260a67e3a71f25c8b402cd5c7da787a96/scripts/run_all_benchmarks.sh
+# Fail if any sub-command in a pipe fails, not just the last one.
+set -o pipefail
+# Fail on undeclared variables.
+set -u
+# Fail if any sub-command fails.
+set -e
+# Fail on traps.
+# set -E
+
+# default RUST_LOG is warn, but could be overridden
+export RUST_LOG="${RUST_LOG:-error}"
+
+echo "[+] Compiling Substrate benchmarks..."
+cargo build --profile=$profile --locked --features=runtime-benchmarks -p staging-node-cli
+
+# The executable to use.
+SUBSTRATE="./target/$profile/substrate-node"
+
+# Manually exclude some pallets.
+EXCLUDED_PALLETS=(
+ # Helper pallets
+ "pallet_election_provider_support_benchmarking"
+ # Pallets without automatic benchmarking
+ "pallet_babe"
+ "pallet_grandpa"
+ "pallet_mmr"
+ "pallet_offences"
+ # Only used for testing, does not need real weights.
+ "frame_benchmarking_pallet_pov"
+ "pallet_example_tasks"
+ "pallet_example_basic"
+ "pallet_example_split"
+ "pallet_example_kitchensink"
+ "pallet_example_mbm"
+ "tasks_example"
+)
+
+# Load all pallet names in an array.
+ALL_PALLETS=($(
+ $SUBSTRATE benchmark pallet --list --chain=dev |\
+ tail -n+2 |\
+ cut -d',' -f1 |\
+ sort |\
+ uniq
+))
+
+# Define the error file.
+ERR_FILE="${ARTIFACTS_DIR}/benchmarking_errors.txt"
+
+# Delete the error file before each run.
+rm -f "$ERR_FILE"
+
+mkdir -p "$(dirname "$ERR_FILE")"
+
+# Update the block and extrinsic overhead weights.
+echo "[+] Benchmarking block and extrinsic overheads..."
+OUTPUT=$(
+ $SUBSTRATE benchmark overhead \
+ --chain=dev \
+ --wasm-execution=compiled \
+ --weight-path="$output_path/frame/support/src/weights/" \
+ --header="$output_path/HEADER-APACHE2" \
+ --warmup=10 \
+ --repeat=100 2>&1
+)
+if [ $? -ne 0 ]; then
+ echo "$OUTPUT" >> "$ERR_FILE"
+ echo "[-] Failed to benchmark the block and extrinsic overheads. Error written to $ERR_FILE; continuing..."
+fi
+
+echo "[+] Benchmarking ${#ALL_PALLETS[@]} Substrate pallets and excluding ${#EXCLUDED_PALLETS[@]}."
+
+echo "[+] Excluded pallets ${EXCLUDED_PALLETS[@]}"
+echo "[+] ------ "
+echo "[+] Whole list pallets ${ALL_PALLETS[@]}"
+
+# Benchmark each pallet.
+for PALLET in "${ALL_PALLETS[@]}"; do
+ FOLDER="$(echo "${PALLET#*_}" | tr '_' '-')";
+ WEIGHT_FILE="$output_path/frame/${FOLDER}/src/weights.rs"
+
+ # Skip the pallet if it is in the excluded list.
+
+ if [[ " ${EXCLUDED_PALLETS[@]} " =~ " ${PALLET} " ]]; then
+ echo "[+] Skipping $PALLET as it is in the excluded list."
+ continue
+ fi
+
+ echo "[+] Benchmarking $PALLET with weight file $WEIGHT_FILE";
+
+ set +e # Disable exit on error for the benchmarking of the pallets
+ OUTPUT=$(
+ $SUBSTRATE benchmark pallet \
+ --chain=dev \
+ --steps=50 \
+ --repeat=20 \
+ --pallet="$PALLET" \
+ --no-storage-info \
+ --no-median-slopes \
+ --no-min-squares \
+ --extrinsic="*" \
+ --wasm-execution=compiled \
+ --heap-pages=4096 \
+ --output="$WEIGHT_FILE" \
+ --header="$output_path/HEADER-APACHE2" \
+ --template="$output_path/.maintain/frame-weight-template.hbs" 2>&1
+ )
+ if [ $? -ne 0 ]; then
+ echo -e "$PALLET: $OUTPUT\n" >> "$ERR_FILE"
+ echo "[-] Failed to benchmark $PALLET. Error written to $ERR_FILE; continuing..."
+ fi
+ set -e # Re-enable exit on error
+done
+
+
+# Check if the error file exists.
+if [ -s "$ERR_FILE" ]; then
+ echo "[-] Some benchmarks failed. See: $ERR_FILE"
+ exit 1
+else
+ echo "[+] All benchmarks passed."
+fi
diff --git a/scripts/lib/bench-overhead.sh b/scripts/lib/bench-overhead.sh
new file mode 100644
index 000000000000..c4cca8b4c128
--- /dev/null
+++ b/scripts/lib/bench-overhead.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+THIS_DIR=$(dirname "${BASH_SOURCE[0]}")
+. "$THIS_DIR/../command-utils.sh"
+
+bench_overhead_common_args=(
+ --
+ benchmark
+ overhead
+ --wasm-execution=compiled
+ --warmup=10
+ --repeat=100
+)
+bench_overhead() {
+ local args
+ case "$target_dir" in
+ substrate)
+ args=(
+ --bin=substrate
+ "${bench_overhead_common_args[@]}"
+ --header="$output_path/HEADER-APACHE2"
+ --weight-path="$output_path/frame/support/src/weights"
+ --chain="dev"
+ )
+ ;;
+ polkadot)
+ get_arg required --runtime "$@"
+ local runtime="${out:-""}"
+ args=(
+ --bin=polkadot
+ "${bench_overhead_common_args[@]}"
+ --header="$output_path/file_header.txt"
+ --weight-path="$output_path/runtime/$runtime/constants/src/weights"
+ --chain="$runtime-dev"
+ )
+ ;;
+ cumulus)
+ get_arg required --runtime "$@"
+ local runtime="${out:-""}"
+ args=(
+ -p=polkadot-parachain-bin
+ "${bench_overhead_common_args[@]}"
+ --header="$output_path/file_header.txt"
+ --weight-path="$output_path/parachains/runtimes/assets/$runtime/src/weights"
+ --chain="$runtime"
+ )
+ ;;
+ trappist)
+ get_arg required --runtime "$@"
+ local runtime="${out:-""}"
+ args=(
+ "${bench_overhead_common_args[@]}"
+ --header="$output_path/templates/file_header.txt"
+ --weight-path="$output_path/runtime/$runtime/src/weights"
+ --chain="$runtime-dev"
+ )
+ ;;
+ *)
+ die "Target Dir \"$target_dir\" is not supported in bench_overhead"
+ ;;
+ esac
+
+ cargo_run "${args[@]}"
+}
+
+bench_overhead "$@"
diff --git a/scripts/lib/bench-pallet.sh b/scripts/lib/bench-pallet.sh
new file mode 100644
index 000000000000..15eac31e3a45
--- /dev/null
+++ b/scripts/lib/bench-pallet.sh
@@ -0,0 +1,178 @@
+#!/bin/bash
+
+THIS_DIR=$(dirname "${BASH_SOURCE[0]}")
+. "$THIS_DIR/../command-utils.sh"
+
+bench_pallet_common_args=(
+ --
+ benchmark
+ pallet
+ --steps=50
+ --repeat=20
+ --extrinsic="*"
+ --wasm-execution=compiled
+ --heap-pages=4096
+ --json-file="${ARTIFACTS_DIR}/bench.json"
+)
+bench_pallet() {
+ get_arg required --subcommand "$@"
+ local subcommand="${out:-""}"
+
+ get_arg required --runtime "$@"
+ local runtime="${out:-""}"
+
+ get_arg required --pallet "$@"
+ local pallet="${out:-""}"
+
+ local args
+ case "$target_dir" in
+ substrate)
+ args=(
+ --features=runtime-benchmarks
+ --manifest-path="$output_path/bin/node/cli/Cargo.toml"
+ "${bench_pallet_common_args[@]}"
+ --pallet="$pallet"
+ --chain="$runtime"
+ )
+
+ case "$subcommand" in
+ pallet)
+ # Translates e.g. "pallet_foo::bar" to "pallet_foo_bar"
+ local output_dir="${pallet//::/_}"
+
+ # Substrate benchmarks are output to the "frame" directory but they aren't
+ # named exactly after the $pallet argument. For example:
+ # - When $pallet == pallet_balances, the output folder is frame/balances
+ # - When $pallet == frame_benchmarking, the output folder is frame/benchmarking
+ # The common pattern we infer from those examples is that we should remove
+ # the prefix
+ if [[ "$output_dir" =~ ^[A-Za-z]*[^A-Za-z](.*)$ ]]; then
+ output_dir="${BASH_REMATCH[1]}"
+ fi
+
+ # We also need to translate '_' to '-' due to the folders' naming
+ # conventions
+ output_dir="${output_dir//_/-}"
+
+ args+=(
+ --header="$output_path/HEADER-APACHE2"
+ --output="$output_path/frame/$output_dir/src/weights.rs"
+ --template="$output_path/.maintain/frame-weight-template.hbs"
+ )
+ ;;
+ *)
+ die "Subcommand $subcommand is not supported for $target_dir in bench_pallet"
+ ;;
+ esac
+ ;;
+ polkadot)
+ # For backward compatibility: replace "-dev" with ""
+ runtime=${runtime/-dev/}
+
+ local weights_dir="$output_path/runtime/${runtime}/src/weights"
+
+ args=(
+ --bin=polkadot
+ --features=runtime-benchmarks
+ "${bench_pallet_common_args[@]}"
+ --pallet="$pallet"
+ --chain="${runtime}-dev"
+ )
+
+ case "$subcommand" in
+ pallet)
+ args+=(
+ --header="$output_path/file_header.txt"
+ --output="${weights_dir}/"
+ )
+ ;;
+ xcm)
+ args+=(
+ --header="$output_path/file_header.txt"
+ --template="$output_path/xcm/pallet-xcm-benchmarks/template.hbs"
+ --output="${weights_dir}/xcm/"
+ )
+ ;;
+ *)
+ die "Subcommand $subcommand is not supported for $target_dir in bench_pallet"
+ ;;
+ esac
+ ;;
+ cumulus)
+ get_arg required --runtime_dir "$@"
+ local runtime_dir="${out:-""}"
+ local chain="$runtime"
+
+ # to support specifying parachain id from runtime name (e.g. ["glutton-westend", "glutton-westend-dev-1300"])
+ # If runtime ends with "-dev" or "-dev-\d+", leave as it is, otherwise concat "-dev" at the end of $chain
+ if [[ ! "$runtime" =~ -dev(-[0-9]+)?$ ]]; then
+ chain="${runtime}-dev"
+ fi
+
+ # replace "-dev" or "-dev-\d+" with "" for runtime
+ runtime=$(echo "$runtime" | sed 's/-dev.*//g')
+
+ args=(
+ -p=polkadot-parachain-bin
+ --features=runtime-benchmarks
+ "${bench_pallet_common_args[@]}"
+ --pallet="$pallet"
+ --chain="${chain}"
+ --header="$output_path/file_header.txt"
+ )
+
+ case "$subcommand" in
+ pallet)
+ args+=(
+ --output="$output_path/parachains/runtimes/$runtime_dir/$runtime/src/weights/"
+ )
+ ;;
+ xcm)
+ mkdir -p "$output_path/parachains/runtimes/$runtime_dir/$runtime/src/weights/xcm"
+ args+=(
+ --template="$output_path/templates/xcm-bench-template.hbs"
+ --output="$output_path/parachains/runtimes/$runtime_dir/$runtime/src/weights/xcm/"
+ )
+ ;;
+ *)
+ die "Subcommand $subcommand is not supported for $target_dir in bench_pallet"
+ ;;
+ esac
+ ;;
+ trappist)
+ local weights_dir="$output_path/runtime/$runtime/src/weights"
+
+ args=(
+ --features=runtime-benchmarks
+ "${bench_pallet_common_args[@]}"
+ --pallet="$pallet"
+ --chain="${runtime}-dev"
+ --header="$output_path/templates/file_header.txt"
+ )
+
+ case "$subcommand" in
+ pallet)
+ args+=(
+ --output="${weights_dir}/"
+ )
+ ;;
+ xcm)
+ args+=(
+ --template="$output_path/templates/xcm-bench-template.hbs"
+ --output="${weights_dir}/xcm/"
+ )
+ ;;
+ *)
+ die "Subcommand $subcommand is not supported for $target_dir in bench_pallet"
+ ;;
+ esac
+ ;;
+ *)
+ die "Repository $target_dir is not supported in bench_pallet"
+ ;;
+ esac
+
+ cargo_run "${args[@]}"
+}
+
+bench_pallet "$@"
diff --git a/scripts/sync.sh b/scripts/sync.sh
new file mode 100755
index 000000000000..b5d8a5219937
--- /dev/null
+++ b/scripts/sync.sh
@@ -0,0 +1,74 @@
+#!/usr/bin/env bash
+
+set -eu -o pipefail
+
+. "$(realpath "$(dirname "${BASH_SOURCE[0]}")/command-utils.sh")"
+
+
+# Function to check syncing status
+check_syncing() {
+ # Send the system_health request and parse the isSyncing field
+ RESPONSE=$(curl -sSX POST http://127.0.0.1:9944 \
+ --header 'Content-Type: application/json' \
+ --data-raw '{"jsonrpc": "2.0", "method": "system_health", "params": [], "id": "1"}')
+
+ # Check for errors in the curl command
+ if [ $? -ne 0 ]; then
+ echo "Error: Unable to send request to Polkadot node"
+ fi
+
+ IS_SYNCING=$(echo $RESPONSE | jq -r '.result.isSyncing')
+
+ # Check for errors in the jq command or missing field in the response
+ if [ $? -ne 0 ] || [ "$IS_SYNCING" == "null" ]; then
+ echo "Error: Unable to parse sync status from response"
+ fi
+
+ # Return the isSyncing value
+ echo $IS_SYNCING
+}
+
+main() {
+ get_arg required --chain "$@"
+ local chain="${out:-""}"
+
+ get_arg required --type "$@"
+ local type="${out:-""}"
+
+ export RUST_LOG="${RUST_LOG:-remote-ext=debug,runtime=trace}"
+
+ cargo build --release
+
+ cp "./target/release/polkadot" ./polkadot-bin
+
+ # Start sync.
+ # "&" runs the process in the background
+ # "> /dev/tty" redirects the output of the process to the terminal
+ ./polkadot-bin --sync="$type" --chain="$chain" > "$ARTIFACTS_DIR/sync.log" 2>&1 &
+
+ # Get the PID of process
+ POLKADOT_SYNC_PID=$!
+
+ sleep 10
+
+ # Poll the node every 100 seconds until syncing is complete
+ while :; do
+ SYNC_STATUS="$(check_syncing)"
+ if [ "$SYNC_STATUS" == "true" ]; then
+ echo "Node is still syncing..."
+ sleep 100
+ elif [ "$SYNC_STATUS" == "false" ]; then
+ echo "Node sync is complete!"
+ kill "$POLKADOT_SYNC_PID" # Stop the Polkadot node process once syncing is complete
+ exit 0 # Success
+ elif [[ "$SYNC_STATUS" = Error:* ]]; then
+ echo "$SYNC_STATUS"
+ exit 1 # Error
+ else
+ echo "Unknown error: $SYNC_STATUS"
+ exit 1 # Unknown error
+ fi
+ done
+}
+
+main "$@"