Skip to content

FIX: Force javascript node24 and enablement:true for docs #136

FIX: Force javascript node24 and enablement:true for docs

FIX: Force javascript node24 and enablement:true for docs #136

Workflow file for this run

name: CI
# Comprehensive CI workflow combining unit tests, integration tests, GPU tests, and code quality checks
#
# Test organization:
# - Unit tests: Run on all PRs and pushes, cross-platform (Ubuntu + Windows), multiple Python versions
# - Integration tests: Run with external data, Ubuntu only
# - GPU tests: Self-hosted runners with CUDA support
# - Code quality: Linting and formatting checks
#
# Test markers:
# - requires_data: Tests that need external data downloads
# - slow: Tests that are computationally intensive or require GPU
on:
push:
branches: [ main, master, develop ]
pull_request:
branches: [ main, master, develop ]
workflow_dispatch:
jobs:
# ============================================================================
# Cross-Platform Unit Tests (Ubuntu + Windows)
# ============================================================================
unit-tests:
name: Unit Tests (${{ matrix.os }}, Python ${{ matrix.python-version }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
python-version: ['3.10', '3.11', '3.12']
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
lfs: true
- name: Free up disk space on Ubuntu
if: matrix.os == 'ubuntu-latest'
run: |
echo "Disk space before cleanup:"
df -h
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/local/lib/android
sudo rm -rf /opt/ghc
sudo rm -rf /opt/hostedtoolcache/CodeQL
sudo docker image prune --all --force
echo "Disk space after cleanup:"
df -h
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: pyproject.toml
- name: Cache pip packages
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('pyproject.toml') }}
restore-keys: |
${{ runner.os }}-pip-${{ matrix.python-version }}-
${{ runner.os }}-pip-
- name: Install system dependencies (Ubuntu)
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y \
libgl1 \
libglib2.0-0 \
libgomp1 \
libsm6 \
libxrender1 \
libxext6 \
libxrandr2 \
libxi6
sudo apt-get clean
sudo rm -rf /var/lib/apt/lists/*
- name: Upgrade pip and build tools
run: |
python -m pip install --upgrade pip setuptools wheel
- name: Install package with test dependencies
run: |
pip install -e ".[test]"
- name: Clear pip cache
run: |
pip cache purge || true
- name: List installed packages
run: |
pip list
- name: Run unit tests (fast, no external data)
run: |
pytest tests/ -v -m "not slow and not requires_data and not experiment" --cov=physiomotion4d --cov-report=xml --cov-report=term --cov-report=html
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.10'
with:
file: ./coverage.xml
flags: unittests
name: codecov-unit-${{ matrix.os }}-py${{ matrix.python-version }}
fail_ci_if_error: false
- name: Upload coverage artifacts
uses: actions/upload-artifact@v4
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.10'
with:
name: coverage-report-unit-tests
path: htmlcov/
retention-days: 7
# ============================================================================
# Integration Tests with External Data (Ubuntu only, on PRs)
# ============================================================================
integration-tests:
name: Integration Tests (with data)
runs-on: ubuntu-latest
needs: unit-tests
if: github.event_name == 'pull_request'
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
lfs: true
- name: Free up disk space
run: |
echo "Disk space before cleanup:"
df -h
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/local/lib/android
sudo rm -rf /opt/ghc
sudo rm -rf /opt/hostedtoolcache/CodeQL
sudo docker image prune --all --force
echo "Disk space after cleanup:"
df -h
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
cache-dependency-path: pyproject.toml
- name: Cache pip packages
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-integration-${{ hashFiles('pyproject.toml') }}
restore-keys: |
${{ runner.os }}-pip-integration-
${{ runner.os }}-pip-
- name: Cache test data
uses: actions/cache@v4
with:
path: |
tests/data/
tests/results/
key: test-data-${{ hashFiles('tests/test_*.py') }}-v2
restore-keys: |
test-data-
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libgl1 \
libglib2.0-0 \
libgomp1 \
libsm6 \
libxrender1 \
libxext6 \
libxrandr2 \
libxi6
sudo apt-get clean
sudo rm -rf /var/lib/apt/lists/*
- name: Upgrade pip and build tools
run: |
python -m pip install --upgrade pip setuptools wheel
- name: Install package with test dependencies
run: |
pip install -e ".[test]"
- name: Clear pip cache
run: |
pip cache purge || true
- name: Run data download tests
run: |
pytest tests/test_download_heart_data.py -v --cov=physiomotion4d --cov-report=xml
continue-on-error: true
- name: Run data conversion tests
run: |
pytest tests/test_convert_nrrd_4d_to_3d.py -v --cov=physiomotion4d --cov-append --cov-report=xml
continue-on-error: true
- name: Run contour tools tests
run: |
pytest tests/test_contour_tools.py -v -m "not slow" --cov=physiomotion4d --cov-append --cov-report=xml
continue-on-error: true
- name: Run USD conversion tests
run: |
pytest tests/test_convert_vtk_to_usd_polymesh.py -v -m "not slow" --cov=physiomotion4d --cov-append --cov-report=xml
continue-on-error: true
- name: Run USD utility tests
run: |
pytest tests/test_usd_merge.py tests/test_usd_time_preservation.py -v --cov=physiomotion4d --cov-append --cov-report=xml
continue-on-error: true
- name: Run all integration tests
run: |
pytest tests/ -v -m "not slow and not experiment and not requires_gpu"
continue-on-error: true
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
flags: integration-tests
name: codecov-integration
fail_ci_if_error: false
# ============================================================================
# GPU Tests (Self-hosted runners with CUDA)
# ============================================================================
# NOTE: GPU tests are DISABLED for automatic runs because they wait indefinitely
# if no self-hosted runner is available. Enable manually via workflow_dispatch
# or by setting the 'run-gpu-tests' label on the PR.
gpu-tests:
name: GPU Tests
runs-on: [self-hosted, Windows, X64, gpu]
needs: unit-tests
timeout-minutes: 30
# Only run GPU tests on manual trigger or if 'run-gpu-tests' label is present
if: github.event_name == 'workflow_dispatch' || contains(github.event.pull_request.labels.*.name, 'run-gpu-tests')
continue-on-error: true
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
lfs: true
- name: Create venv in RUNNER_TEMP
run: |
& "C:\Program Files\Python310\python.exe" -m venv "$env:RUNNER_TEMP\physiomotion4d-venv"
echo "$env:RUNNER_TEMP\physiomotion4d-venv\Scripts" >> $env:GITHUB_PATH
- name: Check GPU availability
run: nvidia-smi
- name: Cache uv packages
uses: actions/cache@v4
with:
path: ~\AppData\Local\uv\cache
key: ${{ runner.os }}-uv-${{ hashFiles('pyproject.toml') }}
restore-keys: |
${{ runner.os }}-uv-
- name: Upgrade pip and build tools
run: |
python -m pip install --upgrade pip setuptools wheel uv
- name: Install package with test dependencies
# uv respects [tool.uv.sources], routing torch to pytorch-cu130 for cuda13
# Invoke via python -m uv so uv targets the active venv interpreter.
run: |
python -m uv pip install -e ".[test,cuda13]"
- name: Assert CUDA is accessible
run: |
python -c "
import sys, torch, cupy
print(f'PyTorch {torch.__version__} | CUDA toolkit {torch.version.cuda} | CuPy {cupy.__version__}')
if not torch.cuda.is_available():
print('ERROR: torch.cuda.is_available() returned False', file=sys.stderr)
sys.exit(1)
n = torch.cuda.device_count()
if n == 0:
print('ERROR: torch.cuda.device_count() == 0', file=sys.stderr)
sys.exit(1)
cn = cupy.cuda.runtime.getDeviceCount()
if cn == 0:
print('ERROR: cupy.cuda.runtime.getDeviceCount() == 0', file=sys.stderr)
sys.exit(1)
print(f'OK: {n} GPU(s) visible to PyTorch and CuPy')
"
- name: List installed packages
run: |
pip list
- name: Run GPU tests
run: |
pytest tests/ -v -m "not slow and not experiment" --cov=physiomotion4d --cov-report=xml --cov-report=term --cov-report=html
env:
CUDA_VISIBLE_DEVICES: 0
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
flags: gpu-tests
name: codecov-gpu
fail_ci_if_error: false
- name: Upload coverage artifacts
uses: actions/upload-artifact@v4
with:
name: coverage-report-gpu
path: htmlcov/
retention-days: 7
# ============================================================================
# Code Quality Checks
# ============================================================================
code-quality:
name: Code Quality Checks
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
lfs: true
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
cache: 'pip'
- name: Install dev dependencies
run: |
python -m pip install --upgrade pip
pip install ruff mypy
pip install -e ".[dev]"
- name: Check formatting with Ruff
run: |
ruff format --check .
continue-on-error: false
- name: Lint with Ruff
run: |
ruff check .
continue-on-error: false
- name: Type check with mypy
run: |
mypy src/
continue-on-error: true
# ==============================================================================
# Notes on Excluded Tests
# ==============================================================================
#
# The following tests are excluded from CI and should be run locally:
#
# Slow/GPU-intensive tests:
# - tests/test_register_images_ants.py (slow, computationally intensive)
# - tests/test_register_images_icon.py (requires CUDA for ICON)
# - tests/test_transform_tools.py (depends on slow registration tests)
# - tests/test_segment_chest_total_segmentator.py (requires CUDA for TotalSegmentator)
# - tests/test_segment_chest_vista_3d.py (requires CUDA for VISTA-3D, 20GB+ RAM)
#
# Experiment tests (EXTREMELY SLOW - hours to complete):
# - tests/test_experiments.py (runs all notebooks in experiments/ subdirectories)
# These tests are NEVER run in CI/CD and must be run manually
# They execute end-to-end workflows that may take multiple hours
#
# To run locally:
# pytest tests/ -v -m "slow" # Run all slow tests
# pytest tests/test_register_images_ants.py -v
# pytest tests/test_register_images_icon.py -v
# pytest tests/test_segment_chest_total_segmentator.py -v
#
# To run experiment tests (manual only, extremely slow):
# pytest tests/test_experiments.py -v -m experiment
# pytest tests/test_experiments.py::test_experiment_heart_gated_ct_to_usd -v