diff --git a/.github/workflows/check-runtime-migration.yml b/.github/workflows/check-runtime-migration.yml
new file mode 100644
index 0000000000000000000000000000000000000000..5de576e2fe4cd20bd87fc8340930687fde521663
--- /dev/null
+++ b/.github/workflows/check-runtime-migration.yml
@@ -0,0 +1,119 @@
+name: check-runtime-migration
+
+on:
+  pull_request:
+    types: [opened, synchronize, reopened, ready_for_review]
+  merge_group:
+concurrency:
+  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+  cancel-in-progress: true
+
+env:
+  FORKLIFT_storage_s3_bucketName: ${{ secrets.FORKLIFT_storage_s3_bucketName }}
+  FORKLIFT_storage_s3_accessKeyId: ${{ secrets.FORKLIFT_storage_s3_accessKeyId }}
+  FORKLIFT_storage_s3_secretAccessKey: ${{ secrets.FORKLIFT_storage_s3_secretAccessKey }}
+  FORKLIFT_storage_s3_endpointUrl: ${{ secrets.FORKLIFT_storage_s3_endpointUrl }}
+  FORKLIFT_metrics_pushEndpoint: ${{ secrets.FORKLIFT_metrics_pushEndpoint }}
+
+jobs:
+  set-image:
+    # GitHub Actions allows using 'env' in a container context.
+    # However, env variables don't work for forks: https://github.com/orgs/community/discussions/44322
+    # This workaround sets the container image for each job using 'set-image' job output.
+    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
+  # rococo and westend are disabled for now (no access to parity-chains.parity.io)
+  check-runtime-migration:
+    runs-on: arc-runners-polkadot-sdk-beefy
+    timeout-minutes: 30
+    needs: [set-image]
+    container:
+      image: ${{ needs.set-image.outputs.IMAGE }}
+    strategy:
+      fail-fast: false
+      matrix:
+        network: [
+            # westend,
+            # rococo,
+            asset-hub-westend,
+            asset-hub-rococo,
+            bridge-hub-westend,
+            bridge-hub-rococo,
+            contracts-rococo,
+            collectives-westend,
+            coretime-rococo,
+          ]
+        include:
+          # - network: westend
+          #   package: westend-runtime
+          #   wasm: westend_runtime.compact.compressed.wasm
+          #   uri: "wss://westend-try-runtime-node.parity-chains.parity.io:443"
+          #   subcommand_extra_args: "--no-weight-warnings"
+          #   command_extra_args: ""
+          # - network: rococo
+          #   package: rococo-runtime
+          #   wasm: rococo_runtime.compact.compressed.wasm
+          #   uri: "wss://rococo-try-runtime-node.parity-chains.parity.io:443"
+          #   subcommand_extra_args: "--no-weight-warnings"
+          #   command_extra_args: ""
+          - network: asset-hub-westend
+            package: asset-hub-westend-runtime
+            wasm: asset_hub_westend_runtime.compact.compressed.wasm
+            uri: "wss://westend-asset-hub-rpc.polkadot.io:443"
+            subcommand_extra_args: ""
+            command_extra_args: ""
+          - network: "asset-hub-rococo"
+            package: "asset-hub-rococo-runtime"
+            wasm: "asset_hub_rococo_runtime.compact.compressed.wasm"
+            uri: "wss://rococo-asset-hub-rpc.polkadot.io:443"
+            subcommand_extra_args: ""
+            command_extra_args: ""
+          - network: "bridge-hub-westend"
+            package: "bridge-hub-westend-runtime"
+            wasm: "bridge_hub_westend_runtime.compact.compressed.wasm"
+            uri: "wss://westend-bridge-hub-rpc.polkadot.io:443"
+          - network: "bridge-hub-rococo"
+            package: "bridge-hub-rococo-runtime"
+            wasm: "bridge_hub_rococo_runtime.compact.compressed.wasm"
+            uri: "wss://rococo-bridge-hub-rpc.polkadot.io:443"
+          - network: "contracts-rococo"
+            package: "contracts-rococo-runtime"
+            wasm: "contracts_rococo_runtime.compact.compressed.wasm"
+            uri: "wss://rococo-contracts-rpc.polkadot.io:443"
+          - network: "collectives-westend"
+            package: "collectives-westend-runtime"
+            wasm: "collectives_westend_runtime.compact.compressed.wasm"
+            uri: "wss://westend-collectives-rpc.polkadot.io:443"
+            command_extra_args: "--disable-spec-name-check"
+          - network: "coretime-rococo"
+            package: "coretime-rococo-runtime"
+            wasm: "coretime_rococo_runtime.compact.compressed.wasm"
+            uri: "wss://rococo-coretime-rpc.polkadot.io:443"
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
+      - name: script
+        run: |
+          echo "Running ${{ matrix.network }} runtime migration check"
+          export RUST_LOG=remote-ext=debug,runtime=debug
+
+          echo "---------- Downloading try-runtime CLI ----------"
+          curl -sL https://github.com/paritytech/try-runtime-cli/releases/download/v0.5.4/try-runtime-x86_64-unknown-linux-musl -o try-runtime
+          chmod +x ./try-runtime
+          echo "Using try-runtime-cli version:"
+          ./try-runtime --version
+
+          echo "---------- Building ${{ matrix.package }} runtime ----------"
+          time forklift cargo build --release --locked -p ${{ matrix.package }} --features try-runtime
+
+          echo "---------- Executing on-runtime-upgrade for ${{ matrix.network }} ----------"
+          time ./try-runtime ${{ matrix.command_extra_args }} \
+              --runtime ./target/release/wbuild/${{ matrix.package }}/${{ matrix.wasm }} \
+              on-runtime-upgrade --disable-spec-version-check --checks=all ${{ matrix.subcommand_extra_args }} live --uri ${{ matrix.uri }}
+          sleep 5
diff --git a/.github/workflows/test-github-actions.yml b/.github/workflows/tests.yml
similarity index 59%
rename from .github/workflows/test-github-actions.yml
rename to .github/workflows/tests.yml
index 5dbdb7156d51a122fa57721ab602d00adf27a4d3..8f46959cccc48c5fa90b350cb3527eeed2932263 100644
--- a/.github/workflows/test-github-actions.yml
+++ b/.github/workflows/tests.yml
@@ -1,4 +1,4 @@
-name: test-github-actions
+name: tests
 
 on:
   pull_request:
