Repository navigation
207 lines (198 loc) · 7.66 KB
/
Copy pathci.yml
File metadata and controls
207 lines (198 loc) · 7.66 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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
name: CI
on:
pull_request:
push:
branches: [main]
schedule:
- cron: "0 4 * * *"
jobs:
lint:
name: lint / format / types
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: python -m pip install -e .[dev]
# Runs the same hooks contributors get from `pre-commit install`, at the
# same pinned tool versions, so CI and local checks cannot disagree.
# pytest is skipped here because the jobs below already run the suite
# across the full matrix rather than once.
- name: Run pre-commit hooks
env:
SKIP: pytest
run: pre-commit run --all-files --show-diff-on-failure
tests-unit:
name: unit / py${{ matrix.python-version }} / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04, ubuntu-24.04]
python-version: ["3.11", "3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: python -m pip install -e .[dev]
- name: Run baseline test suite
run: pytest -q -m "not soak"
tests-hardening:
name: hardening / ${{ matrix.slice }} / py${{ matrix.python-version }}
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
python-version: ["3.12"]
slice:
- adversarial
- runaway_cpu
- memory_exhaustion
- import_escape
- policy_bypass
- race
- crash_injection
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: python -m pip install -e .[dev]
- name: Run hardening slice
run: pytest -q tests/test_matrix_hardening.py -m "${{ matrix.slice }}"
tests-no-gil:
name: no-gil axis + race / py3.13t
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13t"
- name: Install dependencies
# cryptography/cffi cannot yet build wheels for the free-threaded 3.13
# build, so a normal ``.[dev]`` install aborts before any test runs.
# Install pyisolate without that dependency and rely on the suite's
# crypto stub (tests/conftest.py) so the tests actually execute.
# ``--no-deps`` skips *all* runtime deps, so re-add the pure-Python ones
# the import path needs (pyyaml, platformdirs) -- everything declared in
# ``project.dependencies`` except the unbuildable cryptography.
run: |
python -m pip install -e . --no-deps
python -m pip install pytest pyyaml platformdirs
- name: Validate no-GIL readiness axis (must pass on the free-threaded build)
# Deterministic: asserts the axis classifies parallel-cell vs scheduled-
# compartment correctly and that the free-threaded build reports itself
# as such. A regression here is a real release-gate bug, not flakiness.
run: pytest -q tests/test_nogil.py
- name: Run race tests under free-threaded build
# Concurrency stress can be timing-sensitive under free-threading; keep
# it advisory so a flaky race does not block, while the axis check above
# stays authoritative.
continue-on-error: true
run: pytest -q tests/test_matrix_hardening.py -m "race and no_gil"
tests-subinterpreter:
name: cells + fabric / py3.14t
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.14t"
- name: Install dependencies
# Same shape as the 3.13t job: install without the runtime deps that
# may not have free-threaded wheels yet, then re-add the pure-Python
# ones the import path needs. The suite's crypto stub (tests/conftest.py)
# covers the rest, and nothing in this job's scope needs real crypto.
run: |
python -m pip install -e . --no-deps
python -m pip install pytest pyyaml platformdirs
- name: Verify this build actually has sub-interpreters
# Every sub-interpreter test skips itself when the build cannot run it.
# That is right for the 3.11-3.13 matrix, but it means this job would
# report green on a runner that silently resolved to an older Python
# while testing nothing. Fail loudly instead.
run: |
python - <<'PY'
import sys
from pyisolate.runtime import subinterpreter as s
assert s.is_available(), f"no concurrent.interpreters on {sys.version}"
assert not sys._is_gil_enabled(), "expected a free-threaded build"
print("ok:", sys.version)
PY
- name: Run the sub-interpreter backend suite
run: pytest -q tests/test_subinterpreter_backend.py tests/test_supervisor.py
- name: Run the fabric suite
# Spawns worker processes and kills them; the runaway cases run inline
# here because the fabric reclaims them, unlike the in-process backend.
run: pytest -q tests/test_fabric.py
- name: Validate the no-GIL readiness axis on 3.14t
run: pytest -q tests/test_nogil.py
tests-soak:
name: soak / 2k spawn-kill cycles
if: github.event_name == 'schedule'
runs-on: ubuntu-24.04
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: python -m pip install -e .[dev]
- name: Run soak test
env:
PYISOLATE_SOAK_CYCLES: "2000"
run: pytest -q tests/test_matrix_hardening.py -m soak
tests-cross-kernel:
name: kernel smoke / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04, ubuntu-24.04]
steps:
- uses: actions/checkout@v4
- name: Kernel info
run: uname -a
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: python -m pip install -e .[dev]
- name: Run kernel-facing tests
run: pytest -q tests/test_bpf_manager.py tests/test_watchdog.py tests/test_cgroup.py
- name: Run process-backend confinement tests
run: pytest -q tests/test_process_backend.py tests/test_process_confinement.py tests/test_landlock.py
- name: Run live Landlock enforcement (kernels that support it)
env:
PYISOLATE_LIVE_LANDLOCK_TESTS: "1"
run: pytest -q tests/test_landlock.py
coverage:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: python -m pip install -e .[dev]
- name: Run tests with coverage
run: coverage run -m pytest -m "not soak"
# Fails when package coverage drops below the fail_under floor in
# pyproject.toml. Previously coverage was measured and uploaded but never
# checked, so it could regress without CI noticing.
- name: Check coverage against the floor
run: coverage report
- name: Generate coverage report
if: always()
run: coverage xml -o coverage.xml
- uses: actions/upload-artifact@v4
if: always()
with:
name: coverage-report
path: coverage.xml