Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0df6dda
ci: clean up snapshot cache controls
UnArbosFive Jul 12, 2026
9a44109
ci: move scheduled smoke checks to hosted runners
UnArbosFive Jul 12, 2026
f2930a3
ci: increase snapshot RPC concurrency
UnArbosFive Jul 12, 2026
8a56234
ci: speed up cached snapshot downloads
UnArbosFive Jul 12, 2026
f1ce15a
revert: retain faster snapshot download path
UnArbosFive Jul 12, 2026
d43478f
ci: benchmark parallel snapshot downloads
UnArbosFive Jul 12, 2026
0270b68
ci: benchmark mainnet restore across runner pools
UnArbosFive Jul 12, 2026
fe0cba6
ci: parallelize cached snapshot downloads
UnArbosFive Jul 12, 2026
a91a42f
ci: benchmark try-runtime on turbo16
UnArbosFive Jul 12, 2026
a18fc78
ci: run try-runtime on turbo16
UnArbosFive Jul 12, 2026
17b00ae
ci: run try-runtime on GitHub-hosted runners
UnArbosFive Jul 12, 2026
7f332bf
ci: harden cached snapshot workflows
UnArbosFive Jul 12, 2026
526f3ab
ci: consolidate and accelerate clone regressions
UnArbosFive Jul 13, 2026
1a7ce4d
ci: trust base revision for runtime path filtering
UnArbosFive Jul 13, 2026
a871a87
ci: test snapshot producer on hosted runners
UnArbosFive Jul 13, 2026
297d528
ci: retire dedicated try-runtime runners
UnArbosFive Jul 13, 2026
d6442e9
ci: drop hosted-only snapshot telemetry
UnArbosFive Jul 13, 2026
172947f
ci: cache SDK core builds in clone checks
UnArbosFive Jul 13, 2026
09b4a7b
ci: drop ineffective SDK compiler cache
UnArbosFive Jul 13, 2026
216f0d6
ci: respect clone RPC page limit
UnArbosFive Jul 13, 2026
2009512
ci: simplify clone runtime orchestration
UnArbosFive Jul 13, 2026
fc1d474
ci: benchmark single-node e2e finality
UnArbosFive Jul 13, 2026
17e4983
ci: tune single-node e2e block waits
UnArbosFive Jul 13, 2026
f9f84b9
test: synchronize accelerated evm nonces
UnArbosFive Jul 13, 2026
b2a3e60
ci: validate balanced shield shards
UnArbosFive Jul 13, 2026
a4ffe23
ci: finalize accelerated typescript e2e suite
UnArbosFive Jul 13, 2026
68f45e5
test: wait for frontier after substrate transfer
UnArbosFive Jul 13, 2026
9b434c0
test: poll frontier balance after substrate transfer
UnArbosFive Jul 13, 2026
ff30727
test: bypass ethers balance cache
UnArbosFive Jul 13, 2026
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
1 change: 0 additions & 1 deletion .github/actionlint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@ self-hosted-runner:
labels:
- fireactions-turbo-16
- fireactions-turbo-8
- fireactions-tryruntime
- Benchmarking
52 changes: 52 additions & 0 deletions .github/actions/run-typescript-e2e/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Run TypeScript E2E suite
description: Download a prebuilt node and run one Moonwall environment.

inputs:
binary:
description: Node artifact variant to download.
required: true
test:
description: Moonwall environment to run.
required: true

runs:
using: composite
steps:
- name: Download binary
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: node-subtensor-${{ inputs.binary }}
path: target/release

- name: Make binary executable
shell: bash
run: chmod +x target/release/node-subtensor

- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version-file: ts-tests/.nvmrc

- name: Setup pnpm
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
with:
version: 10

- name: Install e2e dependencies
shell: bash
working-directory: ts-tests
run: pnpm install --frozen-lockfile

- name: Install lsof (dev foundation RPC port discovery)
if: inputs.test == 'dev'
shell: bash
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 lsof

- name: Run tests
shell: bash
working-directory: ts-tests
env:
MOONWALL_TEST: ${{ inputs.test }}
run: pnpm moonwall test "$MOONWALL_TEST"
62 changes: 62 additions & 0 deletions .github/scripts/classify-runtime-changes.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env bash

set -euo pipefail

