Parakeet multitalker (#81) #222
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: python-bindings | |
| # The EVERY-PR gate for the PYTHON binding: | |
| # - lint: generated-FFI drift gate (also regenerates the | |
| # binding-neutral include/transcribe.abihash) + | |
| # version-sync across the sources of truth. | |
| # - python-shared: a shared libtranscribe, the pure-C api_smoke as an | |
| # exported-symbol canary, and the Python test suite (model | |
| # tests un-skip when the canary GGUFs are fetchable). | |
| # | |
| # The binding-agnostic native gates (cpp-tests, cpp-tests-sanitized, | |
| # provider-dl-vulkan, link-smoke, posture-lint) moved to native-ci.yml | |
| # (2026-06-13, bindings-shared-infra): they certify the C contracts EVERY | |
| # binding relies on, not just Python's. Job names were preserved across | |
| # the move. | |
| # | |
| # The full WHEEL matrix (python-wheels.yml) deliberately does NOT run per PR: | |
| # it runs on workflow_dispatch and on every publish (rehearsal or release). | |
| # This workflow plus native-ci.yml is what must stay green on every change. | |
| on: | |
| push: | |
| branches: [main] | |
| paths: | |
| - "bindings/python/**" | |
| - "include/**" | |
| - "src/**" | |
| - "scripts/lib/**" | |
| - "tests/**" | |
| - "ggml/**" | |
| - "CMakeLists.txt" | |
| - ".github/workflows/python-bindings.yml" | |
| - ".github/actions/**" | |
| - "scripts/ci/vulkan_degradation_check.py" | |
| pull_request: | |
| paths: | |
| - "bindings/python/**" | |
| - "include/**" | |
| - "src/**" | |
| - "scripts/lib/**" | |
| - "tests/**" | |
| - "ggml/**" | |
| - "CMakeLists.txt" | |
| - ".github/workflows/python-bindings.yml" | |
| - ".github/actions/**" | |
| - "scripts/ci/vulkan_degradation_check.py" | |
| workflow_dispatch: | |
| # The generated FFI layer is pinned to one libclang so the drift gate's embedded | |
| # `libclang: <version>` line is reproducible across runs. | |
| env: | |
| LIBCLANG_PIN: "libclang==18.1.1" | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| lint: | |
| # Idle-friendly job on the Hetzner box (free); falls back to nothing — | |
| # an offline box fails bounded via the timeout. BEFORE the repo goes | |
| # public: move PR-triggered self-hosted jobs to hosted runners or gate | |
| # them on non-PR events (fork PRs + self-hosted = code exec on the box). | |
| runs-on: [self-hosted, Linux, X64, hetzner] | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: astral-sh/setup-uv@v8.2.0 | |
| - name: Install clang (libclang resource-dir headers) | |
| # Idempotent for the persistent self-hosted box: install once, no-op | |
| # after (and no sudo needed when clang is already present). | |
| run: | | |
| command -v clang >/dev/null || \ | |
| { sudo apt-get update && sudo apt-get install -y clang; } | |
| - name: Generated-FFI drift gate | |
| run: | | |
| uv run --no-project --with "$LIBCLANG_PIN" \ | |
| bindings/python/_generate/generate.py --check | |
| - name: Version sync (header / pyproject / __init__) | |
| run: uv run --no-project bindings/python/_generate/check_version_sync.py | |
| - name: GGUF writer layout | |
| run: uv run scripts/lib/test_gguf_writer.py | |
| python-shared: | |
| runs-on: blacksmith-2vcpu-ubuntu-2404 | |
| env: | |
| HF_TOKEN: ${{ secrets.HF_TOKEN }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: astral-sh/setup-uv@v8.2.0 | |
| - name: Install build deps | |
| run: sudo apt-get update && sudo apt-get install -y cmake ninja-build ccache | |
| - name: CPU ISA signature (segregates ccache across the heterogeneous fleet) | |
| # ggml builds with -march=native here (the dev posture under test); | |
| # ccache hashes the literal flag, not the ISA it resolves to, so a | |
| # cache compiled on a richer CPU SIGILLs on a weaker one. Key the | |
| # cache by the CPU's feature flags instead. | |
| run: echo "CPU_SIG=$(grep -m1 '^flags' /proc/cpuinfo | sha256sum | cut -c1-8)" >> "$GITHUB_ENV" | |
| - name: ccache (compile cache across runs) | |
| uses: actions/cache@v5 | |
| with: | |
| path: ~/.cache/ccache | |
| key: ccache-shared-${{ env.CPU_SIG }}-${{ github.sha }} | |
| restore-keys: ccache-shared-${{ env.CPU_SIG }}- | |
| # Shared build in the official-wheel posture (no OpenMP / system BLAS), so | |
| # the canary exercises the same configuration the provider wheels ship. | |
| - name: Configure (shared, wheel posture) | |
| run: | | |
| cmake -B build-shared -G Ninja -DCMAKE_BUILD_TYPE=Release \ | |
| -DTRANSCRIBE_BUILD_SHARED=ON \ | |
| -DTRANSCRIBE_USE_OPENMP=OFF \ | |
| -DTRANSCRIBE_USE_SYSTEM_BLAS=OFF \ | |
| -DCMAKE_C_COMPILER_LAUNCHER=ccache \ | |
| -DCMAKE_CXX_COMPILER_LAUNCHER=ccache | |
| - name: Build | |
| run: cmake --build build-shared -j | |
| - name: api_smoke (exported-symbol canary) + extension umbrella | |
| run: ctest --test-dir build-shared --output-on-failure | |
| # The canary model upgrades this lane from "imports and ABI" to a real | |
| # end-to-end transcription. Guarded on HF_TOKEN (the model repo is | |
| # private for now; forks have no token) — without it the model tests | |
| # skip cleanly, exactly as before. | |
| - uses: ./.github/actions/fetch-canary | |
| with: | |
| hf-token: ${{ secrets.HF_TOKEN }} | |
| - name: Python tests (real transcription when the canary is present) | |
| run: | | |
| # libtranscribe.so is dlopen'd by ctypes; help it resolve its sibling | |
| # ggml shared libs in the build tree. | |
| export LD_LIBRARY_PATH="$(find "$PWD/build-shared" -name '*.so' \ | |
| -printf '%h\n' | sort -u | tr '\n' ':')$LD_LIBRARY_PATH" | |
| # The loader auto-discovers build-shared/src/libtranscribe.so from the | |
| # repo root; the TRANSCRIBE_SMOKE_* vars (exported by fetch-canary | |
| # when HF_TOKEN exists) un-skip the offline AND streaming model | |
| # tests. The prompted (nemotron) streaming test still skips here — | |
| # its regression is pinned in CI by the sanitized C-level test. | |
| uv run --project bindings/python --extra test \ | |
| pytest bindings/python/tests -q -rs |