name: Sandbox IPC tests # Lightweight, fast-iterating job for the out-of-process plugin sandbox IPC # layer (src/audio/Sandbox). Deliberately separate from the heavyweight Build # matrix (build.yml): it needs only JUCE + a C++20 compiler — no cmake-js, # node-addon-api, ONNX, Python, or electron-builder — so it can run on every # push / PR that touches the sandbox without the full release toolchain. # # This is the iteration loop for the macOS sandbox port (issue #264): a # Linux-only developer pushes a branch and gets the macOS compiler + test # results they can't produce locally. The POSIX backend is shared between Linux # and macOS, so Linux gives fast signal and macOS confirms the Darwin-specific # paths (POSIX_SPAWN_CLOEXEC_DEFAULT, SO_NOSIGPIPE, the macOS shm/sem caveats). # # The TSan run on the threaded audio loopback is the highest-value artifact: # it validates the release/acquire memory ordering on arm64 (macos-14) that a # Linux-only dev cannot otherwise exercise. on: push: paths: - 'src/audio/Sandbox/**' - 'src/vst-host/**' - 'tests/sandbox/**' - '.github/workflows/sandbox.yml' pull_request: paths: - 'src/audio/Sandbox/**' - 'src/vst-host/**' - 'tests/sandbox/**' - '.github/workflows/sandbox.yml' workflow_dispatch: # Least privilege: these jobs only check out code and upload artifacts. # actions/checkout needs contents:read; upload-artifact uses its own runtime # token. Everything else defaults to none. permissions: contents: read jobs: sandbox-tests: strategy: fail-fast: false matrix: include: - os: ubuntu-22.04 - os: macos-14 runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 with: submodules: recursive # JUCE # JUCE on Linux needs the usual X11/ALSA dev headers even for juce_core's # transitive config; install the minimal set. (No-op on macOS.) - name: Install Linux deps if: runner.os == 'Linux' run: | sudo apt-get update sudo apt-get install -y --no-install-recommends \ ninja-build libasound2-dev libx11-dev libxext-dev libxinerama-dev \ libxrandr-dev libxcursor-dev libfreetype6-dev libfontconfig1-dev - name: Install Ninja (macOS) if: runner.os == 'macOS' run: brew install ninja # Build + run three ways: plain (Debug), ASan, TSan. Each is a fresh # configure of the JUCE-only standalone harness, then ctest. - name: Build + test (plain, ASan, TSan) shell: bash run: | set -euo pipefail for variant in plain address thread; do echo "::group::$variant" args=(-S tests/sandbox/standalone -B "build/sbx-$variant" -G Ninja \ -DCMAKE_BUILD_TYPE=Debug) if [[ "$variant" != "plain" ]]; then args+=(-DSLOPSMITH_SANITIZE="$variant") fi cmake "${args[@]}" cmake --build "build/sbx-$variant" # TSAN/ASAN: fail the job on any sanitizer diagnostic. TSAN_OPTIONS="halt_on_error=1" ASAN_OPTIONS="halt_on_error=1" \ ctest --test-dir "build/sbx-$variant" --output-on-failure echo "::endgroup::" done - name: Upload sandbox child log on failure if: failure() uses: actions/upload-artifact@v4 with: name: sandbox-logs-${{ matrix.os }} path: | build/sbx-*/Testing/**/*.log if-no-files-found: ignore # Heavier end-to-end job: builds a passthrough VST3 + the real # slopsmith-vst-host, spawns it from a host-side driver, and round-trips audio # over the shm ring (posix_spawn + fd inheritance + handshake + process + # state + shutdown). Separate from the unit job because it pulls in # juce_audio_processors / juce_gui_basics / the VST3 plugin client. sandbox-e2e: strategy: fail-fast: false matrix: include: - os: ubuntu-22.04 - os: macos-14 runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 with: submodules: recursive # Full JUCE Linux GUI/audio dep set (gui_basics + audio_processors). - name: Install Linux deps if: runner.os == 'Linux' run: | sudo apt-get update sudo apt-get install -y --no-install-recommends \ ninja-build xvfb \ libasound2-dev libjack-jackd2-dev libfreetype6-dev libfontconfig1-dev \ libx11-dev libxcomposite-dev libxcursor-dev libxext-dev \ libxinerama-dev libxrandr-dev libxrender-dev libglu1-mesa-dev \ mesa-common-dev libcurl4-openssl-dev libwebkit2gtk-4.1-dev - name: Install Ninja (macOS) if: runner.os == 'macOS' run: brew install ninja - name: Build e2e harness run: | cmake -S tests/sandbox/e2e -B build/e2e -G Ninja -DCMAKE_BUILD_TYPE=Debug cmake --build build/e2e # The vst-host loads a no-editor VST3, so no display is strictly needed; # run under xvfb on Linux anyway as insurance against any X11 touch in # juce_gui_basics init. macOS has a window server. - name: Run e2e (Linux, xvfb) if: runner.os == 'Linux' run: xvfb-run -a ctest --test-dir build/e2e --output-on-failure - name: Run e2e (macOS) if: runner.os == 'macOS' run: ctest --test-dir build/e2e --output-on-failure - name: Upload vst-host log on failure if: failure() uses: actions/upload-artifact@v4 with: name: sandbox-e2e-logs-${{ matrix.os }} path: | ${{ runner.temp }}/slopsmith-vst-host-*.log /tmp/slopsmith-vst-host-*.log if-no-files-found: ignore retention-days: 7