Skip to content

Commit 054b3fc

Browse files
committed
ci: parallelize regression tests per system using dynamic matrix
1 parent 07d4016 commit 054b3fc

4 files changed

Lines changed: 106 additions & 30 deletions

File tree

.github/workflows/pr.yaml

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ jobs:
2020

2121
steps:
2222
- name: Checkout
23-
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
23+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
2424

2525
- name: Set up Python ${{ matrix.python-version }}
26-
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
26+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
2727
with:
2828
python-version: ${{ matrix.python-version }}
2929
cache: pip
@@ -36,12 +36,44 @@ jobs:
3636
- name: Pytest (unit) • ${{ matrix.os }}, ${{ matrix.python-version }}
3737
run: python -m pytest tests/unit
3838

39+
discover-systems:
40+
name: Discover regression systems
41+
runs-on: ubuntu-24.04
42+
outputs:
43+
systems: ${{ steps.set-systems.outputs.systems }}
44+
45+
steps:
46+
- name: Checkout
47+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
48+
49+
- name: Set up Python 3.14
50+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
51+
with:
52+
python-version: "3.14"
53+
cache: pip
54+
55+
- name: Install testing dependencies
56+
run: |
57+
python -m pip install --upgrade pip
58+
python -m pip install -e .[testing]
59+
60+
- name: Discover systems
61+
id: set-systems
62+
run: |
63+
SYSTEMS=$(python -m tests.regression.list_systems)
64+
echo "systems=$SYSTEMS" >> $GITHUB_OUTPUT
65+
3966
regression-quick:
40-
name: Regression (fast)
41-
needs: unit
67+
name: Regression (fast) • ${{ matrix.system }}
68+
needs: [unit, discover-systems]
4269
runs-on: ubuntu-24.04
4370
timeout-minutes: 35
4471

72+
strategy:
73+
fail-fast: false
74+
matrix:
75+
system: ${{ fromJson(needs.discover-systems.outputs.systems) }}
76+
4577
steps:
4678
- name: Checkout
4779
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
@@ -63,20 +95,21 @@ jobs:
6395
python -m pip install --upgrade pip
6496
python -m pip install -e .[testing]
6597
66-
- name: Run fast regression tests (parallel)
98+
- name: Run fast regression tests (per system)
6799
run: |
68100
python -m pytest tests/regression \
69101
-m "not slow" \
70102
-n auto \
71103
--dist=loadscope \
104+
-k "${{ matrix.system }}" \
72105
-vv \
73106
--durations=20
74107
75108
- name: Upload artifacts (failure)
76109
if: failure()
77110
uses: actions/upload-artifact@v4
78111
with:
79-
name: quick-regression-failure
112+
name: quick-regression-failure-${{ matrix.system }}
80113
path: |
81114
.testdata/**
82115
/tmp/pytest-of-*/pytest-*/**
@@ -121,10 +154,10 @@ jobs:
121154

122155
steps:
123156
- name: Checkout
124-
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
157+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
125158

126159
- name: Set up Python 3.14
127-
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
160+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
128161
with:
129162
python-version: "3.14"
130163
cache: pip

.github/workflows/weekly-regression.yaml

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,21 @@ jobs:
2121
- name: Checkout
2222
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
2323

24+
- name: Set up Python 3.14
25+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
26+
with:
27+
python-version: "3.14"
28+
cache: pip
29+
30+
- name: Install testing dependencies
31+
run: |
32+
python -m pip install --upgrade pip
33+
python -m pip install -e .[testing]
34+
2435
- name: Generate system matrix
2536
id: set
2637
run: |
27-
systems=$(ls tests/regression/configs | jq -R -s -c 'split("\n")[:-1]')
38+
systems=$(python -m tests.regression.list_systems)
2839
echo "systems=$systems" >> $GITHUB_OUTPUT
2940
3041
regression:
@@ -56,14 +67,16 @@ jobs:
5667

5768
- name: Install testing dependencies
5869
run: |
59-
pip install --upgrade pip
60-
pip install -e .[testing]
70+
python -m pip install --upgrade pip
71+
python -m pip install -e .[testing]
6172
62-
- name: Run regression tests (slow)
73+
- name: Run regression tests (slow, per system)
6374
run: |
6475
pytest tests/regression \
6576
-k "${{ matrix.system }}" \
6677
--run-slow \
78+
-n auto \
79+
--dist=loadscope \
6780
-vv \
6881
--durations=20
6982

tests/regression/conftest.py

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ def pytest_addoption(parser: pytest.Parser) -> None:
99
1010
Adds options to control regression test execution, baseline updates,
1111
and debugging output.
12-
13-
Args:
14-
parser (pytest.Parser): Pytest CLI parser.
1512
"""
1613
parser.addoption(
1714
"--run-slow",
@@ -31,14 +28,17 @@ def pytest_addoption(parser: pytest.Parser) -> None:
3128
default=False,
3229
help="Print CodeEntropy stdout/stderr and paths for easier debugging.",
3330
)
31+
parser.addoption(
32+
"--system",
33+
action="append",
34+
default=None,
35+
help="Run only tests for specified system(s). Can be passed multiple times.",
36+
)
3437

3538

3639
def pytest_configure(config: pytest.Config) -> None:
3740
"""
3841
Register custom pytest markers.
39-
40-
Args:
41-
config (pytest.Config): Pytest configuration object.
4242
"""
4343
config.addinivalue_line("markers", "regression: end-to-end regression tests")
4444
config.addinivalue_line("markers", "slow: long-running tests (20-30+ minutes)")
@@ -48,19 +48,37 @@ def pytest_collection_modifyitems(
4848
config: pytest.Config, items: list[pytest.Item]
4949
) -> None:
5050
"""
51-
Modify collected test items to skip slow tests unless explicitly enabled.
52-
53-
Only tests marked with `@pytest.mark.slow` are skipped when the
54-
`--run-slow` flag is not provided.
55-
56-
Args:
57-
config (pytest.Config): Pytest configuration object.
58-
items (list[pytest.Item]): Collected test items.
51+
Modify collected test items to:
52+
1. Skip slow tests unless --run-slow is provided
53+
2. Filter tests by --system if specified
5954
"""
60-
if config.getoption("--run-slow"):
55+
if not config.getoption("--run-slow"):
56+
skip_slow = pytest.mark.skip(
57+
reason="Skipped slow test (use --run-slow to run)."
58+
)
59+
for item in items:
60+
if "slow" in item.keywords:
61+
item.add_marker(skip_slow)
62+
63+
selected_systems = config.getoption("--system")
64+
if not selected_systems:
6165
return
6266

63-
skip_slow = pytest.mark.skip(reason="Skipped slow test (use --run-slow to run).")
67+
filtered_items = []
68+
6469
for item in items:
65-
if "slow" in item.keywords:
66-
item.add_marker(skip_slow)
70+
callspec = getattr(item, "callspec", None)
71+
72+
case = None
73+
if callspec is not None:
74+
case = callspec.params.get("case")
75+
76+
# Keep non-parametrized tests
77+
if case is None:
78+
filtered_items.append(item)
79+
continue
80+
81+
if hasattr(case, "system") and case.system in selected_systems:
82+
filtered_items.append(item)
83+
84+
items[:] = filtered_items

tests/regression/list_systems.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import json
2+
3+
from tests.regression.cases import discover_cases
4+
5+
6+
def main():
7+
systems = sorted({case.system for case in discover_cases()})
8+
print(json.dumps(systems))
9+
10+
11+
if __name__ == "__main__":
12+
main()

0 commit comments

Comments
 (0)