@@ -62,3 +62,40 @@ jobs:
         uses: actions/checkout@v4
       - name: script
         run: time forklift cargo run --locked --release -p staging-node-cli --bin substrate-node --features runtime-benchmarks -- benchmark pallet --chain dev --pallet "*" --extrinsic "*" --steps 2 --repeat 1 --quiet
+  # cf https://github.com/paritytech/polkadot-sdk/issues/1652
+  test-syscalls:
+    runs-on: arc-runners-polkadot-sdk-beefy
+    timeout-minutes: 30
+    needs: [set-image]
+    container:
+      image: ${{ needs.set-image.outputs.IMAGE }}
+    continue-on-error: true # this rarely triggers in practice
+    env:
+      SKIP_WASM_BUILD: 1
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
+      - name: script
+        run: |
+          forklift cargo build --locked --profile production --target x86_64-unknown-linux-musl --bin polkadot-execute-worker --bin polkadot-prepare-worker
+          cd polkadot/scripts/list-syscalls
+          ./list-syscalls.rb ../../../target/x86_64-unknown-linux-musl/production/polkadot-execute-worker --only-used-syscalls | diff -u execute-worker-syscalls -
+          ./list-syscalls.rb ../../../target/x86_64-unknown-linux-musl/production/polkadot-prepare-worker --only-used-syscalls | diff -u prepare-worker-syscalls -
+    # todo:
+    # after_script:
+    # - if [[ "$CI_JOB_STATUS" == "failed" ]]; then
+    #   printf "The x86_64 syscalls used by the worker binaries have changed. Please review if this is expected and update polkadot/scripts/list-syscalls/*-worker-syscalls as needed.\n";
+    #   fi
+  cargo-check-all-benches:
+    runs-on: arc-runners-polkadot-sdk-beefy
+    timeout-minutes: 30
+    needs: [set-image]
+    container:
+      image: ${{ needs.set-image.outputs.IMAGE }}
+    env:
+      SKIP_WASM_BUILD: 1
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
+      - name: script
+        run: time forklift cargo check --all --benches
diff --git a/.gitlab/pipeline/check.yml b/.gitlab/pipeline/check.yml
index 6fb8a97fe95821886c416d97224fb21fd0f2897b..5c1a667a313ce391f0c790881d87f48ebd79d073 100644
--- a/.gitlab/pipeline/check.yml
+++ b/.gitlab/pipeline/check.yml
@@ -146,96 +146,6 @@ check-runtime-migration-rococo:
     URI: "wss://rococo-try-runtime-node.parity-chains.parity.io:443"
     SUBCOMMAND_EXTRA_ARGS: "--no-weight-warnings"
 
