FIX: Force javascript node24 and enablement:true for docs #136
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |