Skip to content

docs: gate the WASM exception scope and record the error-code changes #112

docs: gate the WASM exception scope and record the error-code changes

docs: gate the WASM exception scope and record the error-code changes #112

Workflow file for this run

name: Develop CI
# Fast feedback for day-to-day work on develop: formatting, linting, and a
# single-platform (Linux/Debug) build + test. The heavy, thorough validation
# (multi-OS native, ASan/UBSan, coverage, WASM) runs as the pre-release gate in
# ci.yml on pull requests to main and pushes to main.
on:
push:
branches: [develop]
tags-ignore: ['**']
paths-ignore:
- '**.md'
- 'docs/**'
- 'LICENSE'
- 'NOTICE'
pull_request:
branches: [develop]
paths-ignore:
- '**.md'
- 'docs/**'
- 'LICENSE'
- 'NOTICE'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
clang-format:
name: clang-format
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install clang-format
run: |
sudo apt-get update
sudo apt-get install -y clang-format
- name: Check formatting
run: |
git ls-files -z -- '*.h' '*.hpp' '*.c' '*.cpp' '*.mm' ':!:third_party/**' |
xargs -0 clang-format --dry-run --Werror
lint:
runs-on: ubuntu-latest
defaults:
run:
working-directory: bindings/wasm
steps:
- uses: actions/checkout@v7
- run: corepack enable
working-directory: .
- uses: actions/setup-node@v7
with:
node-version: 22
cache: yarn
cache-dependency-path: |
bindings/wasm/yarn.lock
bindings/node/yarn.lock
- run: yarn install --immutable
- run: yarn lint
- name: Lint and type-check the Node binding
# Source-only, so neither check needs the native addon built:
# tsconfig.test.json excludes dist/ and build/, and the tests import
# from ../src rather than the package entry point.
working-directory: bindings/node
run: |
yarn install --immutable
yarn lint
yarn test:types
- name: Lint the Python binding
# Pinned to the resolved version in requirements-dev.lock: an unpinned
# install lets a new ruff release fail an unrelated pull request.
# Invoked as a module so the check does not depend on pip's script
# directory being on PATH.
working-directory: .
run: |
python3 -m pip install --disable-pip-version-check ruff==0.15.14
python3 -m ruff check bindings/python/src bindings/python/tests
- name: Drift gates
# The mechanical cross-surface gates. All are stdlib-only and read-only.
# `gen_abi_layout.py --check` is the only one needing a compiler, and it
# builds a small probe from the public C headers rather than the
# project, so this job stays build-free. Invoked directly rather than
# through `make ci-local`, whose layout target wraps the same script in
# rye -- which the runner does not have and the script does not need.
#
# The layout check is the load-bearing one: it compares every ctypes
# Structure against sizeof/alignof/offsetof taken from the C headers,
# and a desync there segfaults the Python binding rather than failing a
# test.
working-directory: .
run: |
python3 tools/abi/check_abi_versions.py
python3 tools/generate_processor_types.py --check
python3 tools/abi/gen_abi_layout.py --check
python3 tools/conformance/check_public_contracts.py
python3 tools/api/check_request_object_coverage.py
python3 tools/conformance/check_cli_contract.py --schema
python3 -m unittest tests/conformance/test_cli_contract.py
python3 tools/parity/check_parity.py
build-and-test:
name: Native C++ (ubuntu-latest)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install Linux dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake build-essential libeigen3-dev
- name: Configure
run: cmake -B build -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON -DBUILD_CLI=OFF -DSONARE_WITH_FFMPEG=OFF
- name: Build
# Capped at 2 jobs: unbounded parallelism OOM-kills cc1plus on the
# 4-core/16GB hosted runners when compiling the large Debug test TUs.
run: cmake --build build --parallel 2
- name: Generate K-weighting reference fixture
run: make fixtures
- name: Test
run: ctest --test-dir build --output-on-failure --parallel
# `make test-golden` is deliberately not run here. The golden hashes
# quantize samples at 1e-6 before folding them into FNV-1a, which is
# finer than the float reproducibility across architectures and libm
# implementations, so a hash generated on one host cannot match another.
# They stay a same-environment regression check, run locally.
- name: Check capability catalog
run: make capability-catalog-check
examples:
name: Examples (Python and C++)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: '3.13'
- name: Install Linux dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake build-essential libeigen3-dev
python -m pip install numpy
- name: Generate a short WAV fixture
run: |
python - <<'PY'
import math
import struct
import wave
with wave.open('example-input.wav', 'wb') as output:
output.setnchannels(1)
output.setsampwidth(2)
output.setframerate(48000)
output.writeframes(b''.join(
struct.pack('<h', round(0.4 * 32767 * math.sin(2 * math.pi * 440 * i / 48000)))
for i in range(48000 * 3)
))
PY
- name: Build the Python shared library
run: |
cmake -B build-examples -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED=ON \
-DBUILD_TESTING=OFF -DBUILD_CLI=OFF -DSONARE_WITH_FFMPEG=OFF
cmake --build build-examples --target sonare_shared --parallel 2
cp build-examples/lib/libsonare.so bindings/python/src/libsonare/
- name: Run Python examples
env:
PYTHONPATH: bindings/python/src
run: |
python examples/python/analyze.py example-input.wav
python examples/python/master.py example-input.wav example-mastered.wav
python examples/python/midi_to_wav.py example-midi.wav
test -s example-mastered.wav
test -s example-midi.wav
- name: Build and run the C++ example
run: |
cmake -S examples/cpp -B build-examples-cpp -DBUILD_CLI=OFF -DBUILD_TESTING=OFF \
-DSONARE_WITH_FFMPEG=OFF
cmake --build build-examples-cpp --parallel 2
build-examples-cpp/analyze example-input.wav
python-wheel:
name: Python wheel (manylinux x86_64)
runs-on: ubuntu-latest
container: quay.io/pypa/manylinux_2_28_x86_64
steps:
- uses: actions/checkout@v7
- name: Build, audit, and test wheel
# The manylinux image has no system Eigen package; the top-level CMake
# FetchContent fallback supplies its header-only dependency.
run: |
cmake -B build-wheel -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED=ON \
-DBUILD_TESTING=OFF -DBUILD_CLI=OFF \
-DSONARE_WITH_FFMPEG=OFF
cmake --build build-wheel --target sonare_shared --config Release --parallel
cp build-wheel/lib/libsonare.so bindings/python/src/libsonare/
cd bindings/python
/opt/python/cp313-cp313/bin/python -m pip install wheel hatchling auditwheel pytest
/opt/python/cp313-cp313/bin/python -m pip wheel . --no-deps -w dist-raw/
auditwheel repair dist-raw/*.whl -w dist/ --plat manylinux_2_28_x86_64
auditwheel show dist/*.whl
/opt/python/cp313-cp313/bin/python -m pip install dist/*.whl
/opt/python/cp313-cp313/bin/python -c "import libsonare; libsonare.version()"
# The wheel is a shipped artifact, so run its suite against the
# repaired wheel here rather than for the first time at publish time.
# pytest is installed above; `-m "not slow"` comes from pyproject.
/opt/python/cp313-cp313/bin/python -m pytest tests/ -x -q