Stage native forge (.hanzo/workflows) for git.hanzo.ai

Port rust-ci/publish/maturin/gpu-tests into .hanzo/workflows, which the fork
scans first; GitHub.com ignores .hanzo/, so these are inert on GitHub. Only
adaptation: gpu-tests targets the git-runner host daemons by bare backend
label (cuda/rocm/metal) instead of the self-hosted label set.
rust-ci/publish/maturin are verbatim -- they run on the mapped
hanzo-build-linux-amd64 label; the windows/macOS/arm matrix legs need their
own git-runner labels registered or they queue (runner provisioning, not a
workflow change).
This commit is contained in:
Hanzo Dev
2026-07-22 13:27:00 -07:00
parent 403640cf16
commit 5761722e28
4 changed files with 359 additions and 0 deletions
+50
View File
@@ -0,0 +1,50 @@
name: gpu-tests
# Native (Hanzo Git) copy of .github/workflows/gpu-tests.yml. The fork scans
# .hanzo/workflows FIRST; GitHub.com ignores .hanzo/, so this is inert on GitHub.
#
# One native adaptation: the runner label drops the GitHub `self-hosted` prefix
# and targets the git-runner host daemon by its bare backend label. On the native
# forge one label == one host daemon == one backend:
# cuda -> spark (NVIDIA GB10, sm_121)
# rocm -> evo (AMD Strix Halo gfx1151, ROCm 7.x)
# metal -> dbc (Apple M4 Max)
#
# These boxes double as dev/bench machines, so this is NOT per-push: it runs
# nightly and on demand (`gh workflow run gpu-tests`). --test-threads 1 + the
# gpu-guard step keep a single GPU consumer at a time (critical on ROCm, where
# concurrent inits wedge the kfd driver until reboot).
on:
workflow_dispatch:
schedule:
- cron: '0 8 * * *'
jobs:
test:
strategy:
fail-fast: false
matrix:
backend: [cuda, rocm, metal]
runs-on: ["${{ matrix.backend }}"]
timeout-minutes: 60
concurrency:
group: gpu-${{ matrix.backend }}
cancel-in-progress: false
steps:
- uses: actions/checkout@v6
- name: Remove cargo config (macOS ring crate fix)
if: matrix.backend == 'metal'
run: rm -f .cargo/config.toml
- uses: ./.github/actions/gpu-guard
- uses: dtolnay/rust-toolchain@stable
- name: Test (${{ matrix.backend }})
# The rocm test binary dynamically links libamdhip64.so.7 (ROCm 7.x) at run time. /opt/rocm/lib
# is NOT on the runner service's loader path -- there is no ld.so.conf.d entry for it, so only the
# interactive shell finds it (via the profile's `export LD_LIBRARY_PATH=/opt/rocm/lib:...`, which
# the systemd-launched runner does not inherit). Mirror that one export for the rocm arm so the
# binary loads; it is a no-op on cuda/metal (the dir is absent and the loader ignores it).
run: |
if [ "${{ matrix.backend }}" = "rocm" ]; then
export LD_LIBRARY_PATH="/opt/rocm/lib:${LD_LIBRARY_PATH:-}"
fi
cargo test -p hanzo-ml --features ${{ matrix.backend }} -- --test-threads 1
+132
View File
@@ -0,0 +1,132 @@
name: PyO3-Wheels
# Native (Hanzo Git) copy of .github/workflows/maturin.yml. The fork scans
# .hanzo/workflows FIRST; GitHub.com ignores .hanzo/, so this is inert on GitHub
# and only runs on the native forge. Ported verbatim -- no `self-hosted` label to
# rewrite. The `linux`/`sdist` jobs run on the mapped `hanzo-build-linux-amd64`
# label; the `windows`/`macos` jobs use GitHub-hosted labels that need their own
# git-runner host daemons registered, or those legs queue on the native forge (a
# runner-provisioning step, not a workflow change).
on:
push:
branches:
- main
tags:
- '*'
paths:
- hanzo-ml-pyo3/**
pull_request:
paths:
- hanzo-ml-pyo3/**
workflow_dispatch:
permissions:
contents: read
env:
PROTOC_VERSION: '25.0'
FEATURES_FLAG: '--features onnx'
jobs:
linux:
runs-on: hanzo-build-linux-amd64
strategy:
fail-fast: false
matrix:
target: [x86_64, x86, aarch64, s390x, ppc64le]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: '3.13'
- name: Build wheels
uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1
with:
target: ${{ matrix.target }}
args: --release --out dist --find-interpreter
sccache: 'true'
manylinux: auto
working-directory: ./hanzo-ml-pyo3
- name: Upload wheels
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: wheels-linux-${{ matrix.target }}
path: ./hanzo-ml-pyo3/dist
windows:
runs-on: windows-latest
strategy:
matrix:
target: [x64, x86]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: '3.13'
architecture: ${{ matrix.target }}
- name: Install Protoc
uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3
with:
version: ${{ env.PROTOC_VERSION }}
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Build wheels
uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1
with:
target: ${{ matrix.target }}
args: --release --out dist --find-interpreter ${{ env.FEATURES_FLAG }}
sccache: 'true'
working-directory: ./hanzo-ml-pyo3
- name: Upload wheels
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: wheels-windows-${{ matrix.target }}
path: ./hanzo-ml-pyo3/dist
macos:
runs-on: macos-latest
strategy:
matrix:
target: [x86_64, aarch64]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: '3.13'
- name: Install Protoc
uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3
with:
version: ${{ env.PROTOC_VERSION }}
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Build wheels
uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1
with:
target: ${{ matrix.target }}
args: --release --out dist --find-interpreter ${{ env.FEATURES_FLAG }}
sccache: 'true'
working-directory: ./hanzo-ml-pyo3
- name: Upload wheels
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: wheels-macos-${{ matrix.target }}
path: ./hanzo-ml-pyo3/dist
sdist:
runs-on: hanzo-build-linux-amd64
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Protoc
uses: arduino/setup-protoc@a8b67ba40b37d35169e222f3bb352603327985b6 # v2
with:
version: ${{ env.PROTOC_VERSION }}
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Build sdist
uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1
with:
command: sdist
args: --out dist
working-directory: ./hanzo-ml-pyo3
- name: Upload sdist
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: wheels-sdist
path: ./hanzo-ml-pyo3/dist
+57
View File
@@ -0,0 +1,57 @@
name: Publish crates
# Native (Hanzo Git) copy of .github/workflows/publish.yml. The fork scans
# .hanzo/workflows FIRST; GitHub.com ignores .hanzo/, so this is inert on GitHub
# and only runs on the native forge. Ported verbatim -- runs on the mapped
# `hanzo-build-linux-amd64` label, no `self-hosted` label to rewrite.
#
# Publishes the hanzo-* candle-fork crates to crates.io in dependency order on a
# version tag (e.g. `0.11.4`). GPU build scripts can't run on crates.io builders,
# so we publish with --no-verify (downstream consumers build with their own SDK).
# Requires repo secret CARGO_REGISTRY_TOKEN (a crates.io API token).
on:
push:
tags:
- '[0-9]+.[0-9]+.[0-9]+'
workflow_dispatch: {}
jobs:
publish:
# `cargo publish --no-verify` is a pure upload (no GPU build). Seed the
# crates.io token as a repo/org secret CARGO_REGISTRY_TOKEN (from KMS).
runs-on: hanzo-build-linux-amd64
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Publish hanzo-* crates (dependency order)
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: |
set -u
if [ -z "${CARGO_REGISTRY_TOKEN:-}" ]; then
echo "::error::CARGO_REGISTRY_TOKEN is empty -- set it (from KMS) as a repo/org secret"; exit 1
fi
# GHA runs `run:` under `bash -e`; disable errexit so `out=$(cargo publish ...); rc=$?` can
# CAPTURE a non-zero rc and let the already-uploaded->skip logic run. Without this, the first
# already-published crate (e.g. hanzo-kernels) aborts the whole loop before reaching hanzo-ml.
set +e
# bottom-up: leaf kernels + ug + flash-attn-build, then hanzo-ml, then nn, then flash-attn
fail=0
for c in hanzo-kernels hanzo-metal-kernels hanzo-rocm-kernels hanzo-ug \
hanzo-flash-attn-build hanzo-ml hanzo-nn hanzo-flash-attn \
hanzo-flash-attn-v3; do
if [ -d "$c" ]; then
echo "::group::publish $c"
out=$( cd "$c" && cargo publish --no-verify 2>&1 ); rc=$?
echo "$out"
if [ "$rc" -ne 0 ]; then
if echo "$out" | grep -qiE 'already (uploaded|exists)|is already uploaded'; then
echo "::warning::$c already at this version -- skipping"
else
echo "::error::$c publish FAILED"; fail=1
fi
fi
echo "::endgroup::"
fi
done
exit "$fail"
+120
View File
@@ -0,0 +1,120 @@
# Native (Hanzo Git) copy of .github/workflows/rust-ci.yml. The Hanzo Git fork
# scans .hanzo/workflows FIRST
# (GIT__actions__WORKFLOW_DIRS=.hanzo/workflows,.github/workflows,.gitea/workflows);
# GitHub.com ignores .hanzo/, so this file is inert on GitHub and only runs on the
# native forge -- zero effect on the GitHub CI lane.
#
# Ported verbatim -- no `self-hosted` labels to rewrite here. The `fmt`/`clippy`
# jobs run on `hanzo-build-linux-amd64` (the git-runner maps that label). The
# `check`/`test` matrix uses GitHub-hosted labels: `ubuntu-latest`/`ubuntu-24.04`
# are mapped by the git-runner; `windows-latest`, `macOS-latest` and
# `ubuntu-24.04-arm` need their own git-runner labels / host daemons registered,
# or those legs queue on the native forge (a runner-provisioning step, not a
# workflow change).
on:
push:
branches:
- main
pull_request:
name: Continuous integration
jobs:
check:
name: Check
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, ubuntu-24.04, windows-latest, macOS-latest, ubuntu-24.04-arm]
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: "3.13"
- name: Remove cargo config (macOS ring crate fix)
if: runner.os == 'macOS'
run: rm -f .cargo/config.toml
- uses: dtolnay/rust-toolchain@stable
- name: Run macos with metal
if: matrix.os == 'macOS-latest'
run: cargo check --workspace --features metal
- name: Run normal cpu
if: matrix.os == 'ubuntu-latest' || matrix.os == 'windows-latest'
run: cargo check --workspace
- name: Run with avx2
if: matrix.os == 'ubuntu-24.04'
run: |
export RUSTFLAGS="-C target-feature=avx2"
cargo check --workspace
- name: Run with arm neon
if: matrix.os == 'ubuntu-24.04-arm'
run: |
export RUSTFLAGS="-C target-feature=neon"
cargo check --workspace
test:
name: Test Suite
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- name: Free disk space (Linux)
if: runner.os == 'Linux'
run: |
sudo rm -rf /opt/hostedtoolcache
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/local/lib/android
sudo rm -rf /opt/ghc
df -h
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: "3.13"
- name: Remove cargo config (macOS ring crate fix)
if: runner.os == 'macOS'
run: rm -f .cargo/config.toml
- uses: dtolnay/rust-toolchain@stable
- name: Install lld (Linux only)
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y lld
- name: Run tests (with lld on Linux)
if: runner.os == 'Linux'
env:
RUSTFLAGS: "-C link-arg=-fuse-ld=lld"
run: cargo test --workspace
- name: Run tests (Windows & macOS)
if: runner.os != 'Linux'
run: cargo test --workspace
fmt:
name: Rustfmt
runs-on: hanzo-build-linux-amd64
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- run: cargo fmt --all -- --check
clippy:
name: Clippy
runs-on: hanzo-build-linux-amd64
steps:
- uses: actions/checkout@v6
- name: Install C toolchain (runner image ships without cc)
run: |
if ! command -v cc >/dev/null || ! command -v pkg-config >/dev/null; then
(sudo apt-get update && sudo apt-get install -y build-essential pkg-config libssl-dev) \
|| (apt-get update && apt-get install -y build-essential pkg-config libssl-dev)
fi
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- run: cargo clippy --workspace --tests --examples --benches -- -D warnings