fix(ci): build base native extension for OpenAPI lint (#49136)

* fix(openapi): build native extension for base counts

* test(openapi): exercise native import in base worktree

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
yujonglee 2026-10-29 16:56:44 -07:00 • committed by GitHub
parent fd8b89fbec
commit e93e01ca4b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 52 additions and 0 deletions

View file

@ -101,6 +101,23 @@ def _install_termination_handlers() -> None:
signal.signal(termination, _exit_on_termination)
def _install_base_native(worktree: Path, repo_root: Path) -> None:
env: Final = {
**os.environ,
"CARGO_TARGET_DIR": str(
Path(os.environ.get("CARGO_TARGET_DIR", repo_root / "litellm-rust" / "target")).resolve()
),
}
_run(
[
"uv", "pip", "install", "--python", sys.executable, "--no-deps",
"--target", str(worktree.parent / "native-install"), "--editable", str(worktree),
],
cwd=worktree,
env=env,
)
def base_counts(ref: str, repo_root: Path = REPO_ROOT, checker: Path = CHECKER) -> Mapping[str, int]:
"""Rule counts at `ref`, measured with the *current* checker over the base tree."""
_install_termination_handlers()
@ -111,6 +128,7 @@ def base_counts(ref: str, repo_root: Path = REPO_ROOT, checker: Path = CHECKER)
(worktree / "scripts").mkdir(parents=True, exist_ok=True)
base_checker: Final = worktree / "scripts" / "check_openapi_docs.py"
shutil.copy(checker, base_checker)
_install_base_native(worktree, repo_root)
return count_by_rule(_check(worktree, base_checker))
finally:
# Teardown must never raise, or it masks the real error when the body failed.

View file

@ -0,0 +1,9 @@
from typing import Final
import openapi_docs_gate as gate
def test_base_counts_imports_native_extension_from_detached_worktree() -> None:
expected_counts: Final = dict(gate.count_by_rule(gate.head_violations()))
assert expected_counts
assert dict(gate.base_counts("HEAD")) == expected_counts

View file

@ -5,10 +5,35 @@ here is the checker output parse and `introduced`, the diff scan that names the
endpoint behind a breach.
"""
import subprocess
from pathlib import Path
from typing import Final
from unittest.mock import patch
import openapi_docs_gate as gate
import pytest
def test_base_counts_stops_when_the_native_build_fails(tmp_path: Path) -> None:
parent: Final = tmp_path / "oa_base"
parent.mkdir()
checker: Final = tmp_path / "check_openapi_docs.py"
checker.write_text("print('POST /v1/test OA001')\n")
with (
patch("openapi_docs_gate.tempfile.mkdtemp", return_value=str(parent)),
patch(
"subprocess.run",
side_effect=(
subprocess.CompletedProcess([], 0, stdout="", stderr=""),
subprocess.CompletedProcess([], 1, stdout="", stderr="build failed"),
subprocess.CompletedProcess([], 0, stdout="", stderr=""),
),
) as run,
patch("signal.signal"),
):
with pytest.raises(SystemExit, match="uv exited 1"):
gate.base_counts("HEAD", repo_root=tmp_path, checker=checker)
assert run.call_count == 3
def test_editing_the_checker_rekeys_the_base_counts(tmp_path: Path) -> None: