-
Notifications
You must be signed in to change notification settings - Fork 7
138 lines (132 loc) · 5.97 KB
/
Copy pathpython-bindings.yml
File metadata and controls
138 lines (132 loc) · 5.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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