Skip to content

chore: qwen3tts standalone → hal0-slot migration prep (runbook + guarded script) #1659

chore: qwen3tts standalone → hal0-slot migration prep (runbook + guarded script)

chore: qwen3tts standalone → hal0-slot migration prep (runbook + guarded script) #1659

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
# Cancel superseded PR runs to save runners; never cancel a push to main
# (every main commit must build — required checks + the nightly greenness gate).
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
# Least privilege: CI only needs to read the repo.
permissions:
contents: read
jobs:
python:
runs-on: ubuntu-latest
# 3.14 is experimental until every dep ships 3.14 wheels — surface it
# without reddening main. No-op on PRs, which run 3.12 only.
continue-on-error: ${{ matrix.python-version == '3.14' }}
env:
# fastembed (cognee memory tests) honours FASTEMBED_CACHE_PATH
# (fastembed/common/utils.py). Pin it to a stable, cacheable dir so the
# warm step AND pytest share one location that actions/cache persists.
FASTEMBED_CACHE_PATH: ${{ github.workspace }}/.fastembed-cache
strategy:
fail-fast: false
matrix:
# PRs test the primary 3.12 only (fast feedback; matches the required
# "python (3.12)" status check). Pushes to main test the full supported
# range so Python-version drift still gates the protected branch.
python-version: ${{ (github.event_name == 'pull_request' && fromJSON('["3.12"]')) || fromJSON('["3.12","3.13","3.14"]') }}
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
cache: pip
- name: Install system deps
# ffmpeg backs the in-container moonshine audio decoder
# (packaging/toolbox/moonshine/moonshine_server.py). The redaction
# tests in tests/providers/test_moonshine_server.py exercise the
# real subprocess path; without ffmpeg they hit FileNotFoundError
# instead of the CalledProcessError the code catches.
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends ffmpeg
- name: Install
run: pip install -e ".[dev]"
- name: Cache fastembed embedding model
# cognee memory tests (tests/memory/test_cognee_wrapper.py) embed via
# fastembed, which downloads qdrant/bge-small-en-v1.5-onnx-q (~64 MB)
# into FASTEMBED_CACHE_PATH on first use. That per-run download
# intermittently slow-fails (could-not-load-model-from-any-source) and
# gated unrelated PRs (#442, #445). The model id is fixed, so a static
# key caches once and restores forever (bump -vN to refresh).
uses: actions/cache@v5
with:
path: ${{ github.workspace }}/.fastembed-cache
key: fastembed-bge-small-en-v1.5-v2
- name: Warm fastembed cache
# On a cache miss, download the model now. fastembed already retries 3x
# internally; we wrap each attempt in `timeout` so a stalled connection
# is bounded (~6 min) and retried fresh rather than hanging. Best-effort:
# on total failure, let pytest surface the error rather than masking it.
run: |
for attempt in 1 2 3; do
timeout 360 python -c "from fastembed import TextEmbedding; TextEmbedding('BAAI/bge-small-en-v1.5'); print('fastembed model warmed')" && exit 0
echo "::warning::fastembed warm attempt $attempt failed/timed out; retrying in 10s"
sleep 10
done
echo "::warning::fastembed warm-up failed after 3 attempts; cognee tests will surface it"
- name: Lint
run: ruff check src tests
- name: Format check
run: ruff format --check src tests
- name: Test
# Coverage (+ verbose) only on main pushes — it's a report, not a gate,
# so PRs skip the instrumentation overhead and run a quiet, faster suite.
run: pytest tests/ ${{ github.event_name == 'push' && '-v --cov=hal0 --cov-report=term-missing' || '-q' }}
ui:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ui
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: "22"
cache: npm
cache-dependency-path: ui/package-lock.json
- name: Install
run: npm ci
- name: Build
run: npm run build