-# Check runtime migrations for Parity managed asset hub chains
-check-runtime-migration-asset-hub-westend:
-  stage: check
-  extends:
-    - .docker-env
-    - .test-pr-refs
-    - .check-runtime-migration
-  variables:
-    NETWORK: "asset-hub-westend"
-    PACKAGE: "asset-hub-westend-runtime"
-    WASM: "asset_hub_westend_runtime.compact.compressed.wasm"
-    URI: "wss://westend-asset-hub-rpc.polkadot.io:443"
-
-check-runtime-migration-asset-hub-rococo:
-  stage: check
-  extends:
-    - .docker-env
-    - .test-pr-refs
-    - .check-runtime-migration
-  variables:
-    NETWORK: "asset-hub-rococo"
-    PACKAGE: "asset-hub-rococo-runtime"
-    WASM: "asset_hub_rococo_runtime.compact.compressed.wasm"
-    URI: "wss://rococo-asset-hub-rpc.polkadot.io:443"
-
-# Check runtime migrations for Parity managed bridge hub chains
-check-runtime-migration-bridge-hub-westend:
-  stage: check
-  extends:
-    - .docker-env
-    - .test-pr-refs
-    - .check-runtime-migration
-  variables:
-    NETWORK: "bridge-hub-westend"
-    PACKAGE: "bridge-hub-westend-runtime"
-    WASM: "bridge_hub_westend_runtime.compact.compressed.wasm"
-    URI: "wss://westend-bridge-hub-rpc.polkadot.io:443"
-
-check-runtime-migration-bridge-hub-rococo:
-  stage: check
-  extends:
-    - .docker-env
-    - .test-pr-refs
-    - .check-runtime-migration
-  variables:
-    NETWORK: "bridge-hub-rococo"
-    PACKAGE: "bridge-hub-rococo-runtime"
-    WASM: "bridge_hub_rococo_runtime.compact.compressed.wasm"
-    URI: "wss://rococo-bridge-hub-rpc.polkadot.io:443"
-
-# Check runtime migrations for Parity managed contract chains
-check-runtime-migration-contracts-rococo:
-  stage: check
-  extends:
-    - .docker-env
-    - .test-pr-refs
-    - .check-runtime-migration
-  variables:
-    NETWORK: "contracts-rococo"
-    PACKAGE: "contracts-rococo-runtime"
-    WASM: "contracts_rococo_runtime.compact.compressed.wasm"
-    URI: "wss://rococo-contracts-rpc.polkadot.io:443"
-
-# Check runtime migrations for Parity managed collectives chains
-check-runtime-migration-collectives-westend:
-  stage: check
-  extends:
-    - .docker-env
-    - .test-pr-refs
-    - .check-runtime-migration
-  variables:
-    NETWORK: "collectives-westend"
-    PACKAGE: "collectives-westend-runtime"
-    WASM: "collectives_westend_runtime.compact.compressed.wasm"
-    URI: "wss://westend-collectives-rpc.polkadot.io:443"
-    COMMAND_EXTRA_ARGS: "--disable-spec-name-check"
-
-# Check runtime migrations for Parity managed coretime chain
-check-runtime-migration-coretime-rococo:
-  stage: check
-  extends:
-    - .docker-env
-    - .test-pr-refs
-    - .check-runtime-migration
-  variables:
-    NETWORK: "coretime-rococo"
-    PACKAGE: "coretime-rococo-runtime"
-    WASM: "coretime_rococo_runtime.compact.compressed.wasm"
-    URI: "wss://rococo-coretime-rpc.polkadot.io:443"
-
 find-fail-ci-phrase:
   stage: check
   variables:
diff --git a/.gitlab/pipeline/test.yml b/.gitlab/pipeline/test.yml
index 796e4d65310481fef4e831a42497044a9ccaae5a..7976c2ad2e0ff6360c2a1fa0413dee5d2424ae97 100644
--- a/.gitlab/pipeline/test.yml
+++ b/.gitlab/pipeline/test.yml
@@ -24,7 +24,7 @@
 
 #
 #
-#  
+#
 codecov-start:
   stage: test
   when: manual
@@ -53,11 +53,11 @@ codecov-finish:
   extends:
     - .kubernetes-env
     - .common-refs
-    - .pipeline-stopper-artifacts  
+    - .pipeline-stopper-artifacts
   needs:
     - test-linux-stable-codecov
   script:
