99 - ' dev/tests/test_benchmark_frontend_data.py'
1010 - ' dev/tests/test_frontend_contracts.py'
1111 - ' dev/tests/test_frontend_domain_coverage.py'
12- - ' dev/tests/fixtures/benchmark_frontend/**'
1312 - ' frontend/**'
1413 - ' docs/assets/benchmarks/**'
1514 - ' results/benchmark_frontend_sources/**'
2019 - ' dev/tests/test_benchmark_frontend_data.py'
2120 - ' dev/tests/test_frontend_contracts.py'
2221 - ' dev/tests/test_frontend_domain_coverage.py'
23- - ' dev/tests/fixtures/benchmark_frontend/**'
2422 - ' frontend/**'
2523 - ' docs/assets/benchmarks/**'
2624 - ' results/benchmark_frontend_sources/**'
@@ -37,16 +35,13 @@ jobs:
3735 - uses : actions/setup-python@v5
3836 with :
3937 python-version : ${{ matrix.python-version }}
40- - name : Install test dependencies
41- run : python -m pip install -U pip pytest jsonschema
42- - name : Run generator and parser tests
43- run : |
38+ - run : python -m pip install -U pip pytest jsonschema
39+ - run : |
4440 pytest \
4541 dev/tests/test_benchmark_frontend_data.py \
4642 dev/tests/test_frontend_contracts.py \
4743 dev/tests/test_frontend_domain_coverage.py -v
48- - name : Validate generator output
49- run : python dev/benchmarks/generate_benchmark_data.py --check --strict-sources
44+ - run : python dev/benchmarks/generate_benchmark_data.py --check --strict-sources
5045
5146 frontend :
5247 if : github.event_name == 'pull_request' || github.ref == 'refs/heads/master'
5954 - uses : actions/setup-node@v4
6055 with :
6156 node-version : ' 20'
62- - name : Reject committed frontend artifacts
63- run : |
64- if git -C "$GITHUB_WORKSPACE" ls-files \
65- 'frontend/node_modules/**' \
66- 'frontend/test-results/**' \
67- 'frontend/playwright-report/**' | grep -q .; then
68- echo "Generated frontend dependencies/test artifacts must not be committed."
69- exit 1
70- fi
7157 - run : npm ci
7258 - run : npm run typecheck
7359 - run : npm run build
@@ -83,28 +69,19 @@ jobs:
8369 - uses : actions/setup-node@v4
8470 with :
8571 node-version : ' 20'
86- - name : Generate data (deterministic)
87- run : |
72+ - run : |
8873 python dev/benchmarks/generate_benchmark_data.py \
8974 --out frontend/public/data/benchmark_data.json \
9075 --report frontend/public/data/parse_report.json \
9176 --inventory-out frontend/public/data/source_inventory.json \
9277 --deterministic --strict-sources
93- - name : Build frontend
94- run : |
78+ - run : |
9579 cd frontend
9680 npm ci
9781 npm run build
98- - name : Check staleness
99- run : |
82+ - run : |
10083 changes="$(git status --porcelain -- frontend/public/data docs/assets/benchmarks)"
101- if [ -n "$changes" ]; then
102- echo "Generated benchmark assets are stale:"
103- printf '%s\n' "$changes"
104- git diff -- frontend/public/data docs/assets/benchmarks
105- exit 1
106- fi
107- echo "OK — generated benchmark assets are current"
84+ test -z "$changes" || { printf '%s\n' "$changes"; exit 1; }
10885
10986 frontend-e2e :
11087 if : github.event_name == 'pull_request' || github.ref == 'refs/heads/master'
@@ -121,12 +98,6 @@ jobs:
12198 - run : npm ci
12299 - run : npx playwright install --with-deps chromium
123100 - run : npm run test:e2e
124- - uses : actions/upload-artifact@v4
125- if : always()
126- with :
127- name : playwright-report
128- path : frontend/playwright-report/
129- retention-days : 30
130101
131102 refresh-june-dashboard :
132103 if : github.event_name == 'push' && github.ref == 'refs/heads/frontend-dashboard-data-pipeline'
@@ -143,221 +114,49 @@ jobs:
143114 - uses : actions/setup-node@v4
144115 with :
145116 node-version : ' 20'
146- - name : Update benchmark index summary
147- run : |
148- python - <<'PY'
149- from pathlib import Path
150- import re
151-
152- path = Path('docs/en/guides/benchmarks.md')
153- text = path.read_text(encoding='utf-8')
154- replacement = '''## Benchmark Dashboard
155-
156- - **Interactive dashboard**: [Open Dashboard](../../assets/benchmarks/index.html)
157- - **Dashboard guide**: [Filters, charts, metrics, and reproduction](statgpu_benchmark_dashboard.md)
158-
159- The canonical dashboard is restricted to benchmark sources dated **2026-06-01 or later**. Eight sources are currently registered; April 2026 ElasticNet, LassoCV, comprehensive-validation, Cox package-comparison, and knockoff results are not connected.
160-
161- The current bundle covers robust/quantile, unsupervised, ordered, nonparametric, panel, covariance, survival, GLM, and recent linear-model benchmarks. Linear models use the June 2026 squared-error rows from `penalized_glm_perf_20260622.json` and `glm_solver_20260623.json`.
162-
163- Current capabilities:
164-
165- - Environment and multi-category navigation.
166- - Progressive model, variant, penalty, solver, and scale filters.
167- - NumPy, CuPy, and Torch backend selection.
168- - Context-aware external comparisons with scikit-learn, linearmodels, and pyGAM.
169- - Timing and speedup charts with distinct computed and runner-reported semantics.
170- - Sortable run-level table.
171- - Validation, accuracy, inference, prediction, convergence, and selection panels.
172- - Source provenance, parse-report metadata, and source-inventory coverage.
173-
174- Generate and validate the canonical bundle:
175-
176- ```bash
177- python dev/benchmarks/generate_benchmark_data.py \
178- --out frontend/public/data/benchmark_data.json \
179- --report frontend/public/data/parse_report.json \
180- --inventory-out frontend/public/data/source_inventory.json \
181- --deterministic --strict-sources
182-
183- python dev/benchmarks/generate_benchmark_data.py --check --strict-sources
184- ```
185-
186- Build the deployed dashboard:
187-
188- ```bash
189- cd frontend
190- npm ci
191- npm run typecheck
192- npm run build
193- ```
194- '''
195- replacement = '\n'.join(
196- line[10:] if line.startswith(' ') else line
197- for line in replacement.splitlines()
198- )
199- text, count = re.subn(
200- r'## Benchmark Dashboard\n.*?(?=\n---)',
201- replacement,
202- text,
203- count=1,
204- flags=re.S,
205- )
206- if count != 1:
207- raise RuntimeError('Benchmark Dashboard section not found exactly once')
208- path.write_text(text, encoding='utf-8')
209- PY
210- - name : Validate and generate data
117+ - name : Run tests with diagnostic capture
118+ id : pytest
119+ continue-on-error : true
211120 run : |
212121 python -m pip install -U pip pytest jsonschema
122+ set -o pipefail
213123 pytest \
214124 dev/tests/test_benchmark_frontend_data.py \
215125 dev/tests/test_frontend_contracts.py \
216- dev/tests/test_frontend_domain_coverage.py -v
126+ dev/tests/test_frontend_domain_coverage.py -vv 2>&1 | tee /tmp/june-dashboard-pytest.log
127+ - name : Commit failure summary
128+ if : steps.pytest.outcome == 'failure'
129+ run : |
130+ tail -n 200 /tmp/june-dashboard-pytest.log > dev/tests/june_dashboard_pytest_failure.txt
131+ rm -f .github/workflows/finalize-june-dashboard.yml
132+ git show b63e184fa2d9de3c1d2ba8f83c251c5788ca0847:.github/workflows/benchmark-frontend.yml > .github/workflows/benchmark-frontend.yml
133+ git config user.name github-actions[bot]
134+ git config user.email 41898282+github-actions[bot]@users.noreply.github.com
135+ git add -A
136+ git commit -m "test(frontend): capture June-only failure"
137+ git push origin HEAD:frontend-dashboard-data-pipeline
138+ - name : Generate bundle
139+ if : steps.pytest.outcome == 'success'
140+ run : |
217141 python dev/benchmarks/generate_benchmark_data.py \
218142 --out frontend/public/data/benchmark_data.json \
219143 --report frontend/public/data/parse_report.json \
220144 --inventory-out frontend/public/data/source_inventory.json \
221145 --deterministic --strict-sources
222146 - name : Build and test frontend
147+ if : steps.pytest.outcome == 'success'
223148 working-directory : frontend
224149 run : |
225150 npm ci
226151 npm run typecheck
227152 npm run build
228153 npx playwright install --with-deps chromium
229154 npm run test:e2e
230- - name : Restore permanent workflow and commit generated assets
155+ - name : Commit generated assets
156+ if : steps.pytest.outcome == 'success'
231157 run : |
232158 rm -f .github/workflows/finalize-june-dashboard.yml
233- cat > .github/workflows/benchmark-frontend.yml <<'EOF'
234- name: Benchmark Frontend CI
235-
236- on:
237- push:
238- branches: [master]
239- paths:
240- - '.github/workflows/benchmark-frontend.yml'
241- - 'dev/benchmarks/**'
242- - 'dev/tests/test_benchmark_frontend_data.py'
243- - 'dev/tests/test_frontend_contracts.py'
244- - 'dev/tests/test_frontend_domain_coverage.py'
245- - 'dev/tests/fixtures/benchmark_frontend/**'
246- - 'frontend/**'
247- - 'docs/assets/benchmarks/**'
248- - 'results/benchmark_frontend_sources/**'
249- pull_request:
250- paths:
251- - '.github/workflows/benchmark-frontend.yml'
252- - 'dev/benchmarks/**'
253- - 'dev/tests/test_benchmark_frontend_data.py'
254- - 'dev/tests/test_frontend_contracts.py'
255- - 'dev/tests/test_frontend_domain_coverage.py'
256- - 'dev/tests/fixtures/benchmark_frontend/**'
257- - 'frontend/**'
258- - 'docs/assets/benchmarks/**'
259- - 'results/benchmark_frontend_sources/**'
260-
261- jobs:
262- python-data:
263- runs-on: ubuntu-latest
264- strategy:
265- matrix:
266- python-version: ['3.9', '3.11']
267- steps:
268- - uses: actions/checkout@v4
269- - uses: actions/setup-python@v5
270- with:
271- python-version: ${{ matrix.python-version }}
272- - name: Install test dependencies
273- run: python -m pip install -U pip pytest jsonschema
274- - name: Run generator and parser tests
275- run: |
276- pytest \
277- dev/tests/test_benchmark_frontend_data.py \
278- dev/tests/test_frontend_contracts.py \
279- dev/tests/test_frontend_domain_coverage.py -v
280- - name: Validate generator output
281- run: python dev/benchmarks/generate_benchmark_data.py --check --strict-sources
282-
283- frontend:
284- runs-on: ubuntu-latest
285- defaults:
286- run:
287- working-directory: frontend
288- steps:
289- - uses: actions/checkout@v4
290- - uses: actions/setup-node@v4
291- with:
292- node-version: '20'
293- - name: Reject committed frontend artifacts
294- run: |
295- if git -C "$GITHUB_WORKSPACE" ls-files \
296- 'frontend/node_modules/**' \
297- 'frontend/test-results/**' \
298- 'frontend/playwright-report/**' | grep -q .; then
299- echo "Generated frontend dependencies/test artifacts must not be committed."
300- exit 1
301- fi
302- - run: npm ci
303- - run: npm run typecheck
304- - run: npm run build
305-
306- staleness:
307- runs-on: ubuntu-latest
308- steps:
309- - uses: actions/checkout@v4
310- - uses: actions/setup-python@v5
311- with:
312- python-version: '3.11'
313- - uses: actions/setup-node@v4
314- with:
315- node-version: '20'
316- - name: Generate data (deterministic)
317- run: |
318- python dev/benchmarks/generate_benchmark_data.py \
319- --out frontend/public/data/benchmark_data.json \
320- --report frontend/public/data/parse_report.json \
321- --inventory-out frontend/public/data/source_inventory.json \
322- --deterministic --strict-sources
323- - name: Build frontend
324- run: |
325- cd frontend
326- npm ci
327- npm run build
328- - name: Check staleness
329- run: |
330- changes="$(git status --porcelain -- frontend/public/data docs/assets/benchmarks)"
331- if [ -n "$changes" ]; then
332- echo "Generated benchmark assets are stale:"
333- printf '%s\n' "$changes"
334- git diff -- frontend/public/data docs/assets/benchmarks
335- exit 1
336- fi
337- echo "OK — generated benchmark assets are current"
338-
339- frontend-e2e:
340- runs-on: ubuntu-latest
341- needs: [frontend, staleness]
342- defaults:
343- run:
344- working-directory: frontend
345- steps:
346- - uses: actions/checkout@v4
347- - uses: actions/setup-node@v4
348- with:
349- node-version: '20'
350- - run: npm ci
351- - run: npx playwright install --with-deps chromium
352- - run: npm run test:e2e
353- - uses: actions/upload-artifact@v4
354- if: always()
355- with:
356- name: playwright-report
357- path: frontend/playwright-report/
358- retention-days: 30
359- EOF
360- sed -i 's/^ //' .github/workflows/benchmark-frontend.yml
159+ git show b63e184fa2d9de3c1d2ba8f83c251c5788ca0847:.github/workflows/benchmark-frontend.yml > .github/workflows/benchmark-frontend.yml
361160 read runs models <<EOF
362161 $(python - <<'PY'
363162 import json
0 commit comments