Skip to content

Commit 9de6674

Browse files
committed
[MNT] run targeted tests first
1 parent 09a47ce commit 9de6674

File tree

1 file changed

+253
-5
lines changed

1 file changed

+253
-5
lines changed

.github/workflows/test.yml

Lines changed: 253 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,102 @@ concurrency:
1515
cancel-in-progress: true
1616

1717
jobs:
18+
# ===========================================================================
19+
# STAGE 0: Detect what changed (runs immediately)
20+
# ===========================================================================
21+
detect-changes:
22+
name: detect-changes
23+
runs-on: ubuntu-latest
24+
outputs:
25+
core: ${{ steps.filter.outputs.core }}
26+
sklearn: ${{ steps.filter.outputs.sklearn }}
27+
sktime: ${{ steps.filter.outputs.sktime }}
28+
skpro: ${{ steps.filter.outputs.skpro }}
29+
utils: ${{ steps.filter.outputs.utils }}
30+
docs: ${{ steps.filter.outputs.docs }}
31+
examples: ${{ steps.filter.outputs.examples }}
32+
any_src: ${{ steps.filter.outputs.any_src }}
33+
steps:
34+
- uses: actions/checkout@v4
35+
with:
36+
fetch-depth: 0
37+
38+
- name: Detect changed paths
39+
id: filter
40+
run: |
41+
if [ "${{ github.event_name }}" == "push" ]; then
42+
BASE_SHA="${{ github.event.before }}"
43+
# Handle initial push where before is all zeros
44+
if [ "$BASE_SHA" == "0000000000000000000000000000000000000000" ]; then
45+
BASE_SHA="HEAD~1"
46+
fi
47+
else
48+
BASE_SHA="${{ github.event.pull_request.base.sha }}"
49+
fi
50+
51+
CHANGED_FILES=$(git diff --name-only "$BASE_SHA" "${{ github.sha }}" || echo "")
52+
echo "Changed files:"
53+
echo "$CHANGED_FILES"
54+
55+
# Core: base module, main hyperactive files, or general tests
56+
if echo "$CHANGED_FILES" | grep -qE "^src/hyperactive/(base|tests|__init__|hyperactive)"; then
57+
echo "core=true" >> $GITHUB_OUTPUT
58+
else
59+
echo "core=false" >> $GITHUB_OUTPUT
60+
fi
61+
62+
# sklearn integration
63+
if echo "$CHANGED_FILES" | grep -q "^src/hyperactive/integrations/sklearn"; then
64+
echo "sklearn=true" >> $GITHUB_OUTPUT
65+
else
66+
echo "sklearn=false" >> $GITHUB_OUTPUT
67+
fi
68+
69+
# sktime integration
70+
if echo "$CHANGED_FILES" | grep -q "^src/hyperactive/integrations/sktime"; then
71+
echo "sktime=true" >> $GITHUB_OUTPUT
72+
else
73+
echo "sktime=false" >> $GITHUB_OUTPUT
74+
fi
75+
76+
# skpro integration
77+
if echo "$CHANGED_FILES" | grep -q "^src/hyperactive/integrations/skpro"; then
78+
echo "skpro=true" >> $GITHUB_OUTPUT
79+
else
80+
echo "skpro=false" >> $GITHUB_OUTPUT
81+
fi
82+
83+
# utils
84+
if echo "$CHANGED_FILES" | grep -q "^src/hyperactive/utils"; then
85+
echo "utils=true" >> $GITHUB_OUTPUT
86+
else
87+
echo "utils=false" >> $GITHUB_OUTPUT
88+
fi
89+
90+
# docs
91+
if echo "$CHANGED_FILES" | grep -qE "^docs/|\.rst$|\.md$"; then
92+
echo "docs=true" >> $GITHUB_OUTPUT
93+
else
94+
echo "docs=false" >> $GITHUB_OUTPUT
95+
fi
96+
97+
# examples
98+
if echo "$CHANGED_FILES" | grep -q "^examples/"; then
99+
echo "examples=true" >> $GITHUB_OUTPUT
100+
else
101+
echo "examples=false" >> $GITHUB_OUTPUT
102+
fi
103+
104+
# any source code
105+
if echo "$CHANGED_FILES" | grep -q "^src/"; then
106+
echo "any_src=true" >> $GITHUB_OUTPUT
107+
else
108+
echo "any_src=false" >> $GITHUB_OUTPUT
109+
fi
110+
111+
# ===========================================================================
112+
# STAGE 1: Fast checks (code-quality + doctest)
113+
# ===========================================================================
18114
code-quality:
19115
name: code-quality
20116
runs-on: ubuntu-latest
@@ -55,7 +151,7 @@ jobs:
55151
56152
test-no-extras:
57153
name: test-no-extras
58-
needs: [code-quality, doctest]
154+
needs: [targeted-tests-gate]
59155
strategy:
60156
matrix:
61157
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
@@ -93,7 +189,7 @@ jobs:
93189
94190
test-all-extras:
95191
name: test-all-extras
96-
needs: [code-quality, doctest]
192+
needs: [targeted-tests-gate]
97193
strategy:
98194
matrix:
99195
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
@@ -131,7 +227,7 @@ jobs:
131227
132228
test-sklearn-versions:
133229
name: test-sklearn-${{ matrix.sklearn-version }}-python-${{ matrix.python-version }}
134-
needs: [code-quality, doctest]
230+
needs: [targeted-tests-gate]
135231
runs-on: ubuntu-latest
136232

