ci: canonical pair — hanzo.yml + forge caller

github.com has no runner for hanzo-build-linux-amd64, so a caller under
.github/workflows is a gate that can never be scheduled. This is the ~7-line
caller on the plane that can (git.hanzo.ai git-runner fleet), pinned @v1.

Also fixes the one defect the new gate found on its first run:
scripts/preprocess.py referenced `args.ffmpeg_path` at module scope, where
`args` does not exist — so the ffmpeg-not-on-PATH branch, whose entire job is
to recover, raised NameError instead. It meant the local `ffmpeg_path`
defined two lines above.

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
2026-08-06 02:39:17 -07:00
co-authored by Hanzo Dev
parent 4dceb0c044
commit 73dd7ff45d
3 changed files with 53 additions and 1 deletions
+15
View File
@@ -0,0 +1,15 @@
# Canonical caller — every knob lives in /hanzo.yml, none here.
# Runs on the git-runner fleet at git.hanzo.ai, the only pool serving these
# labels. github.com resolves only .github/workflows and has no runner for
# them, so a caller placed there is a gate that cannot be scheduled.
name: CI/CD
on:
push:
branches: [main]
tags: ['v*']
pull_request:
workflow_dispatch:
jobs:
cicd:
uses: hanzoai/ci/.hanzo/workflows/build.yml@v1
secrets: inherit
+37
View File
@@ -0,0 +1,37 @@
# Canonical CI/CD config for hanzoai/zen-dub — read by the hanzoai/ci reusable
# workflow (.hanzo/workflows/cicd.yml) and by platform.hanzo.ai.
#
# No image and no deploy: this is a GPU inference tree (torch + mmpose + mmcv +
# a face-detection stack, driven by app.py / inference.sh) whose weights are
# fetched by download_weights.sh, not vendored. It runs where the GPUs are.
#
# So the gate is scoped to what is TRUE without a GPU, and it says so rather
# than pretending otherwise. Installing requirements.txt on a CPU runner buys a
# multi-gigabyte torch download and still cannot execute a single frame, so the
# gate does not do it. What it does do is catch the two defects that ship in a
# Python tree with no import-time coverage:
#
# compileall — every module parses. A syntax error in a file only the
# inference path imports otherwise surfaces on the GPU box,
# an hour into a job.
# ruff E9,F821,F822,F823 — undefined names. Deliberately ONLY these: no
# style, no unused imports, nothing arguable. Every one of
# these is a NameError that WILL be raised the moment that
# line runs. That is not a lint opinion, it is a latent crash.
#
# It found one on its first run: scripts/preprocess.py used `args.ffmpeg_path`
# at module scope, where `args` does not exist — so the ffmpeg-not-on-PATH
# branch, the code whose whole job is to recover, crashed instead. Fixed in the
# same commit that added this file.
#
# What this gate does NOT claim: nothing here proves the model runs, or that
# the weights load, or that a frame renders. That is a GPU lane and belongs on
# a GPU runner. Better to state the boundary than to let a green tick imply it.
test:
- name: parse-and-undefined-names
run: |
set -euo pipefail
python3 -m compileall -q .
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uvx ruff check --select=E9,F821,F822,F823 .
+1 -1
View File
@@ -26,7 +26,7 @@ if not fast_check_ffmpeg():
print("Adding ffmpeg to PATH")
# Choose path separator based on operating system
path_separator = ';' if sys.platform == 'win32' else ':'
os.environ["PATH"] = f"{args.ffmpeg_path}{path_separator}{os.environ['PATH']}"
os.environ["PATH"] = f"{ffmpeg_path}{path_separator}{os.environ['PATH']}"
if not fast_check_ffmpeg():
print("Warning: Unable to find ffmpeg, please ensure ffmpeg is properly installed")