Skip to content

Parakeet multitalker (#81) #154

Parakeet multitalker (#81)

Parakeet multitalker (#81) #154

Workflow file for this run

name: typescript-ci
# Every-PR gates for the TypeScript/Node binding (npm package transcribe-cpp).
# Thin per-binding workflow on the shared rails: the binding-agnostic C
# contracts are certified in native-ci.yml; this file adds only what the koffi
# FFI layer introduces.
#
# - ts-gates: the generated-FFI drift gate (generate.py --check, which covers
# _generated.py + transcribe.abihash + the TS _generated.ts),
# version-sync, and the TypeScript typecheck (tsc). No native
# build — fast, runs everywhere including forks.
# - ts-build: build a shared libtranscribe, then run the node:test suite and
# the 5 canonical examples against it on linux, macos, and windows.
#
# Two test tiers (requirements §4): the no-model tests (version/ABI/error
# mapping/device discovery) always run, including on forks. The model-gated
# tests (transcription, streaming, cancel, family extensions) un-skip only when
# the canary GGUFs are fetched — same fetch-canary action + HF_TOKEN gate the
# other bindings use — and skip cleanly otherwise.
#
# Scope: Node only for v1 (koffi is N-API-based; Bun/Deno are a documented
# follow-up). Path filters follow native-ci.yml's shape: the binding's own tree
# plus the native paths it loads from. Branch protection is OFF (project
# decision, 2026-06-13).
on:
push:
branches: [main]
paths: &paths
- "bindings/typescript/**"
- "src/**"
- "include/**"
- "ggml/**"
- "cmake/**"
- "CMakeLists.txt"
- "CMakePresets.json"
- "bindings/python/_generate/generate.py"
- "bindings/python/_generate/check_version_sync.py"
- ".github/workflows/typescript-ci.yml"
- ".github/actions/**"
pull_request:
paths: *paths
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
ts-gates:
# Cheap, native-build-free gates. generate.py --check needs libclang; users
# never do, because the FFI surface (_generated.ts) is committed.
runs-on: blacksmith-2vcpu-ubuntu-2404
steps:
- uses: actions/checkout@v6
- uses: astral-sh/setup-uv@v8.2.0 # for the python gate scripts
- uses: actions/setup-node@v4
with:
node-version: 22
- name: Install libclang (FFI generator)
run: sudo apt-get update && sudo apt-get install -y libclang-dev clang
- name: FFI drift gate (_generated.py + transcribe.abihash + _generated.ts)
run: uv run --no-project --with 'libclang==18.1.1' bindings/python/_generate/generate.py --check
- name: Version sync (header <-> every active manifest)
run: uv run --no-project python bindings/python/_generate/check_version_sync.py
- name: Install + typecheck
working-directory: bindings/typescript
run: |
npm install --no-audit --no-fund
npm run build
ts-build:
name: ts-build (${{ matrix.label }})
strategy:
fail-fast: false
matrix:
include:
- label: linux-x64
runner: blacksmith-2vcpu-ubuntu-2404
lib: libtranscribe.so
lib_subdir: src # .so is a LIBRARY artifact (build-shared/src)
cmake_flags: ""
# macOS arm64 on owned hardware; Metal on, embedded library (matches
# native-ci / the shipped macOS wheel posture).
- label: macos-arm64
runner: [self-hosted, macOS, ARM64]
lib: libtranscribe.dylib
lib_subdir: src
cmake_flags: "-DGGML_METAL=ON -DGGML_METAL_EMBED_LIBRARY=ON"
# Windows / MSVC (Blacksmith windows-2025, the wheel + rust-ci image).
# The first koffi load of this tree on Windows: it proves transcribe.dll
# and its co-located ggml DLLs resolve. koffi's first LoadLibraryW fails
# to find the sibling DLLs (Windows does not search a DLL's own dir for
# its deps), then retries with LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR, which
# does — so the package-local layout the loader/pack-platform ship is
# exactly what this exercises. transcribe.dll is a RUNTIME artifact
# (build-shared/bin, not src). MSVC + Ninja mirror rust-ci's
# Windows leg; no ccache there, so it's a cold ggml build every run.
- label: windows-x64
runner: blacksmith-2vcpu-windows-2025
lib: transcribe.dll
lib_subdir: bin # DLL is a RUNTIME artifact (build-shared/bin)
cmake_flags: ""
runs-on: ${{ matrix.runner }}
timeout-minutes: 60 # headroom for the cold MSVC ggml build on Windows
env:
# Gates the model-test tier: present on this repo's branches, absent on
# forks (where fetch-canary skips and the model tests skip cleanly).
HF_TOKEN: ${{ secrets.HF_TOKEN }}
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v4
with:
node-version: 22
- uses: denoland/setup-deno@v2
if: runner.os != 'Windows' # the Deno smoke below is non-Windows only
with:
deno-version: v2.x
- uses: astral-sh/setup-uv@v8.2.0 # fetch-canary fetches via uvx
- name: Install build deps (Linux)
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y cmake ninja-build ccache
# Windows toolchain mirrors rust-ci's Windows leg: cl.exe ambient for the
# Ninja generator (else CMake silently falls back to the image's MinGW gcc).
- name: Set up MSVC (cl.exe on PATH for the Ninja generator)
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64
- name: Install build deps (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
choco install ninja --no-progress -y
- name: Enable ccache launcher
if: runner.os == 'Linux'
run: |
echo "CMAKE_C_COMPILER_LAUNCHER=ccache" >> "$GITHUB_ENV"
echo "CMAKE_CXX_COMPILER_LAUNCHER=ccache" >> "$GITHUB_ENV"
- name: CPU ISA signature (ccache key)
if: runner.os == 'Linux'
run: echo "CPU_SIG=$(grep -m1 '^flags' /proc/cpuinfo | sha256sum | cut -c1-8)" >> "$GITHUB_ENV"
- name: ccache (native source build)
if: runner.os == 'Linux'
uses: actions/cache@v5
with:
path: ~/.cache/ccache
key: ccache-ts-build-${{ matrix.label }}-${{ env.CPU_SIG }}-${{ github.sha }}
restore-keys: ccache-ts-build-${{ matrix.label }}-${{ env.CPU_SIG }}-
- name: Build shared libtranscribe
# bash on every OS (Git Bash on the Windows runner) so the body and the
# GITHUB_ENV append are identical. $GITHUB_WORKSPACE, not $PWD: on Windows
# bash, $PWD is an MSYS /d/... path koffi/node can't open; the workspace
# var is a native path. lib_subdir selects bin (Windows RUNTIME) vs src.
shell: bash
run: |
cmake -B build-shared -G Ninja -DTRANSCRIBE_BUILD_SHARED=ON ${{ matrix.cmake_flags }}
cmake --build build-shared --target transcribe
echo "TRANSCRIBE_LIBRARY=$GITHUB_WORKSPACE/build-shared/${{ matrix.lib_subdir }}/${{ matrix.lib }}" >> "$GITHUB_ENV"
- name: Install + build the binding
working-directory: bindings/typescript
run: |
npm install --no-audit --no-fund
npm run build
# The canary GGUFs upgrade the suite from no-model gates to real
# transcription/streaming/cancel/extension coverage. jfk.wav ships in-repo;
# only the model paths need exporting (fetch-canary handles that).
#
# Windows now runs the full model tier too. It was previously no-model-only
# because loading a model spun up ggml's CPU threadpool, and on MSVC with
# OpenMP (vcomp) the runtime crashed (0xC0000005) at process exit under
# node/koffi. The build now defaults to ggml's native threadpool (no OpenMP
# — see the OpenMP CENTRAL POLICY in CMakeLists.txt), so there is no vcomp
# pool to crash at teardown, and the native barrier is MSVC-correct (the
# transcribe_threadpool_oversubscription test guards it). Re-enabled here.
- uses: ./.github/actions/fetch-canary
with:
hf-token: ${{ secrets.HF_TOKEN }}
- name: Conformance (no-model tier always; model tier when canary present)
working-directory: bindings/typescript
run: npm test
- name: Examples (CI-executed; §6 Rosetta set)
working-directory: bindings/typescript
shell: bash # the loop is bash syntax; Git Bash makes it identical on Windows
run: |
for ex in transcribe-file streaming batch backend-select error-handling; do
echo "=== example: $ex ==="
node "examples/$ex.mjs"
done
# Deno runs the SAME unmodified package via N-API (no adapter). Proves the
# binding is engine-portable; self-skips when the canary is absent. Non-
# Windows: the Windows leg's job is the Node + koffi DLL-resolution proof,
# and Deno-on-Windows N-API quirks shouldn't gate that signal.
- name: Deno smoke (run the package as-is under deno)
if: runner.os != 'Windows'
working-directory: bindings/typescript
run: deno run --allow-ffi --allow-read --allow-env --allow-sys examples/transcribe-file.mjs
- name: ccache stats
if: runner.os == 'Linux'
run: ccache -s | head -8