Repository navigation
126 lines (119 loc) · 5.01 KB
/
Copy pathci.yml
File metadata and controls
126 lines (119 loc) · 5.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
name: CI
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
actionlint:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- name: Actionlint
uses: docker://rhysd/actionlint:1.7.12
test:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Check whitespace
run: |
set -euo pipefail
if [ "${{ github.event_name }}" = "pull_request" ]; then
git fetch --no-tags --depth=1 origin "${{ github.base_ref }}"
git diff --check "origin/${{ github.base_ref }}...HEAD"
else
git diff-tree --check --no-commit-id --root -r HEAD
fi
- uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install dependencies
run: |
set -euo pipefail
python -m pip install --upgrade pip
python -m pip install -e '.[test,ai]'
- name: Verify dependencies
run: python -m pip check
- name: Run tests
run: python -m pytest -q
- name: Ruff
run: ruff check .
- name: Build package
run: python -m build
native-audit:
runs-on: ubuntu-latest
timeout-minutes: 20
env:
UV_PROJECT_ENVIRONMENT: .venv
UV_PYTHON_DOWNLOADS: never
PYTEST_DISABLE_PLUGIN_AUTOLOAD: "1"
PYTHONDONTWRITEBYTECODE: "1"
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install fixed CI resolver
run: python -m pip --isolated install --index-url https://pypi.org/simple "uv==0.11.19"
- name: Install locked optional native SDK
run: |
set -euo pipefail
uv sync --locked --python "$(command -v python)" --extra test --extra native-audit
uv pip check --python "$UV_PROJECT_ENVIRONMENT/bin/python"
- name: Verify installed native SDK identity without requests
run: |
"$UV_PROJECT_ENVIRONMENT/bin/python" - <<'PY'
import json
from importlib.metadata import distribution
from pathlib import Path
import tomllib
from ai_service.client import TaskClient
from ai_service.scenarios import compile_task_spec
requirement, = tomllib.loads(Path("pyproject.toml").read_text())["project"]["optional-dependencies"]["native-audit"]
expected = requirement.rsplit("@", 1)[1]
sdk = distribution("quant-ai-service")
source = json.loads(sdk.read_text("direct_url.json"))
if sdk.version != "2.0.13" or source["vcs_info"]["commit_id"] != expected:
raise SystemExit("native SDK distribution identity mismatch")
if TaskClient.__module__ != "ai_service.client" or not callable(compile_task_spec):
raise SystemExit("native SDK import capability mismatch")
print(f"Native SDK {sdk.version}, commit={expected}; imports verified, no requests")
PY
- name: Run native regressions offline with zero skips
run: |
"$UV_PROJECT_ENVIRONMENT/bin/python" - <<'PY'
import os
from pathlib import Path
import sys
import xml.etree.ElementTree as ET
import pytest
result_file = Path(os.environ["RUNNER_TEMP"]) / "native-audit.xml"
result_file.unlink(missing_ok=True)
blocked = []
def guard(event, args):
if event in {"socket.connect", "socket.bind", "socket.getaddrinfo", "subprocess.Popen", "os.system"}:
blocked.append(event)
raise RuntimeError("native-audit tests must use offline synthetic transports")
sys.addaudithook(guard)
code = pytest.main(["-vv", "--no-header", "-p", "no:cacheprovider",
"tests/test_ai_audit.py", "-k", "native", f"--junitxml={result_file}"])
if code:
raise SystemExit(code)
cases = list(ET.parse(result_file).iter("testcase"))
review = sum(case.get("name", "").startswith("test_native_review_") for case in cases)
skipped = sum(case.find("skipped") is not None for case in cases)
failures = sum(case.find("failure") is not None for case in cases)
errors = sum(case.find("error") is not None for case in cases)
if len(cases) != 114 or review != 45 or not all(case.get("name", "").startswith("test_native_") for case in cases):
raise SystemExit(f"native cohort mismatch: collected={len(cases)} review={review}")
if skipped or failures or errors:
raise SystemExit(f"native zero-skip gate failed: skipped={skipped} failures={failures} errors={errors}")
if blocked:
raise SystemExit(f"native tests attempted external I/O: {blocked}")
print("native-audit gate: collected=114 passed=114 review=45 skipped=0 errors=0 failures=0 external_io=0")
PY