if [[ $# -ne 1 ]]; then
echo "usage: classify-runtime-changes.sh OUTPUT_FILE" >&2
exit 2
fi

output_file="$1"

runtime=false
docs=false
python_sdk=false
sdk_drift=false
snapshot_ci=false

# Keep path ownership explicit. SDK-only changes are covered by sdk-checks and
# the Rust SDK e2e workflow; they should not force clone-upgrade or SDK drift.
while IFS= read -r path; do
case "$path" in
common/*|node/*|pallets/*|precompiles/*|primitives/*|runtime/*|support/*|chain-extensions/*|src/*|vendor/*|Cargo.toml|build.rs|rust-toolchain.toml)
runtime=true
sdk_drift=true
;;
clones/*|website/apps/bittensor-website/scripts/*)
runtime=true
;;
.github/workflows/runtime-checks.yml|.github/workflows/refresh-mainnet-snapshot.yml|.github/actions/rust-setup/*|.github/actions/sccache-setup/*|.github/scripts/sccache-configure.sh)
runtime=true
;;
.github/scripts/classify-runtime-changes.sh|.github/scripts/test-runtime-change-filter.sh|.github/scripts/snapshot-artifact.sh|.github/scripts/test-snapshot-artifact.sh)
runtime=true
snapshot_ci=true
;;
esac

case "$path" in
website/*|sdk/python/*|.github/workflows/runtime-checks.yml) docs=true ;;
esac

case "$path" in
sdk/python/*|sdk/bittensor-core/*|sdk/bittensor-core-py/*|sdk/bittensor-core-wasm/*|Cargo.lock|.github/workflows/runtime-checks.yml)
python_sdk=true
;;
esac

case "$path" in
.github/workflows/runtime-checks.yml|.github/workflows/refresh-mainnet-snapshot.yml)
snapshot_ci=true
;;
esac
done

echo "runtime=$runtime, docs=$docs, python_sdk=$python_sdk, sdk_drift=$sdk_drift, snapshot_ci=$snapshot_ci"
{
echo "runtime=$runtime"
echo "docs=$docs"
echo "python_sdk=$python_sdk"
echo "sdk_drift=$sdk_drift"
echo "snapshot_ci=$snapshot_ci"
} >> "$output_file"
107 changes: 52 additions & 55 deletions .github/scripts/snapshot-artifact.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@ usage() {
cat >&2 <<'EOF'
Usage:
snapshot-artifact.sh mode EVENT_NAME LABELS_JSON MANUAL_FRESH OUTPUT_FILE
snapshot-artifact.sh select ARTIFACT_NAME BRANCH REPOSITORY_ID MAX_AGE_HOURS OUTPUT_FILE [required|optional]
snapshot-artifact.sh download ARTIFACT_ID DIGEST DESTINATION
snapshot-artifact.sh validate MANIFEST_FILE SNAPSHOT_FILE NETWORK GENESIS_HASH CLI_VERSION
snapshot-artifact.sh select ARTIFACT_NAME BRANCH REPOSITORY_ID WORKFLOW_PATH MAX_AGE_HOURS OUTPUT_FILE [required|optional]
snapshot-artifact.sh validate MANIFEST_FILE SNAPSHOT_FILE NETWORK GENESIS_HASH CLI_VERSION PRODUCER_SHA

For tests, set ARTIFACTS_JSON_FILE instead of calling the GitHub API,
ARTIFACT_ZIP_FILE instead of downloading an artifact, and NOW_EPOCH to
override the current time.
For tests, set ARTIFACTS_JSON_FILE and WORKFLOW_RUNS_JSON_FILE instead of
calling the GitHub API and NOW_EPOCH to override the current time.
EOF
exit 2
}
Expand Down Expand Up @@ -62,16 +60,21 @@ resolve_mode() {
}

select_artifact() {
[[ $# -eq 6 ]] || usage
[[ $# -eq 7 ]] || usage
local artifact_name="$1"
local branch="$2"
local repository_id="$3"
local max_age_hours="$4"
local output_file="$5"
local requirement="$6"
local payload now candidate created_epoch age_seconds age_hours
local workflow_path="$4"
local max_age_hours="$5"
local output_file="$6"
local requirement="$7"
local payload workflow_runs workflow_file now candidate created_epoch age_seconds age_hours

[[ "$repository_id" =~ ^[0-9]+$ ]] || { echo "invalid repository id: $repository_id" >&2; exit 2; }
[[ "$workflow_path" =~ ^\.github/workflows/[A-Za-z0-9._-]+\.ya?ml$ ]] || {
echo "invalid workflow path: $workflow_path" >&2
exit 2
}
[[ "$max_age_hours" =~ ^[0-9]+$ ]] || { echo "invalid maximum age: $max_age_hours" >&2; exit 2; }
[[ "$requirement" == required || "$requirement" == optional ]] || usage

Expand All @@ -82,30 +85,58 @@ select_artifact() {
payload=$(gh api \
"repos/$GITHUB_REPOSITORY/actions/artifacts?name=$artifact_name&per_page=100")
fi
if [[ -n "${WORKFLOW_RUNS_JSON_FILE:-}" ]]; then
workflow_runs=$(<"$WORKFLOW_RUNS_JSON_FILE")
else
workflow_file="${workflow_path##*/}"
workflow_runs=$(gh api --method GET \
"repos/$GITHUB_REPOSITORY/actions/workflows/$workflow_file/runs" \
-f branch="$branch" -F per_page=100 -F exclude_pull_requests=true \
--jq '{workflow_runs: [.workflow_runs[] | {
id, path, head_branch, head_sha,
repository: {id: .repository.id},
head_repository: {id: .head_repository.id}
}]}')
fi

