Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,12 @@ jobs:

cleanroom-compliance:
runs-on: ubuntu-latest
env:
OMP_NUM_THREADS: "1"
MKL_NUM_THREADS: "1"
OPENBLAS_NUM_THREADS: "1"
NUMEXPR_NUM_THREADS: "1"
VECLIB_MAXIMUM_THREADS: "1"

steps:
- uses: actions/checkout@v4
Expand All @@ -144,9 +150,12 @@ jobs:
python -m pip install -e .
python -m pip install pyyaml

- name: Checkout upstream MATLAB nSTAT repo snapshot
- name: Checkout pinned MATLAB nSTAT reference
run: |
GIT_LFS_SKIP_SMUDGE=1 git clone --depth 1 https://github.com/cajigaslab/nSTAT.git /tmp/upstream-nstat
python tools/parity/checkout_matlab_reference.py \
--config parity/matlab_reference.yml \
--dest /tmp/upstream-nstat \
--metadata-out parity/matlab_reference_checkout.json

- name: Run clean-room overlap check
run: |
Expand Down
26 changes: 23 additions & 3 deletions .github/workflows/full-parity-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ on:
jobs:
full-parity:
runs-on: ubuntu-latest
env:
OMP_NUM_THREADS: "1"
MKL_NUM_THREADS: "1"
OPENBLAS_NUM_THREADS: "1"
NUMEXPR_NUM_THREADS: "1"
VECLIB_MAXIMUM_THREADS: "1"

steps:
- uses: actions/checkout@v4
Expand All @@ -26,9 +32,12 @@ jobs:
python -m pip install -e .[dev,docs,notebooks]
python -m pip install reportlab pillow

- name: Checkout upstream MATLAB nSTAT repo snapshot
- name: Checkout pinned MATLAB nSTAT reference
run: |
GIT_LFS_SKIP_SMUDGE=1 git clone --depth 1 https://github.com/cajigaslab/nSTAT.git /tmp/upstream-nstat
python tools/parity/checkout_matlab_reference.py \
--config parity/matlab_reference.yml \
--dest /tmp/upstream-nstat \
--metadata-out parity/matlab_reference_checkout.json

- name: Prepare deterministic validation images
run: |
Expand Down Expand Up @@ -65,6 +74,14 @@ jobs:
--min-unique-images-per-topic 1 \
--max-cross-topic-reuse-ratio 1.0

- name: Normalize canonical validation artifact names
run: |
latest_json="$(ls -1t output/pdf/nstat_python_validation_report_*.json | head -n 1)"
latest_base="${latest_json%.json}"
cp "${latest_base}.pdf" output/pdf/validation_gate_mode_latest.pdf
cp "${latest_base}.json" output/pdf/validation_gate_mode_latest.json
cp "${latest_base}.csv" output/pdf/validation_gate_mode_latest.csv

