Skip to content

Improve test workflows #173

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Aug 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 173 additions & 0 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
name: E2E Tests

concurrency:
group: e2e-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

on:
pull_request:
branches:
- '**'
types: [ opened, synchronize, reopened, ready_for_review ]

workflow_dispatch:
inputs:
verbose:
description: "Output more information when triggered manually"
required: false
default: ""

env:
CARGO_TERM_COLOR: always
VERBOSE: ${{ github.event.inputs.verbose }}

# job to run tests in parallel
jobs:
# Looking for e2e tests
find-tests:
runs-on: ubuntu-latest
if: ${{ github.event.pull_request.draft == false }}
outputs:
test-files: ${{ steps.get-tests.outputs.test-files }}
steps:
- name: Check-out repository under $GITHUB_WORKSPACE
uses: actions/checkout@v4

- name: Find test files
id: get-tests
run: |
test_files=$(find tests/e2e_tests -name "test*.py" | jq -R -s -c 'split("\n") | map(select(. != ""))')
# keep it here for future debug
# test_files=$(find tests/e2e_tests -type f -name "test*.py" | grep -E 'test_(hotkeys|staking)\.py$' | jq -R -s -c 'split("\n") | map(select(. != ""))')
echo "Found test files: $test_files"
echo "test-files=$test_files" >> "$GITHUB_OUTPUT"
shell: bash

# Pull docker image
pull-docker-image:
runs-on: ubuntu-latest
outputs:
image-name: ${{ steps.set-image.outputs.image }}
steps:
- name: Set Docker image tag based on label or branch
id: set-image
run: |
echo "Event: $GITHUB_EVENT_NAME"
echo "Branch: $GITHUB_REF_NAME"

echo "Reading labels ..."
if [[ "${GITHUB_EVENT_NAME}" == "pull_request" ]]; then
labels=$(jq -r '.pull_request.labels[].name' "$GITHUB_EVENT_PATH")
else
labels=""
fi

image=""

for label in $labels; do
echo "Found label: $label"
case "$label" in
"subtensor-localnet:main")
image="ghcr.io/opentensor/subtensor-localnet:main"
break
;;
"subtensor-localnet:testnet")
image="ghcr.io/opentensor/subtensor-localnet:testnet"
break
;;
"subtensor-localnet:devnet")
image="ghcr.io/opentensor/subtensor-localnet:devnet"
break
;;
esac
done

if [[ -z "$image" ]]; then
# fallback to default based on branch
if [[ "${GITHUB_REF_NAME}" == "master" ]]; then
image="ghcr.io/opentensor/subtensor-localnet:main"
else
image="ghcr.io/opentensor/subtensor-localnet:devnet-ready"
fi
fi

echo "✅ Final selected image: $image"
echo "image=$image" >> "$GITHUB_OUTPUT"

- name: Log in to GitHub Container Registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $GITHUB_ACTOR --password-stdin

- name: Pull Docker Image
run: docker pull ${{ steps.set-image.outputs.image }}

- name: Save Docker Image to Cache
run: docker save -o subtensor-localnet.tar ${{ steps.set-image.outputs.image }}

- name: Upload Docker Image as Artifact
uses: actions/upload-artifact@v4
with:
name: subtensor-localnet
path: subtensor-localnet.tar

# Job to run tests in parallel
run-fast-blocks-e2e-test:
name: "FB: ${{ matrix.test-file }} / Python ${{ matrix.python-version }}"
needs:
- find-tests
- pull-docker-image
runs-on: ubuntu-latest
timeout-minutes: 45
strategy:
fail-fast: false # Allow other matrix jobs to run even if this job fails
max-parallel: 32 # Set the maximum number of parallel jobs (same as we have cores in ubuntu-latest runner)
matrix:
os:
- ubuntu-latest
test-file: ${{ fromJson(needs.find-tests.outputs.test-files) }}
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
steps:
- name: Check-out repository
uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@v4

- name: install dependencies
run: |
uv sync --extra dev --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: Run tests with retry
env:
LOCALNET_IMAGE_NAME: ${{ needs.pull-docker-image.outputs.image-name }}
run: |
for i in 1 2 3; do
echo "::group::🔁 Test attempt $i"
if uv run pytest ${{ matrix.test-file }} -s; then
echo "✅ Tests passed on attempt $i"
echo "::endgroup::"
exit 0
else
echo "❌ Tests failed on attempt $i"
echo "::endgroup::"
if [ "$i" -lt 3 ]; then
echo "Retrying..."
sleep 5
fi
fi
done

echo "Tests failed after 3 attempts"
exit 1
81 changes: 0 additions & 81 deletions .github/workflows/run-async-substrate-interface-tests.yml

This file was deleted.

59 changes: 59 additions & 0 deletions .github/workflows/unit-and-integration-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Unit and integration tests checker
permissions:
contents: read

on:
pull_request:
types: [opened, synchronize, reopened, edited]

jobs:
unit-and-integration-tests:
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest

strategy:
fail-fast: false
max-parallel: 5
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Cache venv
id: cache
uses: actions/cache@v4
with:
path: venv
key: v2-${{ runner.os }}-${{ hashFiles('pyproject.toml') }}

- name: Install deps
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
run: |
python -m venv venv
source venv/bin/activate
python -m pip install --upgrade pip
python -m pip install uv
python -m uv sync --extra dev --active

- name: Unit tests
timeout-minutes: 20
env:
PYTHONUNBUFFERED: "1"
run: |
source venv/bin/activate
python -m uv run pytest -n 2 tests/unit_tests/ --reruns 3

- name: Integration tests
timeout-minutes: 20
env:
PYTHONUNBUFFERED: "1"
run: |
source venv/bin/activate
python -m uv run pytest -n 2 tests/integration_tests/ --reruns 3
11 changes: 10 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,13 @@ requires = ["setuptools~=70.0.0", "wheel"]
build-backend = "setuptools.build_meta"

[project.optional-dependencies]
dev = ["pytest", "bittensor", "pytest-asyncio"]
dev = [
"bittensor",
"pytest==8.3.5",
"pytest-asyncio==0.26.0",
"pytest-mock==3.14.0",
"pytest-split==0.10.0",
"pytest-xdist==3.6.1",
"pytest-rerunfailures==10.2",
"substrate-interface"
]
Empty file added tests/__init__.py
Empty file.
File renamed without changes.
Loading
Loading