now="${NOW_EPOCH:-$(date -u +%s)}"
[[ "$now" =~ ^[0-9]+$ ]] || { echo "invalid NOW_EPOCH: $now" >&2; exit 2; }

candidate=$(jq -cer \
candidate=$(jq -ncer \
--arg name "$artifact_name" \
--arg branch "$branch" \
--arg workflow_path "$workflow_path" \
--argjson repository_id "$repository_id" \
--argjson now "$now" \
--argjson max_age_seconds "$((max_age_hours * 3600))" '
--argjson max_age_seconds "$((max_age_hours * 3600))" \
--argjson artifacts "$payload" \
--argjson workflow_runs "$workflow_runs" '
($workflow_runs.workflow_runs
| map(select(
.path == $workflow_path and
.head_branch == $branch and
.repository.id == $repository_id and
.head_repository.id == $repository_id and
(.head_sha | test("^[0-9a-f]{40}$"))
))
| map({key: (.id | tostring), value: .head_sha})
| from_entries) as $trusted_runs
|
[
.artifacts[]
$artifacts.artifacts[]
| select(.name == $name)
| select(.expired == false)
| select(.workflow_run.head_branch == $branch)
| select(.workflow_run.repository_id == $repository_id)
| select(.workflow_run.head_repository_id == $repository_id)
| select($trusted_runs[(.workflow_run.id | tostring)] == .workflow_run.head_sha)
| .created_epoch = (.created_at | fromdateiso8601)
| select(.created_epoch <= $now)
| select(($now - .created_epoch) <= $max_age_seconds)
]
| sort_by(.created_epoch)
| last // empty
' <<<"$payload" 2>/dev/null || true)
' 2>/dev/null || true)

if [[ -z "$candidate" ]]; then
set_output "$output_file" found false
Expand All @@ -124,57 +155,23 @@ select_artifact() {
set_output "$output_file" found true
set_output "$output_file" artifact-id "$(jq -er '.id' <<<"$candidate")"
set_output "$output_file" run-id "$(jq -er '.workflow_run.id' <<<"$candidate")"
set_output "$output_file" producer-sha "$(jq -er '.workflow_run.head_sha' <<<"$candidate")"
set_output "$output_file" created-at "$(jq -er '.created_at' <<<"$candidate")"
set_output "$output_file" age-hours "$age_hours"
set_output "$output_file" size-bytes "$(jq -er '.size_in_bytes' <<<"$candidate")"
set_output "$output_file" digest "$(jq -er '.digest // ""' <<<"$candidate")"

if ((age_seconds > 36 * 3600)); then
echo "::warning::$artifact_name is ${age_hours}h old; refresh is expected daily and this artifact becomes unusable after ${max_age_hours}h."
fi
echo "Selected $artifact_name artifact $(jq -er '.id' <<<"$candidate") from run $(jq -er '.workflow_run.id' <<<"$candidate") (${age_hours}h old)."
}

download_artifact() {
[[ $# -eq 3 ]] || usage
local artifact_id="$1"
local digest="$2"
local destination="$3"
local archive actual_digest

[[ "$artifact_id" =~ ^[0-9]+$ ]] || { echo "invalid artifact id: $artifact_id" >&2; exit 2; }
[[ "$digest" =~ ^sha256:[0-9a-f]{64}$ ]] || { echo "invalid artifact digest: $digest" >&2; exit 2; }

archive=$(mktemp)
trap 'rm -f "$archive"' RETURN
if [[ -n "${ARTIFACT_ZIP_FILE:-}" ]]; then
cp "$ARTIFACT_ZIP_FILE" "$archive"
else
: "${GITHUB_REPOSITORY:?GITHUB_REPOSITORY must be set}"
gh api \
-H 'Accept: application/vnd.github+json' \
"repos/$GITHUB_REPOSITORY/actions/artifacts/$artifact_id/zip" > "$archive"
fi

actual_digest="sha256:$(sha256sum "$archive" | awk '{print $1}')"
[[ "$actual_digest" == "$digest" ]] || {
echo "artifact archive checksum mismatch: expected $digest, got $actual_digest" >&2
exit 1
}
mkdir -p "$destination"
unzip -q "$archive" -d "$destination"
rm -f "$archive"
trap - RETURN
echo "Downloaded and verified artifact $artifact_id."
}

validate_manifest() {
[[ $# -eq 5 ]] || usage
[[ $# -eq 6 ]] || usage
local manifest_file="$1"
local snapshot_file="$2"
local network="$3"
local genesis_hash="$4"
local cli_version="$5"
local producer_sha="$6"
local expected_file expected_size expected_sha actual_size actual_sha

[[ -f "$manifest_file" ]] || { echo "missing snapshot manifest: $manifest_file" >&2; exit 1; }
Expand All @@ -183,7 +180,8 @@ validate_manifest() {
jq -e \
--arg network "$network" \
--arg genesis "$genesis_hash" \
--arg cli "$cli_version" '
--arg cli "$cli_version" \
--arg producer_sha "$producer_sha" '
.schema_version == 1 and
.kind == "try-runtime-state" and
.network == $network and
Expand All @@ -194,7 +192,7 @@ validate_manifest() {
(.source_spec_name | type == "string" and length > 0) and
(.source_spec_version | type == "number") and
(.created_at | fromdateiso8601 | type == "number") and
(.producer_sha | test("^[0-9a-f]{40}$")) and
.producer_sha == $producer_sha and
(.snapshot_file | type == "string" and length > 0) and
(.snapshot_size_bytes | type == "number") and
(.snapshot_sha256 | test("^[0-9a-f]{64}$"))
Expand Down Expand Up @@ -231,7 +229,6 @@ shift || true
case "$command" in
mode) resolve_mode "$@" ;;
select) select_artifact "$@" ;;
download) download_artifact "$@" ;;
validate) validate_manifest "$@" ;;
*) usage ;;
esac
41 changes: 41 additions & 0 deletions .github/scripts/test-runtime-change-filter.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env bash

set -euo pipefail

script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
classifier="$script_dir/classify-runtime-changes.sh"
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT

assert_classification() {
local path="$1" expected="$2" output="$tmp/output"
: > "$output"
printf '%s\n' "$path" | "$classifier" "$output" >/dev/null
diff -u <(printf '%s\n' "$expected") "$output"
}

all_false=$'runtime=false\ndocs=false\npython_sdk=false\nsdk_drift=false\nsnapshot_ci=false'
runtime_only=$'runtime=true\ndocs=false\npython_sdk=false\nsdk_drift=false\nsnapshot_ci=false'
runtime_and_sdk=$'runtime=true\ndocs=false\npython_sdk=false\nsdk_drift=true\nsnapshot_ci=false'
runtime_and_docs=$'runtime=true\ndocs=true\npython_sdk=false\nsdk_drift=false\nsnapshot_ci=false'
runtime_and_snapshot_only=$'runtime=true\ndocs=false\npython_sdk=false\nsdk_drift=false\nsnapshot_ci=true'
runtime_and_snapshot=$'runtime=true\ndocs=true\npython_sdk=true\nsdk_drift=false\nsnapshot_ci=true'
docs_and_python=$'runtime=false\ndocs=true\npython_sdk=true\nsdk_drift=false\nsnapshot_ci=false'
python_only=$'runtime=false\ndocs=false\npython_sdk=true\nsdk_drift=false\nsnapshot_ci=false'

assert_classification README.md "$all_false"
assert_classification .github/actions/rust-setup/action.yml "$runtime_only"
assert_classification .github/actions/sccache-setup/action.yml "$runtime_only"
assert_classification .github/scripts/classify-runtime-changes.sh "$runtime_and_snapshot_only"
assert_classification .github/scripts/test-runtime-change-filter.sh "$runtime_and_snapshot_only"
assert_classification clones/scripts/start-local-clone-and-wait.sh "$runtime_only"
assert_classification .github/workflows/refresh-mainnet-snapshot.yml "$runtime_and_snapshot_only"
assert_classification .github/workflows/runtime-checks.yml "$runtime_and_snapshot"
assert_classification website/apps/bittensor-website/scripts/generate-metadata.mjs "$runtime_and_docs"
assert_classification sdk/bittensor-core/src/lib.rs "$python_only"
assert_classification Cargo.lock "$python_only"
assert_classification rust-toolchain.toml "$runtime_and_sdk"
assert_classification $'README.md\nsdk/python/example.py' "$docs_and_python"
assert_classification $'README.md\nnode/src/renamed-service.rs' "$runtime_and_sdk"

echo "runtime change filter tests passed"
Loading
Loading