- name: Enforce visual validation gate
run: |
python tools/reports/check_validation_visuals.py \
Expand All @@ -91,7 +108,10 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: nightly-validation-pdf
path: output/pdf/*.pdf
path: |
output/pdf/validation_gate_mode_latest.pdf
output/pdf/validation_gate_mode_latest.json
output/pdf/validation_gate_mode_latest.csv
if-no-files-found: warn

- name: Upload notebook image artifact
Expand Down
91 changes: 91 additions & 0 deletions .github/workflows/image-mode-parity.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: image-mode-parity

on:
pull_request:
schedule:
- cron: "0 5 * * *"
workflow_dispatch:

jobs:
image-mode-parity:
runs-on: ubuntu-latest
env:
OMP_NUM_THREADS: "1"
MKL_NUM_THREADS: "1"
OPENBLAS_NUM_THREADS: "1"
NUMEXPR_NUM_THREADS: "1"
VECLIB_MAXIMUM_THREADS: "1"
PYTHONUNBUFFERED: "1"

steps:
- uses: actions/checkout@v4
with:
lfs: false

- uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -e .[dev,notebooks]
python -m pip install reportlab pillow

- name: Checkout pinned MATLAB nSTAT reference
run: |
python tools/parity/checkout_matlab_reference.py \
--config parity/matlab_reference.yml \
--dest /tmp/upstream-nstat \
--metadata-out parity/matlab_reference_checkout.json

- name: Prepare deterministic validation images
run: |
python tools/parity/prepare_validation_images.py

- name: Generate Python validation PDF (image mode)
run: |
python tools/reports/generate_validation_pdf.py \
--repo-root "$GITHUB_WORKSPACE" \
--matlab-help-root /tmp/upstream-nstat/helpfiles \
--notebook-group all \
--timeout 900 \
--skip-command-tests \
--parity-mode image \
--skip-parity-check

- name: Resolve latest validation JSON
id: latest
run: |
latest_json="$(ls -1t output/pdf/nstat_python_validation_report_*.json | head -n 1)"
echo "json=${latest_json}" >> "$GITHUB_OUTPUT"

- name: Build paired MATLAB/Python image PDFs
run: |
python tools/reports/build_image_parity_pdfs.py \
--report-json "${{ steps.latest.outputs.json }}" \
--python-out output/pdf/image_mode_parity/python_pages.pdf \
--matlab-out output/pdf/image_mode_parity/matlab_pages.pdf \
--pairs-json output/pdf/image_mode_parity/pairs.json

- name: Run page-by-page SSIM parity gate
run: |
python tools/reports/check_pdf_image_parity.py \
--python-pdf output/pdf/image_mode_parity/python_pages.pdf \
--matlab-pdf output/pdf/image_mode_parity/matlab_pages.pdf \
--out-dir output/pdf/image_mode_parity \
--dpi 150 \
--ssim-threshold 0.70 \
--max-failing-pages 0

- name: Upload image-mode parity artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: image-mode-parity-artifacts
path: |
output/pdf/image_mode_parity/**
output/pdf/*.pdf
output/pdf/*.json
output/pdf/*.csv
if-no-files-found: warn
48 changes: 46 additions & 2 deletions .github/workflows/parity-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ on:
jobs:
parity-checks:
runs-on: ubuntu-latest
env:
OMP_NUM_THREADS: "1"
MKL_NUM_THREADS: "1"
OPENBLAS_NUM_THREADS: "1"
NUMEXPR_NUM_THREADS: "1"
VECLIB_MAXIMUM_THREADS: "1"

steps:
- uses: actions/checkout@v4
Expand All @@ -25,9 +31,12 @@ jobs:
python -m pip install -e .[dev,notebooks]
python -m pip install pyyaml

- name: Checkout upstream MATLAB nSTAT repo snapshot
- name: Checkout pinned MATLAB nSTAT reference
run: |
GIT_LFS_SKIP_SMUDGE=1 git clone --depth 1 https://github.com/cajigaslab/nSTAT.git /tmp/upstream-nstat
python tools/parity/checkout_matlab_reference.py \
--config parity/matlab_reference.yml \
--dest /tmp/upstream-nstat \
--metadata-out parity/matlab_reference_checkout.json

- name: Prepare deterministic validation images
run: |
Expand Down Expand Up @@ -60,3 +69,38 @@ jobs:
docs/help \
docs/notebooks.md \
baseline/help_mapping.json

- name: Generate full validation PDF (gate mode)
run: |
python tools/reports/generate_validation_pdf.py \
--repo-root "$GITHUB_WORKSPACE" \
--matlab-help-root /tmp/upstream-nstat/helpfiles \
--notebook-group all \
--timeout 900 \
--skip-command-tests \
--parity-mode gate \
--enforce-unique-images \
--min-unique-images-per-topic 1 \
--max-cross-topic-reuse-ratio 1.0

- name: Normalize canonical validation artifact names
run: |
latest_json="$(ls -1t output/pdf/nstat_python_validation_report_*.json | head -n 1)"
latest_base="${latest_json%.json}"
cp "${latest_base}.pdf" output/pdf/validation_gate_mode_latest.pdf
cp "${latest_base}.json" output/pdf/validation_gate_mode_latest.json
cp "${latest_base}.csv" output/pdf/validation_gate_mode_latest.csv

- name: Upload parity gate validation artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: parity-gate-validation-artifacts
path: |
output/pdf/validation_gate_mode_latest.pdf
output/pdf/validation_gate_mode_latest.json
output/pdf/validation_gate_mode_latest.csv
parity/function_example_alignment_report.json
parity/numeric_drift_report.json
parity/performance_parity_report.json
if-no-files-found: warn
84 changes: 84 additions & 0 deletions .github/workflows/performance-parity.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: performance-parity

on:
pull_request:
schedule:
- cron: "30 6 * * *"
workflow_dispatch:

jobs:
performance-parity:
runs-on: ubuntu-latest
env:
OMP_NUM_THREADS: "1"
MKL_NUM_THREADS: "1"
OPENBLAS_NUM_THREADS: "1"
NUMEXPR_NUM_THREADS: "1"
VECLIB_MAXIMUM_THREADS: "1"
PYTHONUNBUFFERED: "1"

steps:
- uses: actions/checkout@v4
with:
lfs: false

- uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -e .[dev,notebooks]

- name: Set benchmark scope
id: scope
run: |
if [ "${{ github.event_name }}" = "pull_request" ]; then
echo "tiers=S" >> "$GITHUB_OUTPUT"
echo "repeats=5" >> "$GITHUB_OUTPUT"
echo "warmup=1" >> "$GITHUB_OUTPUT"
else
echo "tiers=S,M,L" >> "$GITHUB_OUTPUT"
echo "repeats=7" >> "$GITHUB_OUTPUT"
echo "warmup=2" >> "$GITHUB_OUTPUT"
fi

- name: Run python performance benchmark harness
run: |
python tools/performance/run_python_benchmarks.py \
--tiers "${{ steps.scope.outputs.tiers }}" \
--repeats "${{ steps.scope.outputs.repeats }}" \
--warmup "${{ steps.scope.outputs.warmup }}" \
--out-json output/performance/python_performance_report.json \
--out-csv output/performance/python_performance_report.csv

- name: Compare Python benchmark report against MATLAB baseline
run: |
python tools/performance/compare_matlab_python_performance.py \
--python-report output/performance/python_performance_report.json \
--matlab-report tests/performance/fixtures/matlab/performance_baseline_470fde8.json \
--policy parity/performance_gate_policy.yml \
--previous-python-report tests/performance/fixtures/python/performance_baseline_20260303.json \
--report-out output/performance/performance_parity_report.json \
--csv-out output/performance/performance_parity_report.csv \
--fail-on-regression

- name: Run pytest-benchmark smoke suite
env:
NSTAT_RUN_PERF_BENCHMARKS: "1"
run: |
pytest tests/performance/test_pytest_benchmarks.py \
--benchmark-json=output/performance/pytest_benchmark_smoke.json

- name: Upload performance artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: performance-parity-artifacts
path: |
output/performance/*.json
output/performance/*.csv
tests/performance/fixtures/matlab/performance_baseline_470fde8.json
tests/performance/fixtures/python/performance_baseline_20260303.json
if-no-files-found: warn
13 changes: 11 additions & 2 deletions .github/workflows/release-rc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ env:
jobs:
build-and-release:
runs-on: ubuntu-latest
env:
OMP_NUM_THREADS: "1"
MKL_NUM_THREADS: "1"
OPENBLAS_NUM_THREADS: "1"
NUMEXPR_NUM_THREADS: "1"
VECLIB_MAXIMUM_THREADS: "1"

steps:
- uses: actions/checkout@v4
Expand All @@ -43,9 +49,12 @@ jobs:
python tools/notebooks/generate_notebooks.py
git diff --exit-code

- name: Checkout upstream MATLAB nSTAT repo snapshot
- name: Checkout pinned MATLAB nSTAT reference
run: |
GIT_LFS_SKIP_SMUDGE=1 git clone --depth 1 https://github.com/cajigaslab/nSTAT.git /tmp/upstream-nstat
python tools/parity/checkout_matlab_reference.py \
--config parity/matlab_reference.yml \
--dest /tmp/upstream-nstat \
--metadata-out parity/matlab_reference_checkout.json

- name: Prepare deterministic validation images
run: |
Expand Down
13 changes: 11 additions & 2 deletions .github/workflows/release-stable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ env:
jobs:
promote:
runs-on: ubuntu-latest
env:
OMP_NUM_THREADS: "1"
MKL_NUM_THREADS: "1"
OPENBLAS_NUM_THREADS: "1"
NUMEXPR_NUM_THREADS: "1"
VECLIB_MAXIMUM_THREADS: "1"

steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -60,9 +66,12 @@ jobs:
python tools/docs/generate_help_pages.py
sphinx-build -W -b html docs docs/_build/html

- name: Checkout upstream MATLAB nSTAT repo snapshot
- name: Checkout pinned MATLAB nSTAT reference
run: |
GIT_LFS_SKIP_SMUDGE=1 git clone --depth 1 https://github.com/cajigaslab/nSTAT.git /tmp/upstream-nstat
python tools/parity/checkout_matlab_reference.py \
--config parity/matlab_reference.yml \
--dest /tmp/upstream-nstat \
--metadata-out parity/matlab_reference_checkout.json

- name: Prepare deterministic validation images
run: |
Expand Down
Loading