From 775199e79bf18e75fd125902f712a90bf407cc0e Mon Sep 17 00:00:00 2001 From: Szymon Janikowski Date: Fri, 8 May 2026 18:12:17 +0200 Subject: [PATCH] ci: extend quality-gate matrix to Windows; fix codex backend test isolation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linux-only quality-gate hid three Windows-only test failures on main. The runner-test bug was fixed in #43; the remaining two were `Path.home()` isolation gaps in `tests/test_evaluator_backends.py`: setting `HOME` does not redirect `Path.home()` on Windows (which reads `USERPROFILE`), so `_has_chatgpt_oauth()` leaked into the dev's real `~/.codex/auth.json` and flipped the strip/promote branches in `_build_env`. - `tests/test_evaluator_backends.py`: replace `monkeypatch.setenv("HOME", ...)` with `monkeypatch.setattr("pathlib.Path.home", lambda: tmp_path)` in the five codex-oauth tests. Matches the pattern already used in `tests/test_runner.py:315,398`. Cross-platform; tests no longer touch real env state. - `.github/workflows/quality-gate.yml`: pytest job now runs on `[ubuntu-latest, windows-latest] × ["3.12", "3.13"]` with `fail-fast: false`. Lint/typecheck/audit stay single-OS — pure-Python checks with no platform variance. Verified locally on Windows: all 147 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/quality-gate.yml | 11 ++++++++--- tests/test_evaluator_backends.py | 10 +++++----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.github/workflows/quality-gate.yml b/.github/workflows/quality-gate.yml index 3dcea84..14dfab7 100644 --- a/.github/workflows/quality-gate.yml +++ b/.github/workflows/quality-gate.yml @@ -56,8 +56,13 @@ jobs: run: uv run mypy src/nasde_toolkit/ test: - name: Unit tests (pytest) - runs-on: ubuntu-latest + name: Unit tests (pytest) — ${{ matrix.os }} / py${{ matrix.python }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest] + python: ["3.12", "3.13"] steps: - uses: actions/checkout@v4 @@ -67,7 +72,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: "3.12" + python-version: ${{ matrix.python }} - name: Install dependencies run: uv sync --extra dev diff --git a/tests/test_evaluator_backends.py b/tests/test_evaluator_backends.py index efe865e..1d4150e 100644 --- a/tests/test_evaluator_backends.py +++ b/tests/test_evaluator_backends.py @@ -223,7 +223,7 @@ def test_codex_backend_validate_auth_succeeds_with_chatgpt_oauth( codex_home.mkdir() auth_file = codex_home / "auth.json" auth_file.write_text('{"auth_mode": "chatgpt", "tokens": {"access_token": "tok"}}') - monkeypatch.setenv("HOME", str(tmp_path)) + monkeypatch.setattr("pathlib.Path.home", lambda: tmp_path) backend = CodexSubprocessBackend() backend.validate_auth() @@ -231,7 +231,7 @@ def test_codex_backend_validate_auth_succeeds_with_chatgpt_oauth( def test_codex_backend_validate_auth_fails_without_credentials(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None: monkeypatch.delenv("OPENAI_API_KEY", raising=False) monkeypatch.delenv("CODEX_API_KEY", raising=False) - monkeypatch.setenv("HOME", str(tmp_path)) + monkeypatch.setattr("pathlib.Path.home", lambda: tmp_path) backend = CodexSubprocessBackend() with pytest.raises(SystemExit): backend.validate_auth() @@ -263,7 +263,7 @@ def test_codex_backend_env_strips_api_keys_when_oauth_present( codex_home = tmp_path / ".codex" codex_home.mkdir() (codex_home / "auth.json").write_text('{"auth_mode": "chatgpt", "tokens": {"access_token": "tok"}}') - monkeypatch.setenv("HOME", str(tmp_path)) + monkeypatch.setattr("pathlib.Path.home", lambda: tmp_path) monkeypatch.setenv("CODEX_API_KEY", "sk-stale-key-from-dotenv") monkeypatch.delenv("OPENAI_API_KEY", raising=False) @@ -278,7 +278,7 @@ def test_codex_backend_env_promotes_codex_key_to_openai_key( monkeypatch: pytest.MonkeyPatch, tmp_path: Path, ) -> None: - monkeypatch.setenv("HOME", str(tmp_path)) + monkeypatch.setattr("pathlib.Path.home", lambda: tmp_path) monkeypatch.setenv("CODEX_API_KEY", "sk-codex-key") monkeypatch.delenv("OPENAI_API_KEY", raising=False) @@ -296,7 +296,7 @@ def test_codex_backend_env_preserves_openai_key_priority( codex_home = tmp_path / ".codex" codex_home.mkdir() (codex_home / "auth.json").write_text('{"auth_mode": "chatgpt", "tokens": {"access_token": "tok"}}') - monkeypatch.setenv("HOME", str(tmp_path)) + monkeypatch.setattr("pathlib.Path.home", lambda: tmp_path) monkeypatch.setenv("OPENAI_API_KEY", "sk-explicit-openai-key") monkeypatch.setenv("CODEX_API_KEY", "sk-stale-codex-key")