-    - !reference [.codecov-check, script]  
+    - !reference [.codecov-check, script]
     - codecovcli -v create-report-results -t ${CODECOV_TOKEN} -r paritytech/polkadot-sdk --commit-sha ${CI_COMMIT_SHA} --git-service github
     - codecovcli -v get-report-results -t ${CODECOV_TOKEN} -r paritytech/polkadot-sdk --commit-sha ${CI_COMMIT_SHA} --git-service github
     - codecovcli -v send-notifications -t ${CODECOV_TOKEN} -r paritytech/polkadot-sdk --commit-sha ${CI_COMMIT_SHA} --git-service github
@@ -78,14 +78,14 @@ test-linux-stable-codecov:
     RUST_TOOLCHAIN: stable
     RUSTFLAGS: "-Cdebug-assertions=y -Cinstrument-coverage"
     LLVM_PROFILE_FILE: "target/coverage/cargo-test-${CI_NODE_INDEX}-%p-%m.profraw"
-    CARGO_INCREMENTAL: 0    
-    FORKLIFT_BYPASS: "true"  
+    CARGO_INCREMENTAL: 0
+    FORKLIFT_BYPASS: "true"
   parallel: 2
   script:
     # tools
-    - !reference [.codecov-check, script]    
+    - !reference [.codecov-check, script]
     - rustup component add llvm-tools-preview
-    - mkdir -p target/coverage/result/  
+    - mkdir -p target/coverage/result/
     # Place real test call here
     - >
       time cargo nextest run -p polkadot \
@@ -102,15 +102,15 @@ test-linux-stable-codecov:
         -t lcov \
         --branch \
         -o target/coverage/result/report-${CI_NODE_INDEX}.lcov
-    - ls -l target/coverage/result/  
+    - ls -l target/coverage/result/
     - >
       if [ "$CI_COMMIT_REF_NAME" != "master" ]; then  
         codecovcli -v do-upload -f target/coverage/result/report-${CI_NODE_INDEX}.lcov --disable-search -t ${CODECOV_TOKEN} -r paritytech/polkadot-sdk --commit-sha ${CI_COMMIT_SHA} --fail-on-error --pr ${CI_COMMIT_REF_NAME} --git-service github;
       else
         codecovcli -v do-upload -f target/coverage/result/report-${CI_NODE_INDEX}.lcov --disable-search -t ${CODECOV_TOKEN} -r paritytech/polkadot-sdk --commit-sha ${CI_COMMIT_SHA} --fail-on-error --git-service github;
       fi
-          
-  #  
+
+  #
 
 test-linux-stable:
   stage: test
@@ -254,18 +254,6 @@ test-rustdoc:
   script:
     - time cargo doc --workspace --all-features --no-deps
 
-cargo-check-all-benches:
-  stage: test
-  extends:
-    - .docker-env
-    - .common-refs
-  # DAG
-  needs:
-    - job: cargo-hfuzz
-      artifacts: false
-  script:
-    - time cargo check --all --benches
-
 test-node-metrics:
   stage: test
   extends:
@@ -598,26 +586,6 @@ cargo-hfuzz:
     - for target in $(cargo read-manifest | jq -r '.targets | .[] | .name'); do
       cargo hfuzz run "$target" || { printf "fuzzing failure for %s\n" "$target"; exit 1; }; done
 
-# cf https://github.com/paritytech/polkadot-sdk/issues/1652
-test-syscalls:
-  stage: test
-  extends:
-    - .docker-env
-    - .common-refs
-    - .run-immediately
-  variables:
-    SKIP_WASM_BUILD: 1
-  script:
-    - cargo build --locked --profile production --target x86_64-unknown-linux-musl --bin polkadot-execute-worker --bin polkadot-prepare-worker
-    - cd polkadot/scripts/list-syscalls
-    - ./list-syscalls.rb ../../../target/x86_64-unknown-linux-musl/production/polkadot-execute-worker --only-used-syscalls | diff -u execute-worker-syscalls -
-    - ./list-syscalls.rb ../../../target/x86_64-unknown-linux-musl/production/polkadot-prepare-worker --only-used-syscalls | diff -u prepare-worker-syscalls -
-  after_script:
-    - if [[ "$CI_JOB_STATUS" == "failed" ]]; then
-      printf "The x86_64 syscalls used by the worker binaries have changed. Please review if this is expected and update polkadot/scripts/list-syscalls/*-worker-syscalls as needed.\n";
-      fi
-  allow_failure: false # this rarely triggers in practice
-
 .subsystem-benchmark-template:
   stage: test
   artifacts: