|
| 1 | +# ─── BitNet CPU kernel CI ────────────────────────────────────────────────────── |
| 2 | +# |
| 3 | +# Builds the bitnet.cpp project with all L2-L5 math kernels enabled and runs |
| 4 | +# the kernel unit test suite. No model download (full smoke/perplexity happens |
| 5 | +# locally or in a separate nightly workflow). |
| 6 | +# |
| 7 | +# Why this exists: |
| 8 | +# - Clang ≥ 18 is required for SIMD kernels (per CLAUDE.md). |
| 9 | +# - 3rdparty/llama.cpp is a fork (branch `merge-dev`); submodule init is |
| 10 | +# critical for the build. |
| 11 | +# - GCC 14 may not be installed in the runner image; we explicitly install |
| 12 | +# libstdc++-14-dev so Clang 18 can find its system C++ headers. |
| 13 | +# |
| 14 | +# Trigger: every push to main, every PR. |
| 15 | + |
| 16 | +name: kernel-ci |
| 17 | + |
| 18 | +on: |
| 19 | + push: |
| 20 | + branches: [main] |
| 21 | + pull_request: |
| 22 | + branches: [main] |
| 23 | + workflow_dispatch: |
| 24 | + |
| 25 | +jobs: |
| 26 | + build-and-test: |
| 27 | + name: build + test (Ubuntu, clang-18) |
| 28 | + runs-on: ubuntu-24.04 |
| 29 | + timeout-minutes: 30 |
| 30 | + |
| 31 | + steps: |
| 32 | + - name: Checkout (with submodules) |
| 33 | + uses: actions/checkout@v4 |
| 34 | + with: |
| 35 | + submodules: recursive |
| 36 | + fetch-depth: 1 |
| 37 | + |
| 38 | + - name: Apply dispatch patch (combined 05) |
| 39 | + run: | |
| 40 | + echo "Applying combined patch 05 (L3 ACDC + L5 HRR + L4 K_i8 cache + FaseIII rect + LLaMA gate)..." |
| 41 | + chmod +x ./scripts/apply-dispatch-patches.sh |
| 42 | + ./scripts/apply-dispatch-patches.sh |
| 43 | + echo "Verifying idempotence..." |
| 44 | + ./scripts/apply-dispatch-patches.sh --check |
| 45 | + shell: bash |
| 46 | + |
| 47 | + - name: Install build dependencies |
| 48 | + run: | |
| 49 | + sudo apt-get update |
| 50 | + sudo apt-get install -y \ |
| 51 | + clang-18 \ |
| 52 | + cmake \ |
| 53 | + ninja-build \ |
| 54 | + libstdc++-14-dev \ |
| 55 | + python3 \ |
| 56 | + python3-pip \ |
| 57 | + python3-venv |
| 58 | +
|
| 59 | + - name: Create Python venv and install test dependencies |
| 60 | + # Use an isolated venv to avoid PEP-668 conflicts between apt numpy/scipy |
| 61 | + # and PyPI packages (safetensors has no numpy dep; still isolate for safety). |
| 62 | + run: | |
| 63 | + python3 -m venv .venv |
| 64 | + .venv/bin/pip install --no-cache-dir numpy scipy safetensors |
| 65 | +
|
| 66 | + - name: Configure (Release, all kernels + ACDC_RECT) |
| 67 | + # BITNET_ENABLE_ACDC_RECT defaults ON → 16 tests in CI. |
| 68 | + # Python3_EXECUTABLE points to the venv so test_extract_acdc_diagonal |
| 69 | + # finds the installed numpy/safetensors. |
| 70 | + run: | |
| 71 | + cmake -B build -G Ninja \ |
| 72 | + -DCMAKE_C_COMPILER=clang-18 \ |
| 73 | + -DCMAKE_CXX_COMPILER=clang++-18 \ |
| 74 | + -DCMAKE_BUILD_TYPE=Release \ |
| 75 | + -DBITNET_L2_WHT=ON \ |
| 76 | + -DBITNET_L3_ACDC=ON \ |
| 77 | + -DBITNET_L4_TROPICAL=ON \ |
| 78 | + -DBITNET_L5_HRR=ON \ |
| 79 | + -DBITNET_L6_RAG=ON \ |
| 80 | + -DBITNET_BUILD_TESTS=ON \ |
| 81 | + -DPython3_EXECUTABLE=$(pwd)/.venv/bin/python3 |
| 82 | +
|
| 83 | + - name: Build (compiles L1 + L2-L6 + all test targets) |
| 84 | + # Single build step — cmake discovers all targets from CMakeLists.txt. |
| 85 | + # No hardcoded --target list: avoids breakage when targets are added/renamed. |
| 86 | + run: cmake --build build --config Release -j$(nproc) |
| 87 | + |
| 88 | + - name: ctest — 16/16 kernel unit tests |
| 89 | + # BITNET_ENABLE_ACDC_RECT=ON (default) adds test_acdc_rect → 16 tests. |
| 90 | + # -j$(nproc): parallel execution; --output-on-failure: full log on fail. |
| 91 | + # PYTHON3_EXECUTABLE env var ensures the venv Python is used for |
| 92 | + # test_extract_acdc_diagonal (the add_test() COMMAND is cmake-resolved). |
| 93 | + run: | |
| 94 | + ctest --test-dir build \ |
| 95 | + --output-on-failure \ |
| 96 | + -j$(nproc) \ |
| 97 | + --timeout 120 |
| 98 | +
|
| 99 | + - name: NO-06 — telemetry audit (zero hits required) |
| 100 | + # Persona D4: binário nunca envia dados a endpoints externos. |
| 101 | + # Any match = CI failure. |
| 102 | + run: | |
| 103 | + HITS=$(grep -rn \ |
| 104 | + "telemetry\|upload_data\|send_metrics\|POST.*http" \ |
| 105 | + src/ utils/ run_inference*.py setup_env.py 2>/dev/null | \ |
| 106 | + grep -v "^Binary\|\.pyc" || true) |
| 107 | + if [ -n "$HITS" ]; then |
| 108 | + echo "::error::NO-06 FAIL — telemetry code found:" |
| 109 | + echo "$HITS" |
| 110 | + exit 1 |
| 111 | + fi |
| 112 | + echo "NO-06 PASS — 0 telemetry hits" |
| 113 | +
|
| 114 | + - name: NO-07 — cloud URL audit (zero hits in production code) |
| 115 | + # Ensures no hard-coded HTTP endpoints in C/C++ production sources. |
| 116 | + # URLs in comments (// http) and docs are excluded. |
| 117 | + run: | |
| 118 | + HITS=$(grep -rn "http://\|https://" \ |
| 119 | + src/ include/ \ |
| 120 | + --include="*.cpp" --include="*.h" | \ |
| 121 | + grep -v "//.*http\|/\*.*http\| \* http" || true) |
| 122 | + if [ -n "$HITS" ]; then |
| 123 | + echo "::error::NO-07 FAIL — cloud URLs in production code:" |
| 124 | + echo "$HITS" |
| 125 | + exit 1 |
| 126 | + fi |
| 127 | + echo "NO-07 PASS — 0 cloud URL hits" |
| 128 | +
|
| 129 | + - name: Cross-validation C ↔ Python (L3/L4/L5) |
| 130 | + # Verifies that the Python reference implementations match the C kernels |
| 131 | + # to rtol=1e-5, atol=1e-7. No model required. |
| 132 | + # --build-dir points to the cmake output dir (build/tests/), not the |
| 133 | + # local development build (build_tests/). |
| 134 | + run: | |
| 135 | + .venv/bin/python3 tests/cross_validation.py \ |
| 136 | + --all \ |
| 137 | + --build-dir build/tests |
| 138 | + echo "Cross-validation: PASS" |
| 139 | +
|
| 140 | + - name: Air-gapped boot test (AC-11) |
| 141 | + # Verifies that the built llama-cli binary runs without making any |
| 142 | + # network syscalls. This enforces persona D4 (no telemetry, no cloud) |
| 143 | + # at the CI level. The script is in tests/test_air_gapped_boot.sh; |
| 144 | + # it auto-skips if no model file is provided (which is the case in CI). |
| 145 | + # Result: SKIPPED is acceptable in CI; PASS requires a real model. |
| 146 | + run: | |
| 147 | + chmod +x tests/test_air_gapped_boot.sh |
| 148 | + bash tests/test_air_gapped_boot.sh 2>&1 | tee /tmp/air_gapped.log |
| 149 | + rc=${PIPESTATUS[0]} |
| 150 | + if [ $rc -ne 0 ]; then |
| 151 | + echo "::error::AC-11 air-gapped boot FAILED (rc=$rc)" |
| 152 | + cat /tmp/air_gapped.log |
| 153 | + exit $rc |
| 154 | + fi |
0 commit comments