Skip to content

Fix Windows preview process leak, and make the nightly heavy tests able to fail honestly #140

Fix Windows preview process leak, and make the nightly heavy tests able to fail honestly

Fix Windows preview process leak, and make the nightly heavy tests able to fail honestly #140

Workflow file for this run

name: CI Tests
# Pulls the published dependency bundle + the whisper add-on (binary + small
# model) and runs the Rust test suite plus the Flutter tests, EXCLUDING the
# heavy full-encode integration tests (those run in nightly.yml via
# `--tags heavy`). macOS is tested natively on both arm64 (macos-15) and x64
# (macos-15-intel); Windows on x64; Linux on x64 (ubuntu-24.04).
on:
push:
branches: [main]
paths-ignore: ['**.md', 'docs/**', 'licenses/**']
pull_request:
paths-ignore: ['**.md', 'docs/**', 'licenses/**']
workflow_dispatch:
concurrency:
group: ci-test-${{ github.ref }}
cancel-in-progress: true
env:
WHISPER_MODEL_URL: https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small.bin
jobs:
macos:
strategy:
fail-fast: false
matrix:
include:
- arch: arm64
runner: macos-15
- arch: x64
runner: macos-15-intel # last native Intel image, available until ~Aug 2027
runs-on: ${{ matrix.runner }}
env:
# Point the Flutter ToolLocator/DependencyManager at the repo-root deps
# (Platform.resolvedExecutable is the test runner under `flutter test`).
VAPOURBOX_DEPS_DIR: ${{ github.workspace }}/deps/macos-${{ matrix.arch }}
steps:
- uses: actions/checkout@v5
- name: Resolve deps tag
id: deps
run: |
TAG=$(python3 -c "import json;print(json.load(open('app/assets/deps-version.json'))['releaseTag'])")
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "ver=${TAG#deps-v}" >> "$GITHUB_OUTPUT"
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: stable
cache: true
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Download dependencies (${{ matrix.arch }})
env:
GH_TOKEN: ${{ github.token }}
run: |
VER="${{ steps.deps.outputs.ver }}"
ZIP="VapourBox-deps-${VER}-macos-${{ matrix.arch }}.zip"
mkdir -p deps/macos-${{ matrix.arch }}
gh release download "${{ steps.deps.outputs.tag }}" --pattern "$ZIP" --dir . --clobber
unzip -q -o "$ZIP" -d deps/macos-${{ matrix.arch }}
rm -f "$ZIP"
xattr -cr deps/macos-${{ matrix.arch }} 2>/dev/null || true
# The whisper small model (~466 MB) is architecture-independent; cache it.
- name: Cache whisper model
uses: actions/cache@v5
with:
path: .whisper-cache
key: whisper-ggml-small-v1
- name: Provision whisper add-on
run: |
mkdir -p .whisper-cache addons/whisper/models
if [ ! -f .whisper-cache/ggml-small.bin ]; then
echo "Downloading whisper small model..."
curl -L -o .whisper-cache/ggml-small.bin "$WHISPER_MODEL_URL"
fi
cp .whisper-cache/ggml-small.bin addons/whisper/models/ggml-small.bin
# whisper-cli comes from the same Homebrew bottle the app downloads.
brew install whisper-cpp
BP="$(brew --prefix)"
ln -sfn "$BP/opt/whisper-cpp/bin" addons/whisper/bin
ln -sfn "$BP/opt/whisper-cpp/lib" addons/whisper/lib
- name: Rust tests
# Debug build: DependencyLocator's upward search then finds the repo-root
# deps/ and addons/ (release mode looks under ~/Library).
run: cd worker && cargo test -- --nocapture
- name: Generate Dart serialization
run: |
cd app
flutter pub get
dart run build_runner build --delete-conflicting-outputs
- name: Flutter tests
# Excludes @Tags(['heavy']) — the full-encode integration tests, which
# run in nightly.yml. The script-only integration tests + unit tests run here.
run: cd app && flutter test --exclude-tags heavy
windows:
runs-on: windows-latest
env:
VAPOURBOX_DEPS_DIR: ${{ github.workspace }}/deps/windows-x64
steps:
- uses: actions/checkout@v5
- name: Resolve deps tag
id: deps
shell: bash
run: |
TAG=$(python -c "import json;print(json.load(open('app/assets/deps-version.json'))['releaseTag'])")
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "ver=${TAG#deps-v}" >> "$GITHUB_OUTPUT"
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: stable
cache: true
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Download dependencies (windows-x64)
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
VER="${{ steps.deps.outputs.ver }}"
ZIP="VapourBox-deps-${VER}-windows-x64.zip"
mkdir -p deps/windows-x64
gh release download "${{ steps.deps.outputs.tag }}" --pattern "$ZIP" --dir . --clobber
# The Windows deps zip uses backslash separators; 7-Zip handles that
# (info-zip `unzip` warns and exits non-zero, tripping `set -e`).
7z x "$ZIP" -o"deps/windows-x64" -y >/dev/null
rm -f "$ZIP"
- name: Cache whisper model
uses: actions/cache@v5
with:
path: .whisper-cache
key: whisper-ggml-small-v1
- name: Provision whisper add-on
shell: bash
run: |
mkdir -p .whisper-cache addons/whisper/models
if [ ! -f .whisper-cache/ggml-small.bin ]; then
curl -L -o .whisper-cache/ggml-small.bin "$WHISPER_MODEL_URL"
fi
cp .whisper-cache/ggml-small.bin addons/whisper/models/ggml-small.bin
curl -L -o /tmp/whisper-win.zip \
"https://github.com/ggml-org/whisper.cpp/releases/download/v1.8.3/whisper-bin-x64.zip"
7z x /tmp/whisper-win.zip -o/tmp/whisper-win -y >/dev/null
# Flatten: DependencyLocator expects addons/whisper/whisper-cli.exe
CLI=$(find /tmp/whisper-win -name "whisper-cli.exe" | head -1)
cp "$(dirname "$CLI")"/*.exe addons/whisper/ 2>/dev/null || true
cp "$(dirname "$CLI")"/*.dll addons/whisper/ 2>/dev/null || true
ls addons/whisper/
- name: Rust tests
run: cd worker && cargo test -- --nocapture
- name: Generate Dart serialization
run: |
cd app
flutter pub get
dart run build_runner build --delete-conflicting-outputs
- name: Flutter tests
# Excludes @Tags(['heavy']) — the full-encode integration tests, which
# run in nightly.yml. The script-only integration tests + unit tests run here.
run: cd app && flutter test --exclude-tags heavy
linux:
runs-on: ubuntu-24.04 # must match the deps-build runner: those binaries
# need its glibc, so an older runner cannot run them
env:
# Dart ToolLocator/DependencyManager honour this; the Rust locator does
# not (it uses the XDG path), so we also symlink it below.
VAPOURBOX_DEPS_DIR: ${{ github.workspace }}/deps/linux-x64
steps:
- uses: actions/checkout@v5
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y clang cmake ninja-build pkg-config \
libgtk-3-dev liblzma-dev unzip
- name: Resolve deps tag
id: deps
run: |
TAG=$(python3 -c "import json;print(json.load(open('app/assets/deps-version.json'))['releaseTag'])")
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "ver=${TAG#deps-v}" >> "$GITHUB_OUTPUT"
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: stable
cache: true
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Download dependencies (linux-x64)
env:
GH_TOKEN: ${{ github.token }}
run: |
VER="${{ steps.deps.outputs.ver }}"
ZIP="VapourBox-deps-${VER}-linux-x64.zip"
mkdir -p deps/linux-x64
gh release download "${{ steps.deps.outputs.tag }}" --pattern "$ZIP" --dir . --clobber
unzip -q -o "$ZIP" -d deps/linux-x64
rm -f "$ZIP"
- name: Cache whisper model
uses: actions/cache@v5
with:
path: .whisper-cache
key: whisper-ggml-small-v1
- name: Provision whisper add-on
run: |
mkdir -p .whisper-cache addons/whisper/models addons/whisper/bin
if [ ! -f .whisper-cache/ggml-small.bin ]; then
echo "Downloading whisper small model..."
curl -L -o .whisper-cache/ggml-small.bin "$WHISPER_MODEL_URL"
fi
cp .whisper-cache/ggml-small.bin addons/whisper/models/ggml-small.bin
# Download the same published whisper-cli the app fetches at runtime
# (the linux-x64 source in whisper-addon.json), so the test exercises
# the real add-on artifact + tar layout instead of building from
# source. Mirrors the Windows job, which curls its release zip.
WHISPER_URL=$(python3 -c "import json;print(json.load(open('app/assets/whisper-addon.json'))['binary']['platforms']['linux-x64']['url'])")
echo "whisper-cli: $WHISPER_URL"
curl -L -o /tmp/whisper-cli.tar.gz "$WHISPER_URL"
tar xzf /tmp/whisper-cli.tar.gz -C addons/whisper # => addons/whisper/bin/whisper-cli
chmod +x addons/whisper/bin/whisper-cli
ls -la addons/whisper/bin addons/whisper/models
- name: Stage deps/addons at XDG path for the Rust locator
# The Rust DependencyLocator on Linux only looks under
# ~/.local/share/VapourBox (no debug upward-search); the Dart tests use
# the repo-root copy. Symlink so a single checkout satisfies both.
run: |
mkdir -p "$HOME/.local/share/VapourBox"
ln -sfn "${{ github.workspace }}/deps" "$HOME/.local/share/VapourBox/deps"
ln -sfn "${{ github.workspace }}/addons" "$HOME/.local/share/VapourBox/addons"
- name: Rust tests
run: cd worker && cargo test -- --nocapture
- name: Generate Dart serialization
run: |
cd app
flutter pub get
dart run build_runner build --delete-conflicting-outputs
- name: Flutter tests
# Excludes @Tags(['heavy']) — the full-encode integration tests, which
# run in nightly.yml. The script-only integration tests + unit tests run here.
run: cd app && flutter test --exclude-tags heavy