137233
strategy:
@@ -182,9 +278,161 @@ jobs:
182278
run: |
183279
python -m pytest --doctest-modules src/hyperactive/ -v
184280
281+
# ===========================================================================
282+
# STAGE 2: Targeted tests (only for changed areas, fast feedback)
283+
# ===========================================================================
284+
targeted-core:
285+
name: targeted-core
286+
needs: [code-quality, doctest, detect-changes]
287+
if: needs.detect-changes.outputs.core == 'true' || needs.detect-changes.outputs.any_src == 'false'
288+
runs-on: ubuntu-latest
289+
timeout-minutes: 10
290+
291+
steps:
292+
- uses: actions/checkout@v4
293+
294+
- name: Set up Python 3.11
295+
uses: actions/setup-python@v5
296+
with:
297+
python-version: "3.11"
298+
299+
- name: Install dependencies
300+
run: |
301+
python -m pip install --upgrade pip
302+
python -m pip install .[test]
303+
304+
- name: Run core tests
305+
run: |
306+
python -m pytest src/hyperactive/base/tests/ src/hyperactive/tests/ -v -p no:warnings
307+
308+
targeted-sklearn:
309+
name: targeted-sklearn
310+
needs: [code-quality, doctest, detect-changes]
311+
if: needs.detect-changes.outputs.sklearn == 'true'
312+
runs-on: ubuntu-latest
313+
timeout-minutes: 10
314+
315+
steps:
316+
- uses: actions/checkout@v4
317+
318+
- name: Set up Python 3.11
319+
uses: actions/setup-python@v5
320+
with:
321+
python-version: "3.11"
322+
323+
- name: Install dependencies
324+
run: |
325+
python -m pip install --upgrade pip
326+
python -m pip install .[all_extras,test]
327+
328+
- name: Run sklearn integration tests
329+
run: |
330+
python -m pytest src/hyperactive/integrations/sklearn/tests/ -v -p no:warnings
331+
332+
targeted-sktime:
333+
name: targeted-sktime
334+
needs: [code-quality, doctest, detect-changes]
335+
if: needs.detect-changes.outputs.sktime == 'true'
336+
runs-on: ubuntu-latest
337+
timeout-minutes: 10
338+
339+
steps:
340+
- uses: actions/checkout@v4
341+
342+
- name: Set up Python 3.11
343+
uses: actions/setup-python@v5
344+
with:
345+
python-version: "3.11"
346+
347+
- name: Install dependencies
348+
run: |
349+
python -m pip install --upgrade pip
350+
python -m pip install .[sktime-integration,test]
351+
352+
- name: Run sktime integration tests
353+
run: |
354+
python -m pytest src/hyperactive/integrations/sktime/tests/ -v -p no:warnings
355+
356+
targeted-skpro:
357+
name: targeted-skpro
358+
needs: [code-quality, doctest, detect-changes]
359+
if: needs.detect-changes.outputs.skpro == 'true'
360+
runs-on: ubuntu-latest
361+
timeout-minutes: 10
362+
363+
steps:
364+
- uses: actions/checkout@v4
365+
366+
- name: Set up Python 3.11
367+
uses: actions/setup-python@v5
368+
with:
369+
python-version: "3.11"
370+
371+
- name: Install dependencies
372+
run: |
373+
python -m pip install --upgrade pip
374+
python -m pip install .[sktime-integration,test]
375+
376+
- name: Run skpro integration tests
377+
run: |
378+
python -m pytest src/hyperactive/integrations/skpro/tests/ -v -p no:warnings
379+
380+
targeted-utils:
381+
name: targeted-utils
382+
needs: [code-quality, doctest, detect-changes]
383+
if: needs.detect-changes.outputs.utils == 'true'
384+
runs-on: ubuntu-latest
385+
timeout-minutes: 10
386+
387+
steps:
388+
- uses: actions/checkout@v4
389+
390+
- name: Set up Python 3.11
391+
uses: actions/setup-python@v5
392+
with:
393+
python-version: "3.11"
394+
395+
- name: Install dependencies
396+
run: |
397+
python -m pip install --upgrade pip
398+
python -m pip install .[test,test_parallel_backends]
399+
400+
- name: Run utils tests
401+
run: |
402+
python -m pytest src/hyperactive/utils/tests/ -v -p no:warnings
403+
404+
# Gate job: passes if all targeted tests pass OR are skipped (not failed)
405+
targeted-tests-gate:
406+
name: targeted-tests-gate
407+
needs: [targeted-core, targeted-sklearn, targeted-sktime, targeted-skpro, targeted-utils]
408+
if: always()
409+
runs-on: ubuntu-latest
410+
steps:
411+
- name: Check targeted test results
412+
run: |
413+
echo "Core: ${{ needs.targeted-core.result }}"
414+
echo "Sklearn: ${{ needs.targeted-sklearn.result }}"
415+
echo "Sktime: ${{ needs.targeted-sktime.result }}"
416+
echo "Skpro: ${{ needs.targeted-skpro.result }}"
417+
echo "Utils: ${{ needs.targeted-utils.result }}"
418+
419+
# Fail if any targeted test failed (not skipped)
420+
if [[ "${{ needs.targeted-core.result }}" == "failure" ]] || \
421+
[[ "${{ needs.targeted-sklearn.result }}" == "failure" ]] || \
422+
[[ "${{ needs.targeted-sktime.result }}" == "failure" ]] || \
423+
[[ "${{ needs.targeted-skpro.result }}" == "failure" ]] || \
424+
[[ "${{ needs.targeted-utils.result }}" == "failure" ]]; then
425+
echo "One or more targeted tests failed"
426+
exit 1
427+
fi
428+
echo "All targeted tests passed or were skipped"
429+
430+
# ===========================================================================
431+
# STAGE 3: Full test matrix (only after targeted tests pass)
432+
# ===========================================================================
185433
coverage:
186434
name: coverage
187-
needs: [code-quality, doctest]
435+
needs: [targeted-tests-gate]
188436
runs-on: ubuntu-latest
189437
timeout-minutes: 15
190438

@@ -214,7 +462,7 @@ jobs:
214462

215463
test-examples:
216464
name: test-examples
217-
needs: [code-quality, doctest]
465+
needs: [targeted-tests-gate]
218466
runs-on: ubuntu-latest
219467
timeout-minutes: 15
220468

0 commit comments

Comments
 (0)