Skip to content

Reduce Subtensor compilation time and run E2E tests a few times faster #4

Reduce Subtensor compilation time and run E2E tests a few times faster

Reduce Subtensor compilation time and run E2E tests a few times faster #4

name: Bittensor Bittensor E2E Test
permissions:
pull-requests: write
contents: read
concurrency:
group: e2e-cli-${{ github.ref }}
cancel-in-progress: true
on:
pull_request:
branches: ["*"]
types: [opened, synchronize, reopened, labeled, unlabeled]
workflow_dispatch:
inputs:
verbose:
description: "Output more information when triggered manually"
required: false
default: ""
env:
CARGO_TERM_COLOR: always
VERBOSE: ${{ github.event.inputs.verbose }}
jobs:
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-btcli-e2e-tests:
needs: check-label
if: needs.check-label.outputs.skip-bittensor-e2e-tests == 'false'
runs-on: ubuntu-latest
outputs:
test-files: ${{ steps.get-btcli-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: Research preparation
working-directory: ${{ github.workspace }}
run: git clone https://github.com/opentensor/btcli.git
- name: Checkout
working-directory: ${{ github.workspace }}/btcli
run: git checkout staging
- name: Find e2e test files
id: get-btcli-tests
run: |
test_files=$(find ${{ github.workspace }}/btcli/tests/e2e_tests -name "test*.py" | jq -R -s -c 'split("\n") | map(select(. != ""))')
echo "test-files=$test_files" >> $GITHUB_OUTPUT
shell: bash
find-sdk-e2e-tests:
needs: check-label
if: needs.check-label.outputs.skip-bittensor-e2e-tests == 'false'
runs-on: ubuntu-latest
outputs:
test-files: ${{ steps.get-sdk-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: Research preparation
working-directory: ${{ github.workspace }}
run: git clone https://github.com/opentensor/bittensor.git
- name: Checkout
working-directory: ${{ github.workspace }}/bittensor
run: git checkout staging
- name: Find e2e test files
id: get-sdk-tests
run: |
test_files=$(find ${{ github.workspace }}/bittensor/tests/e2e_tests -name "test*.py" | jq -R -s -c 'split("\n") | map(select(. != ""))')
echo "test-files=$test_files" >> $GITHUB_OUTPUT
shell: bash
# build artifacts for non-fast-runtime (e2e tests only need this)
artifacts:
name: Node β€’ ${{ matrix.runtime }} β€’ ${{ matrix.platform.arch }}
needs: check-label
if: needs.check-label.outputs.skip-bittensor-e2e-tests == 'false'
strategy:
matrix:
platform:
- triple: x86_64-unknown-linux-gnu
arch: amd64
runtime: ["non-fast-runtime"]
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: 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 }}"
./scripts/localnet.sh False --build-only
# use `ci_target` name bc .dockerignore excludes `target`
- name: Prepare artifacts for upload
run: |
RUNTIME="${{ matrix.runtime }}"
TRIPLE="${{ matrix.platform.triple }}"
# Verify binaries exist before copying
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
# Collect all artifacts and build a Docker image
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 -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
# main btcli job
run-btcli-e2e-tests:
needs:
- check-label
- find-btcli-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: 16
matrix:
rust-branch:
- stable
rust-target:
- x86_64-unknown-linux-gnu
os:
- ubuntu-latest
test-file: ${{ fromJson(needs.find-btcli-e2e-tests.outputs.test-files) }}
env:
RELEASE_NAME: development
RUSTV: ${{ matrix.rust-branch }}
RUST_BACKTRACE: full
RUST_BIN_DIR: target/${{ matrix.rust-target }}
TARGET: ${{ matrix.rust-target }}
timeout-minutes: 60
name: "cli: ${{ matrix.test-file }}"
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: Create Python virtual environment
working-directory: ${{ github.workspace }}
run: uv venv --seed ${{ github.workspace }}/venv
- name: Clone Bittensor CLI repo
working-directory: ${{ github.workspace }}
run: git clone https://github.com/opentensor/btcli.git
- name: Setup Bittensor-cli from cloned repo
working-directory: ${{ github.workspace }}/btcli
run: |
source ${{ github.workspace }}/venv/bin/activate
git checkout staging
git fetch origin staging
uv run --active pip install --upgrade pip
uv run --active pip install '.[dev]'
uv run --active pip install pytest
- 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 ghcr.io/opentensor/subtensor-localnet:devnet-ready
- name: Run with retry
working-directory: ${{ github.workspace }}/btcli
run: |
source ${{ github.workspace }}/venv/bin/activate
export SKIP_PULL=1
set +e
for i in 1 2; do
echo "πŸ” Attempt $i: Running tests"
uv run pytest ${{ matrix.test-file }} -s
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
# main sdk job
run-sdk-e2e-tests:
needs:
- check-label
- find-sdk-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: 16
matrix:
rust-branch:
- stable
rust-target:
- x86_64-unknown-linux-gnu
os:
- ubuntu-latest
test-file: ${{ fromJson(needs.find-sdk-e2e-tests.outputs.test-files) }}
env:
RELEASE_NAME: development
RUSTV: ${{ matrix.rust-branch }}
RUST_BACKTRACE: full
RUST_BIN_DIR: target/${{ matrix.rust-target }}
TARGET: ${{ matrix.rust-target }}
timeout-minutes: 60
name: "sdk: ${{ matrix.test-file }}"
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: Create Python virtual environment
working-directory: ${{ github.workspace }}
run: uv venv --seed ${{ github.workspace }}/venv
- name: Clone Bittensor SDK repo
working-directory: ${{ github.workspace }}
run: git clone https://github.com/opentensor/bittensor.git
- name: Setup Bittensor SDK from cloned repo
working-directory: ${{ github.workspace }}/bittensor
run: |
source ${{ github.workspace }}/venv/bin/activate
git checkout staging
git fetch origin staging
uv run --active pip install --upgrade pip
uv run --active pip install '.[dev]'
uv run --active pip install pytest
- 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 ghcr.io/opentensor/subtensor-localnet:devnet-ready
- name: Run with retry
working-directory: ${{ github.workspace }}/bittensor
run: |
source ${{ github.workspace }}/venv/bin/activate
export SKIP_PULL=1
set +e
for i in 1 2; do
echo "πŸ” Attempt $i: Running tests"
uv run pytest ${{ matrix.test-file }} -s
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