mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-27 14:17:10 -04:00
CI installed 'onnxruntime>=1.16.0' for the Rust ort runtime. That floor is 8 minor versions too low, and the failure mode below it is a silent hang. Why 1.24: ort-sys computes ORT_API_VERSION = 17 + one per enabled api-N feature, and Cargo features are additive across the graph. fastembed 5.17.3 enables api-24, so the constant resolves to 24 and ort rejects any lower runtime. Why it hangs instead of failing: on rejection ort calls Error::new() from inside load_dylib_from_path, which already runs inside the Once that setup_api() is initialising. Building the error re-enters that Once, and std::sync::Once blocks forever on re-entry. Reproduced in isolation with a bare Session::builder() and onnxruntime 1.21.1 - killed after >1h at 0% CPU, no output; ORT_DYLIB_PATH makes no difference. With 1.24.4 the same call returns in 1.2s and the kompress parity fixtures pass 21/21. Per @RubenAAA this is not limited to old runtimes: a box that resolves no libonnxruntime at all hangs identically (0.0% CPU, threads in futex_wait_queue, nothing onnx-shaped in /proc/<pid>/maps). Any failure inside load_dylib_from_path re-enters the Once, so a pin alone cannot close it. So this adds a pre-flight to the dylib step asserting, before any test runs, that onnxruntime imports, that its minor is >= 24, and that a libonnxruntime object exists under capi/. Each failure exits 1 with an ::error:: annotation naming the cause, instead of burning the 30-minute timeout with an empty log. Verified all three branches locally (absent -> rc=1, 1.21.1 -> rc=1, 1.24.4 -> rc=0) and in CI, where it resolved onnxruntime 1.28.0 and exported the .so path. pyproject.toml is deliberately untouched: bumping the floor there makes headroom-ai[all] unsatisfiable via a pillow chain (onnxruntime>=1.24 forces pillow>=10.3.0,<12.0 while [all] requires pillow>=12.3.0). The user-facing hazard via headroom/_ort.py remains open and needs its own change.
164 lines
5.5 KiB
YAML
164 lines
5.5 KiB
YAML
name: Network Diff Capture
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: network-diff-capture-${{ github.ref }}
|
|
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
|
|
|
env:
|
|
PY_VERSION: "3.12"
|
|
|
|
jobs:
|
|
offline:
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 20
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
|
|
- uses: actions/setup-python@v6
|
|
with:
|
|
python-version: ${{ env.PY_VERSION }}
|
|
|
|
- name: Install offline test tools
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
python -m pip install \
|
|
'tiktoken>=0.5.0' \
|
|
'pydantic>=2.0.0' \
|
|
'litellm==1.82.3' \
|
|
'click>=8.1.0' \
|
|
'rich>=13.0.0' \
|
|
'opentelemetry-api>=1.24.0' \
|
|
'ast-grep-cli>=0.30.0' \
|
|
'fastapi>=0.100.0' \
|
|
'uvicorn>=0.23.0' \
|
|
'httpx[http2]>=0.24.0' \
|
|
'openai>=2.14.0' \
|
|
'mcp>=1.0.0' \
|
|
'magika>=0.6.0' \
|
|
'zstandard>=0.20.0' \
|
|
'websockets>=13.0' \
|
|
'onnxruntime>=1.24' \
|
|
'transformers>=4.30.0' \
|
|
'watchdog>=4.0.0' \
|
|
'sqlite-vec>=0.1.6' \
|
|
pytest ruff mypy
|
|
|
|
- name: Lint capture code
|
|
run: ruff check headroom/capture headroom/cli/capture.py tests/test_network_diff_capture.py
|
|
|
|
- name: Format check capture code
|
|
run: ruff format --check headroom/capture headroom/cli/capture.py tests/test_network_diff_capture.py
|
|
|
|
- name: Type-check capture code
|
|
run: mypy headroom/capture/network_diff.py headroom/cli/capture.py
|
|
|
|
- name: Run capture tests
|
|
run: python -m pytest tests/test_network_diff_capture.py
|
|
|
|
- name: Validate compose model
|
|
env:
|
|
ANTHROPIC_API_KEY: dummy
|
|
run: docker compose -f docker/differential-network-capture/docker-compose.yml --profile run config
|
|
|
|
- name: Build Claude Code runner image
|
|
env:
|
|
ANTHROPIC_API_KEY: dummy
|
|
run: docker compose -f docker/differential-network-capture/docker-compose.yml --profile run build claude-direct
|
|
|
|
- name: Smoke Claude Code runner image
|
|
run: docker run --rm -e CLAUDE_COMMAND="claude --version" headroom-network-diff-claude-direct:latest
|
|
|
|
live-anthropic:
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 90
|
|
needs: offline
|
|
env:
|
|
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
CLAUDE_PROMPT: "Summarize this repository in one sentence. Keep the answer under 30 words."
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
|
|
- uses: actions/setup-python@v6
|
|
with:
|
|
python-version: ${{ env.PY_VERSION }}
|
|
|
|
- name: Install report dependencies
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
python -m pip install \
|
|
'tiktoken>=0.5.0' \
|
|
'pydantic>=2.0.0' \
|
|
'litellm==1.82.3' \
|
|
'click>=8.1.0' \
|
|
'rich>=13.0.0' \
|
|
'opentelemetry-api>=1.24.0' \
|
|
'ast-grep-cli>=0.30.0' \
|
|
'fastapi>=0.100.0' \
|
|
'uvicorn>=0.23.0' \
|
|
'httpx[http2]>=0.24.0' \
|
|
'openai>=2.14.0' \
|
|
'mcp>=1.0.0' \
|
|
'magika>=0.6.0' \
|
|
'zstandard>=0.20.0' \
|
|
'websockets>=13.0' \
|
|
'onnxruntime>=1.24' \
|
|
'transformers>=4.30.0' \
|
|
'watchdog>=4.0.0' \
|
|
'sqlite-vec>=0.1.6'
|
|
|
|
- name: Run live Claude Code differential capture
|
|
if: env.ANTHROPIC_API_KEY != ''
|
|
working-directory: docker/differential-network-capture
|
|
run: |
|
|
set -euo pipefail
|
|
mkdir -p captures
|
|
docker compose up -d --build mitm-direct mitm-headroom-upstream headroom-proxy mitm-headroom-client
|
|
trap 'docker compose --profile run down -v' EXIT
|
|
|
|
for i in $(seq 1 90); do
|
|
if docker compose exec -T headroom-proxy curl --fail --silent http://127.0.0.1:8787/readyz >/dev/null; then
|
|
break
|
|
fi
|
|
if [ "$i" -eq 90 ]; then
|
|
docker compose logs headroom-proxy
|
|
exit 1
|
|
fi
|
|
sleep 2
|
|
done
|
|
|
|
docker compose --profile run run --rm claude-direct
|
|
docker compose --profile run run --rm claude-headroom
|
|
|
|
- name: Report skipped live capture
|
|
if: env.ANTHROPIC_API_KEY == ''
|
|
run: |
|
|
echo "::warning title=Live network diff skipped::ANTHROPIC_API_KEY is not configured for this repository; offline harness checks ran, but live Claude Code capture was skipped."
|
|
mkdir -p docker/differential-network-capture/captures
|
|
cat > docker/differential-network-capture/captures/skipped.md <<'EOF'
|
|
# Live Network Diff Capture Skipped
|
|
|
|
`ANTHROPIC_API_KEY` is not configured for this repository.
|
|
EOF
|
|
|
|
- name: Generate network diff report
|
|
if: env.ANTHROPIC_API_KEY != ''
|
|
run: |
|
|
python -m headroom.cli capture network-diff \
|
|
--direct docker/differential-network-capture/captures/direct.jsonl \
|
|
--headroom docker/differential-network-capture/captures/headroom-client.jsonl \
|
|
--output docker/differential-network-capture/captures/report.md \
|
|
--json-output docker/differential-network-capture/captures/report.json
|
|
|
|
- name: Upload capture artifacts
|
|
if: always()
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: network-diff-capture-${{ github.run_number }}
|
|
path: docker/differential-network-capture/captures/
|
|
if-no-files-found: warn
|