Files
OpenJarvis/.github/workflows/ci.yml
T
krypticmouseandClaude Opus 4.7 c06633e26f ci: add windows-latest job to empirically verify Windows code paths
The `test` job runs only on ubuntu-latest, so the Windows-specific
branches added for #373 (RAM detection via GlobalMemoryStatusEx) and
#293 (cp9xx → UTF-8 stdout reconfigure) were never *executed* in CI —
only unit-tested with mocks on Linux. `tests/hardware/test_hardware_profiles.py::test_total_ram_gb_windows`
has existed all along but is `skipif(sys.platform != "win32")`, so it
silently skipped on every run.

This adds a `test-windows` job that runs on a real Windows runner
(free for public repos) and:

1. Verifies `_total_ram_gb()` returns > 0 on actual Windows — executes
   the real `ctypes.windll.kernel32.GlobalMemoryStatusEx` path (#373).
   Runs as a pure-Python step BEFORE any Rust build, so a flaky
   toolchain install can't mask the result.
2. Runs `tests/hardware/test_hardware_profiles.py` (the now-unskipped
   Windows RAM test) and `tests/cli/test_cli.py` (the
   `test_windows_reconfigures_stdout_to_utf8` test from #293).
3. Builds + imports the `openjarvis_rust` PyO3 extension on Windows —
   the only CI job that does so. The extension is mandatory at runtime
   (`_rust_bridge.py` hard-errors without it), yet nothing else
   verified it compiles/imports on Windows. desktop.yml builds the
   Tauri app's Rust, not this extension.
4. Smoke-tests `jarvis --version`.

Scoped to the platform-relevant test files (not the full 6700-test
suite) so the job stays fast; the slow part is the Rust build, which
doubles as Windows-extension-build coverage.

All `run:` steps are static commands with no `github.event.*`
interpolation — no workflow-injection surface.

Note: #331 (desktop "did not become healthy" — uv sync error
surfacing) is GUI-triggered Tauri boot logic and isn't covered here;
its only automatable surface is string formatting, and testing it
needs the heavy webview build. Left as a possible follow-up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 15:03:11 +00:00

161 lines
4.6 KiB
YAML

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install uv
uses: astral-sh/setup-uv@v8.0.0
- name: Install dependencies
run: uv sync --extra dev --extra framework-comparison --extra server
- name: Ruff check
run: uv run ruff check src/ tests/
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cargo cache
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
rust/target
key: rust-${{ runner.os }}-${{ hashFiles('rust/Cargo.lock') }}
restore-keys: rust-${{ runner.os }}-
- name: Install uv
uses: astral-sh/setup-uv@v8.0.0
- name: Install dependencies
run: uv sync --extra dev --extra framework-comparison --extra server
- name: Build Rust extension
run: uv run maturin develop --manifest-path rust/crates/openjarvis-python/Cargo.toml
- name: Run tests
run: |
uv run pytest tests/ -v --tb=short -m "not live and not cloud" \
--cov=openjarvis \
--cov-report=term-missing \
--cov-report=xml \
--cov-fail-under=60
- name: Upload coverage report
if: always()
continue-on-error: true
timeout-minutes: 5
uses: actions/upload-artifact@v4
with:
name: coverage-xml
path: coverage.xml
if-no-files-found: warn
# Windows job — empirically exercises the platform-specific code paths that
# the Ubuntu `test` job can never reach: GlobalMemoryStatusEx RAM detection
# (#373) and the cp9xx -> UTF-8 stdout reconfigure (#293). Also the only CI
# job that builds + imports the mandatory `openjarvis_rust` PyO3 extension
# on Windows. Public repo -> Windows runner minutes are free.
#
# All `run:` steps use static commands only (no `github.event.*`
# interpolation), so there is no workflow-injection surface here.
test-windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install uv
uses: astral-sh/setup-uv@v8.0.0
- name: Install dependencies
run: uv sync --extra dev --extra server
# Pure-Python check — runs before the Rust build so a flaky toolchain
# install can never mask the actual RAM-detection verification.
- name: Verify Windows RAM detection (#373)
shell: bash
run: |
uv run python -c "from openjarvis.core.config import _total_ram_gb; ram = _total_ram_gb(); print(f'GlobalMemoryStatusEx RAM = {ram} GB'); assert ram > 0, f'Windows RAM detection returned {ram}, expected > 0'"
- name: Run Windows-specific tests (hardware + CLI)
shell: bash
run: |
uv run pytest tests/hardware/test_hardware_profiles.py tests/cli/test_cli.py -v -m "not live and not cloud"
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Build + import the PyO3 extension on Windows
shell: bash
run: |
uv run maturin develop --manifest-path rust/crates/openjarvis-python/Cargo.toml
uv run python -c "import openjarvis_rust; print('openjarvis_rust imports on Windows OK')"
- name: Smoke-test CLI
shell: bash
run: |
uv run jarvis --version
rust:
runs-on: ubuntu-latest
defaults:
run:
working-directory: rust
steps:
- uses: actions/checkout@v6
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- name: Cargo cache
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
rust/target
key: rust-${{ runner.os }}-${{ hashFiles('rust/Cargo.lock') }}
restore-keys: rust-${{ runner.os }}-
- name: Clippy
run: cargo clippy --workspace --all-targets -- -D warnings
- name: Test
run: cargo test --workspace