bittensor-core: one Rust core (keys, keyfiles, timelock, codec, RFC-0078 digest, Ledger) under a thin Python SDK #3289
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Bittensor E2E Test | |
| permissions: | |
| pull-requests: write | |
| contents: read | |
| concurrency: | |
| group: e2e-cli-${{ github.ref }} | |
| cancel-in-progress: true | |
| # Path-filtered: none of this workflow's checks are required for merge, so a | |
| # workflow-level `paths:` filter is safe. If any check here is ever made | |
| # required, this filter MUST move to job-level `if:` gating (a required check | |
| # whose workflow never triggers is stuck "Expected" and blocks the merge). | |
| on: | |
| pull_request: | |
| branches: ["*"] | |
| types: [opened, synchronize, reopened, labeled, unlabeled] | |
| paths: | |
| # Anything that changes the node/runtime the e2e suites run against. | |
| - "common/**" | |
| - "node/**" | |
| - "pallets/**" | |
| - "precompiles/**" | |
| - "primitives/**" | |
| - "runtime/**" | |
| - "support/**" | |
| - "chain-extensions/**" | |
| - "src/**" | |
| - "vendor/**" | |
| - "Cargo.toml" | |
| - "Cargo.lock" | |
| - "build.rs" | |
| - "rust-toolchain.toml" | |
| - "Dockerfile-localnet" | |
| # The SDK/CLI code under test. | |
| - "sdk/**" | |
| - ".github/workflows/check-bittensor-e2e-tests.yml" | |
| workflow_dispatch: | |
| inputs: | |
| verbose: | |
| description: "Output more information when triggered manually" | |
| required: false | |
| default: "" | |
| env: | |
| CARGO_TERM_COLOR: always | |
| VERBOSE: ${{ github.event.inputs.verbose }} | |
| # The in-repo SDK e2e harness reads LOCALNET_IMAGE from the environment. | |
| LOCALNET_IMAGE: ghcr.io/raofoundation/subtensor-localnet:ci | |
| jobs: | |
| trusted-pr: | |
| name: Trusted PR source (non-fork) | |
| if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false | |
| runs-on: ubuntu-latest | |
| steps: | |
| - run: echo "Non-fork PR; self-hosted runners may execute checkout." | |
| check-label: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| skip-bittensor-e2e-tests: ${{ steps.get-labels.outputs.skip-bittensor-e2e-tests || steps.set-default.outputs.skip-bittensor-e2e-tests }} | |
| steps: | |
| - name: Install dependencies | |
| run: | | |
| sudo DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt-get update | |
| sudo DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt-get install -y --no-install-recommends -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" gh jq | |
| - name: Check out repository | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }} | |
| ref: ${{ github.event.pull_request.head.ref || github.ref_name }} | |
| - name: Get labels from PR | |
| id: get-labels | |
| if: github.event_name == 'pull_request' | |
| run: | | |
| LABELS=$(gh pr -R ${{ github.repository }} view ${{ github.event.pull_request.number }} --json labels --jq '.labels[].name') | |
| echo "Current labels: $LABELS" | |
| if echo "$LABELS" | grep -q "skip-bittensor-e2e-tests"; then | |
| echo "skip-bittensor-e2e-tests=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "skip-bittensor-e2e-tests=false" >> $GITHUB_OUTPUT | |
| fi | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set default skip value for workflow_dispatch | |
| id: set-default | |
| if: github.event_name == 'workflow_dispatch' | |
| run: | | |
| echo "skip-bittensor-e2e-tests=false" >> $GITHUB_OUTPUT | |
| find-e2e-tests: | |
| needs: check-label | |
| if: needs.check-label.outputs.skip-bittensor-e2e-tests == 'false' | |
| runs-on: ubuntu-latest | |
| outputs: | |
| test-files: ${{ steps.get-tests.outputs.test-files }} | |
| steps: | |
| - name: Install dependencies | |
| run: | | |
| sudo DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt-get update | |
| sudo DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt-get install -y --no-install-recommends -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" jq | |
| - name: Check out repository | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }} | |
| ref: ${{ github.event.pull_request.head.ref || github.ref_name }} | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.10" | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v5 | |
| with: | |
| enable-cache: "false" | |
| - name: Collect in-repo SDK e2e tests | |
| id: get-tests | |
| working-directory: sdk/python | |
| run: | | |
| set -euo pipefail | |
| uv sync --locked --all-extras --dev | |
| test_matrix=$( | |
| uv run pytest -q --collect-only -m e2e \ | |
| | sed -n '/^tests\/e2e\//p' \ | |
| | jq -R -s -c ' | |
| split("\n") | |
| | map(select(. != "")) | |
| | map({nodeid: ., label: (sub("^tests/e2e/"; "") | sub("\\.py$"; ""))}) | |
| ' | |
| ) | |
| echo "Found tests: $test_matrix" | |
| if [ "$test_matrix" = "[]" ] || [ -z "$test_matrix" ]; then | |
| echo "No e2e tests found — failing." | |
| exit 1 | |
| fi | |
| echo "test-files=$test_matrix" >> "$GITHUB_OUTPUT" | |
| shell: bash | |
| artifacts: | |
| name: Node • ${{ matrix.runtime }} • ${{ matrix.platform.arch }} | |
| needs: [check-label, trusted-pr] | |
| if: needs.check-label.outputs.skip-bittensor-e2e-tests == 'false' | |
| strategy: | |
| matrix: | |
| platform: | |
| - runner: [self-hosted, fireactions-heavy] | |
| triple: x86_64-unknown-linux-gnu | |
| arch: amd64 | |
| runtime: ["fast-runtime", "non-fast-runtime"] | |
| runs-on: ${{ matrix.platform.runner }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }} | |
| ref: ${{ github.event.pull_request.head.ref || github.ref_name }} | |
| - name: Install Rust + dependencies | |
| run: | | |
| chmod +x ./scripts/install_build_env.sh | |
| ./scripts/install_build_env.sh | |
| - name: Add Rust target triple | |
| run: | | |
| source "$HOME/.cargo/env" | |
| rustup target add ${{ matrix.platform.triple }} | |
| - name: Patch limits for local run | |
| run: | | |
| chmod +x ./scripts/localnet_patch.sh | |
| ./scripts/localnet_patch.sh | |
| - name: Build binaries | |
| run: | | |
| export PATH="$HOME/.cargo/bin:$PATH" | |
| export CARGO_BUILD_TARGET="${{ matrix.platform.triple }}" | |
| if [ "${{ matrix.runtime }}" = "fast-runtime" ]; then | |
| ./scripts/localnet.sh --build-only | |
| else | |
| ./scripts/localnet.sh False --build-only | |
| fi | |
| - name: Prepare artifacts for upload | |
| run: | | |
| RUNTIME="${{ matrix.runtime }}" | |
| TRIPLE="${{ matrix.platform.triple }}" | |
| BINARY_PATH="target/${RUNTIME}/${TRIPLE}/release/node-subtensor" | |
| WASM_PATH="target/${RUNTIME}/${TRIPLE}/release/wbuild/node-subtensor-runtime/node_subtensor_runtime.compact.compressed.wasm" | |
| if [[ ! -f "$BINARY_PATH" ]]; then | |
| echo "Error: Binary not found at $BINARY_PATH" | |
| exit 1 | |
| fi | |
| if [[ ! -f "$WASM_PATH" ]]; then | |
| echo "Error: WASM file not found at $WASM_PATH" | |
| exit 1 | |
| fi | |
| mkdir -p build/ci_target/${RUNTIME}/${TRIPLE}/release/ | |
| cp -v "$BINARY_PATH" \ | |
| build/ci_target/${RUNTIME}/${TRIPLE}/release/ | |
| mkdir -p build/ci_target/${RUNTIME}/${TRIPLE}/release/wbuild/node-subtensor-runtime/ | |
| cp -v "$WASM_PATH" \ | |
| build/ci_target/${RUNTIME}/${TRIPLE}/release/wbuild/node-subtensor-runtime/ | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: binaries-${{ matrix.platform.triple }}-${{ matrix.runtime }} | |
| path: build/ | |
| if-no-files-found: error | |
| build-image-with-current-branch: | |
| needs: [check-label, artifacts] | |
| if: needs.check-label.outputs.skip-bittensor-e2e-tests == 'false' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }} | |
| ref: ${{ github.event.pull_request.head.ref || github.ref_name }} | |
| - name: Download all binary artifacts | |
| uses: actions/download-artifact@v5 | |
| with: | |
| pattern: binaries-* | |
| path: build/ | |
| merge-multiple: true | |
| - name: Move Docker data-root to /mnt/data | |
| run: | | |
| sudo systemctl stop docker | |
| sudo mkdir -p /mnt/data/docker | |
| sudo chown -R runner:runner /mnt/data | |
| sudo chmod -R 777 /mnt/data | |
| echo '{"data-root": "/mnt/data/docker"}' | sudo tee /etc/docker/daemon.json | |
| sudo systemctl start docker | |
| docker info | grep "Docker Root Dir" | |
| - name: Build Docker Image | |
| run: docker build -f Dockerfile-localnet --build-arg BUILT_IN_CI="Boom shakalaka" -t localnet . | |
| - name: Save Docker Image as Tar | |
| run: docker save -o /mnt/data/subtensor-localnet.tar localnet | |
| - name: Upload Docker Image as Artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: subtensor-localnet | |
| path: /mnt/data/subtensor-localnet.tar | |
| run-sdk-e2e-tests: | |
| needs: | |
| - check-label | |
| - find-e2e-tests | |
| - build-image-with-current-branch | |
| if: needs.check-label.outputs.skip-bittensor-e2e-tests == 'false' | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| max-parallel: 32 | |
| matrix: | |
| include: ${{ fromJson(needs.find-e2e-tests.outputs.test-files) }} | |
| timeout-minutes: 60 | |
| name: "sdk: ${{ matrix.label }}" | |
| steps: | |
| - name: Check-out repository | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }} | |
| ref: ${{ github.event.pull_request.head.ref || github.ref_name }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v5 | |
| with: | |
| enable-cache: "false" | |
| - name: Install in-repo SDK | |
| working-directory: sdk/python | |
| run: | | |
| uv sync --locked --all-extras --dev | |
| - name: Download Cached Docker Image | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: subtensor-localnet | |
| - name: Load Docker Image | |
| run: docker load -i subtensor-localnet.tar | |
| - name: Retag Docker Image | |
| run: docker tag localnet "$LOCALNET_IMAGE" | |
| - name: Run with retry | |
| working-directory: sdk/python | |
| env: | |
| SKIP_PULL: 1 | |
| run: | | |
| set +e | |
| for i in 1 2; do | |
| echo "Attempt $i: Running tests" | |
| # -m e2e overrides the default addopts (-m 'not e2e') which would | |
| # otherwise deselect the collected test and fail with "no tests ran". | |
| uv run pytest "${{ matrix.nodeid }}" -s -m e2e | |
| status=$? | |
| if [ $status -eq 0 ]; then | |
| echo "Tests passed on attempt $i" | |
| break | |
| else | |
| echo "Tests failed on attempt $i" | |
| if [ $i -eq 2 ]; then | |
| echo "Tests failed after 2 attempts" | |
| exit 1 | |
| fi | |
| echo "Retrying..." | |
| sleep 5 | |
| fi | |
| done |