@@ -9,6 +9,9 @@ name: Nightly Health
99# - Artifact "health-dashboard": index.html + status.json (90-day retention)
1010# - Artifact "health-test-results": JUnit XML + coverage reports (90-day retention)
1111#
12+ # The suite runs as two pytest invocations, core and tutorials, so that an
13+ # overrunning tutorial cannot destroy the core suite's results.
14+ #
1215# The dashboard is NOT deployed to GitHub Pages to avoid overwriting the
1316# documentation site published by docs.yml. Use the workflow status badge
1417# for a live pass/fail indicator in README:
@@ -41,10 +44,10 @@ jobs:
4144 timeout-minutes : 360
4245
4346 outputs :
44- # Captures the pytest step's actual outcome (success / failure / skipped)
45- # for the dashboard. The job itself is failed by the gate step at the end,
47+ # Captures the pytest steps' combined outcome (success / failure) for
48+ # the dashboard. The job itself is failed by the gate step at the end,
4649 # after the artifacts have been uploaded.
47- test-outcome : ${{ steps.run-tests.outcome }}
50+ test-outcome : ${{ ( steps.run-core- tests.outcome == 'success' && steps.run-tutorial-tests.outcome == 'success') && 'success' || 'failure' }}
4851
4952 steps :
5053 - name : Checkout code
@@ -154,26 +157,65 @@ jobs:
154157 print(f'OK: {n} GPU(s) visible to PyTorch and CuPy')
155158 "
156159
157- - name : Run health test suite
158- id : run-tests
159- # continue-on-error keeps the job running so artifacts are always uploaded.
160- # The step outcome (success/failure) is still captured and passed downstream.
160+ # The suite runs in two invocations rather than one. pytest-timeout on
161+ # Windows can only kill the whole process, so a single overrunning
162+ # tutorial used to take the JUnit XML, the coverage and every other
163+ # test's result with it, leaving the dashboard nothing to render.
164+ # Splitting the runs bounds that blast radius to one of them, and the
165+ # tutorial run additionally isolates each test in an xdist worker.
166+ #
167+ # --max-test-seconds fails a test that finishes but took too long, so the
168+ # overrun is reported with its duration and the rest of the suite still
169+ # runs. --timeout is the pytest-timeout backstop above it, left to catch
170+ # a genuine hang and nothing else. Both steps are continue-on-error so
171+ # the artifacts are always uploaded; the gate step at the end fails the
172+ # job.
173+ - name : Run core test suite
174+ id : run-core-tests
175+ continue-on-error : true
176+ run : |
177+ pytest tests/ --ignore=tests/test_tutorials.py -v `
178+ --run-all --require-tutorial-data `
179+ --max-test-seconds=400 `
180+ --timeout=900 `
181+ --cov=physiotwin4d `
182+ --junitxml=test-results-core.xml
183+ env :
184+ CUDA_VISIBLE_DEVICES : 0
185+ # The datasets, the results and the trained networks live on the
186+ # runner's own disk rather than in the checkout, which
187+ # actions/checkout wipes every run. Each root has a "test" subtree
188+ # that this suite reads and writes, so a nightly run never touches a
189+ # full run's files, and the downsampled subsets the fixtures build
190+ # under <input>/test survive between runs instead of being rebuilt.
191+ # Unset, each falls back to its in-repo default; see data/README.md.
192+ PHYSIOTWIN_INPUT_DATA_DIR : D:\PhysioTwin4D\nightly-runner\data
193+ PHYSIOTWIN_OUTPUT_DATA_DIR : D:\PhysioTwin4D\nightly-runner\output
194+ PHYSIOTWIN_WEIGHTS_DIR : D:\PhysioTwin4D\nightly-runner\network_weights
195+
196+ - name : Run tutorial test suite
197+ id : run-tutorial-tests
161198 continue-on-error : true
162- # --max-test-seconds fails a test that finishes but took too long, so the
163- # overrun is reported with its duration and the rest of the suite still
164- # runs. --timeout raises the pytest-timeout backstop above it: on
165- # Windows that backstop can only kill the whole process, which would
166- # take the JUnit XML and every other result with it, so it is left to
167- # catch a genuine hang and nothing else. Both numbers are provisional
168- # until the per-tutorial timings are measured.
199+ # -n 1 keeps the tutorials strictly serial -- they share one GPU, one
200+ # "test" output subtree, and several bootstrap their prerequisite
201+ # tutorial inline -- while running them in an xdist worker process.
202+ # pytest-timeout then kills the worker rather than the session: xdist
203+ # reports that test as crashed, starts a fresh worker and carries on,
204+ # so an overrun costs one tutorial instead of the whole run.
205+ #
206+ # --cov-append adds to the core run's data, and the reports are written
207+ # here so that they cover both runs.
169208 run : |
170- pytest tests/ -v --run-all --require-tutorial-data `
171- --max-test-seconds=900 `
172- --timeout=3600 `
209+ pytest tests/test_tutorials.py -v `
210+ --run-all --require-tutorial-data `
211+ -n 1 --max-worker-restart=40 `
212+ --max-test-seconds=600 `
213+ --timeout=900 `
173214 --cov=physiotwin4d `
215+ --cov-append `
174216 --cov-report=xml `
175217 --cov-report=json `
176- --junitxml=test-results.xml
218+ --junitxml=test-results-tutorials .xml
177219 env :
178220 CUDA_VISIBLE_DEVICES : 0
179221 # The datasets, the results and the trained networks live on the
@@ -193,7 +235,8 @@ jobs:
193235 with :
194236 name : health-test-results
195237 path : |
196- test-results.xml
238+ test-results-core.xml
239+ test-results-tutorials.xml
197240 coverage.xml
198241 coverage.json
199242 retention-days : 90
@@ -204,9 +247,10 @@ jobs:
204247 # would report success even when tests failed or the step timed out,
205248 # and the workflow status badge would say green while nothing passed.
206249 # build-dashboard runs on if: always(), so it still gets its inputs.
207- if : steps.run-tests.outcome != 'success'
250+ if : steps.run-core-tests.outcome != 'success' || steps.run-tutorial- tests.outcome != 'success'
208251 run : |
209- Write-Output "Health test suite outcome: ${{ steps.run-tests.outcome }}"
252+ Write-Output "Core suite outcome: ${{ steps.run-core-tests.outcome }}"
253+ Write-Output "Tutorial suite outcome: ${{ steps.run-tutorial-tests.outcome }}"
210254 Write-Output "See the health-test-results artifact for the JUnit XML."
211255 exit 1
212256
0 commit comments