Bump napi-build from 2.3.2 to 2.4.0 in /lib #79
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| jobs: | |
| test: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| cache-dependency-path: | | |
| frontend/package-lock.json | |
| app/package-lock.json | |
| mastervault-mcp-server/package-lock.json | |
| - name: Install frontend dependencies | |
| working-directory: frontend | |
| run: npm ci | |
| - name: Install app dependencies | |
| working-directory: app | |
| run: npm ci | |
| - name: Install mastervault-mcp-server dependencies | |
| working-directory: mastervault-mcp-server | |
| run: npm ci | |
| - name: Lint frontend | |
| working-directory: frontend | |
| run: npm run lint | |
| - name: Typecheck frontend | |
| working-directory: frontend | |
| run: npx tsc -b | |
| - name: Typecheck app | |
| working-directory: app | |
| run: npx tsc -p tsconfig.json --noEmit | |
| - name: Test frontend | |
| working-directory: frontend | |
| run: npm test | |
| - name: Test app | |
| working-directory: app | |
| run: npm test | |
| - name: Build frontend | |
| working-directory: frontend | |
| run: npm run build | |
| - name: Build app | |
| working-directory: app | |
| run: npm run build | |
| - name: Build bundled mastervault-mcp-server (the copy ModelForge packages) | |
| working-directory: mastervault-mcp-server | |
| run: npm run build:bundled | |
| - name: Smoke-test the bundled mastervault-mcp-server over stdio | |
| working-directory: mastervault-mcp-server | |
| run: | | |
| set -euo pipefail | |
| mkdir -p /tmp/mastervault-ci-vault | |
| echo '# CI test vault' > /tmp/mastervault-ci-vault/_orientation.md | |
| printf '%s\n%s\n' \ | |
| '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"ci","version":"1"}}}' \ | |
| '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \ | |
| | node dist-bundled/index.js /tmp/mastervault-ci-vault > worker-output.json | |
| cat worker-output.json | |
| test "$(grep -o 'mastervault_orient' worker-output.json | wc -l)" -ge 1 | |
| e2e: | |
| # Electron E2E tests spin up a real Electron process and a Vite preview | |
| # server per test, which is slower and flakier than the unit-test job | |
| # above — kept as its own job so a flaky e2e run never blocks/hides a | |
| # unit-test failure, and so it can be retried or skipped independently. | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| cache-dependency-path: | | |
| frontend/package-lock.json | |
| app/package-lock.json | |
| e2e/package-lock.json | |
| - name: Install frontend dependencies | |
| working-directory: frontend | |
| run: npm ci | |
| - name: Install app dependencies | |
| working-directory: app | |
| run: npm ci | |
| - name: Install e2e dependencies | |
| working-directory: e2e | |
| run: npm ci | |
| - name: Install Playwright browsers | |
| working-directory: e2e | |
| run: npx playwright install --with-deps chromium | |
| - name: Build frontend | |
| working-directory: frontend | |
| run: npm run build | |
| - name: Build app | |
| working-directory: app | |
| run: npm run build | |
| - name: Run e2e suite | |
| working-directory: e2e | |
| # Electron needs a real (or virtual) display even headless-ish, hence | |
| # xvfb — there's no way to launch a BrowserWindow without one on Linux. | |
| run: xvfb-run --auto-servernum npx playwright test | |
| - name: Upload Playwright report | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: playwright-report | |
| path: e2e/playwright-report | |
| retention-days: 7 | |
| rust: | |
| # lib/ (modelforge-native) is the napi-rs addon backing GGUF downloads | |
| # and, more recently, the JSON datastore/audit-hashing primitives (see | |
| # docs/ARCHITECTURE.md). fmt/clippy/cargo test only prove the Rust side | |
| # is correct on whichever OS runs them — they say nothing about whether | |
| # the resulting `.node` binary actually loads under Node on that OS, | |
| # which is a materially different failure mode (wrong ABI, missing | |
| # platform target, packaging mismatch). Previously this job only ran on | |
| # ubuntu-latest, so nothing in CI ever built or loaded the addon on | |
| # Windows or macOS despite installers shipping for both — see | |
| # docs/RUST_MIGRATION_ASSESSMENT.md's platform-matrix section. The | |
| # matrix below and the "napi build + require() smoke test" step close | |
| # that gap. | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, windows-latest, macos-latest] | |
| runs-on: ${{ matrix.os }} | |
| defaults: | |
| run: | |
| working-directory: lib | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install rustfmt and clippy | |
| run: rustup component add rustfmt clippy | |
| - uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| lib/target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('lib/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo- | |
| # fmt/clippy only need to run once — Rust source and formatting are | |
| # identical across OSes, so repeating this on all three runners would | |
| # just burn CI minutes for the same answer three times. | |
| - name: Format check | |
| if: matrix.os == 'ubuntu-latest' | |
| run: cargo fmt --check | |
| - name: Clippy | |
| if: matrix.os == 'ubuntu-latest' | |
| run: cargo clippy --all-targets -- -D warnings | |
| - name: Build | |
| run: cargo build --release | |
| - name: Test | |
| run: cargo test | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| cache-dependency-path: lib/package-lock.json | |
| - name: Install napi CLI | |
| run: npm ci | |
| - name: napi build (produces the real platform-specific .node binary) | |
| run: npm run build:debug | |
| # The actual gap this job exists to close: proves Node on *this* OS | |
| # can load the binary napi build just produced, not just that Cargo | |
| # compiled it. A wrong target triple, an ABI mismatch, or a packaging | |
| # error would fail cargo build's cross-compile silently-succeed case | |
| # but fail right here. | |
| - name: Load the built addon under Node and verify its exports | |
| shell: bash | |
| run: | | |
| node -e " | |
| const addon = require('../app/native'); | |
| const expected = ['downloadGgufFile', 'DownloadManager', 'readJsonFileNative', 'writeJsonFileAtomicNative', 'sha256HexNative', 'appendJsonArrayElementNative']; | |
| const missing = expected.filter((name) => !(name in addon)); | |
| if (missing.length > 0) { | |
| console.error('Native addon loaded but is missing expected exports:', missing); | |
| process.exit(1); | |
| } | |
| console.log('Native addon loaded successfully on ${{ matrix.os }} with all expected exports.'); | |
| " | |
| sbom: | |
| # Generates a CycloneDX SBOM per npm workspace so every release has an | |
| # auditable, machine-readable dependency manifest — required groundwork | |
| # for the supply-chain/provenance controls flagged in | |
| # docs/ENTERPRISE_READINESS_ASSESSMENT.md, and useful on its own for | |
| # answering "are we affected by CVE-X" without re-deriving the dependency | |
| # tree by hand. Runs independently of the test job so a flaky SBOM | |
| # generation never blocks the build/test signal. | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| cache-dependency-path: | | |
| frontend/package-lock.json | |
| app/package-lock.json | |
| mastervault-mcp-server/package-lock.json | |
| - name: Install frontend dependencies | |
| working-directory: frontend | |
| run: npm ci | |
| - name: Install app dependencies | |
| working-directory: app | |
| run: npm ci | |
| - name: Install mastervault-mcp-server dependencies | |
| working-directory: mastervault-mcp-server | |
| run: npm ci | |
| - name: Generate SBOM (frontend) | |
| working-directory: frontend | |
| run: npx --yes @cyclonedx/cyclonedx-npm --output-file ../sbom-frontend.cdx.json | |
| - name: Generate SBOM (app) | |
| working-directory: app | |
| run: npx --yes @cyclonedx/cyclonedx-npm --output-file ../sbom-app.cdx.json | |
| - name: Generate SBOM (mastervault-mcp-server) | |
| working-directory: mastervault-mcp-server | |
| run: npx --yes @cyclonedx/cyclonedx-npm --output-file ../sbom-mastervault-mcp-server.cdx.json | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: sbom | |
| path: sbom-*.cdx.json | |
| retention-days: 90 | |
| python-recommender: | |
| # ml/hardware-recommender/ is a standalone project (its own venv, own | |
| # train/download-dataset scripts) that isn't part of the app's build — | |
| # only its exported ONNX model ships with the app | |
| # (app/python/artifacts/hardware_recommender.onnx), loaded at runtime by | |
| # app/python/recommender_worker.py. This job is deliberately scoped to | |
| # what release publishing actually depends on: the recommender package's | |
| # own unit tests (data/feature encoding logic, no dataset or GPU needed) | |
| # and a smoke test that the packaged worker script can actually load the | |
| # shipped artifact and answer a request — never train.py or | |
| # download_dataset.py, which need a real (large) dataset pull. | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| cache: pip | |
| cache-dependency-path: ml/hardware-recommender/requirements.txt | |
| - name: Install dependencies (CPU-only torch for ML tests) | |
| working-directory: ml/hardware-recommender | |
| # torch's CPU wheels live on a separate index from the rest of | |
| # PyPI. Install it separately to keep the training/test stack CPU-only | |
| # and avoid a multi-gigabyte CUDA wheel download on a GPU-less runner; | |
| # the packaged app uses ONNX Runtime for inference and does not ship | |
| # torch in its managed runtime. | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install --only-binary=:all: --index-url https://download.pytorch.org/whl/cpu torch==2.13.0 | |
| # pip parses comments and blank lines correctly. Passing the file | |
| # through shell command substitution turned the first comment into | |
| # a literal `#` requirement and failed the job. | |
| python -m pip install --only-binary=:all: -r requirements.txt | |
| - name: Run hardware-recommender unit tests | |
| working-directory: ml/hardware-recommender | |
| run: python -m pytest tests/ -q | |
| - name: Verify the packaged model artifacts exist | |
| run: | | |
| test -f app/python/artifacts/hardware_recommender.onnx | |
| test -f app/python/artifacts/hardware_recommender.onnx.sha256 | |
| test -f app/python/artifacts/hardware_recommender.meta.json | |
| - name: Smoke-test the packaged recommender worker against the shipped artifact | |
| working-directory: app/python | |
| run: | | |
| printf '%s\n%s\n' \ | |
| '{"protocol":1,"id":"1","method":"health","params":{}}' \ | |
| '{"protocol":1,"id":"2","method":"recommend","params":{"model_params_b":7,"ram_gb":16,"vram_gb":8,"cpu_cores":8,"platform":"linux","gpu_backend":"cuda"}}' \ | |
| | python recommender_worker.py > worker-output.json | |
| cat worker-output.json | |
| test "$(grep -o '"ok": *true' worker-output.json | wc -l)" -eq 2 |