ENH: Clarify work is not limited to CT (#14) #31
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 | |
| - 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 PyTorch (CPU) | |
| run: | | |
| pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu | |
| - 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" --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 | |
| - 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 PyTorch (CPU) | |
| run: | | |
| pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu | |
| - 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_4d_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" | |
| 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 (Python ${{ matrix.python-version }}) | |
| runs-on: [self-hosted, linux, 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') | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.10", "3.11"] | |
| continue-on-error: true | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Check GPU availability | |
| run: | | |
| nvidia-smi || echo "No GPU available" | |
| python -c "import torch; print(f'PyTorch CUDA available: {torch.cuda.is_available()}')" || echo "PyTorch not installed yet" | |
| - name: Cache pip packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/pip | |
| key: ${{ runner.os }}-pip-gpu-${{ matrix.python-version }}-${{ hashFiles('pyproject.toml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pip-gpu-${{ matrix.python-version }}- | |
| ${{ runner.os }}-pip-gpu- | |
| ${{ runner.os }}-pip- | |
| - name: Upgrade pip and build tools | |
| run: | | |
| python -m pip install --upgrade pip setuptools wheel | |
| - name: Install PyTorch (CUDA 12.6) | |
| run: | | |
| pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126 | |
| - name: Install package with test dependencies | |
| run: | | |
| pip install -e ".[test]" | |
| - name: Verify GPU setup | |
| run: | | |
| python -c "import torch; print(f'PyTorch version: {torch.__version__}')" | |
| python -c "import torch; print(f'CUDA available: {torch.cuda.is_available()}')" | |
| python -c "import torch; print(f'CUDA version: {torch.version.cuda}')" || echo "CUDA not available" | |
| python -c "import torch; print(f'Number of GPUs: {torch.cuda.device_count()}')" || echo "No GPUs" | |
| - name: List installed packages | |
| run: | | |
| pip list | |
| - name: Run GPU tests | |
| run: | | |
| pytest tests/ -v -m "not slow" --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 | |
| if: matrix.python-version == '3.10' | |
| with: | |
| file: ./coverage.xml | |
| flags: gpu-tests | |
| name: codecov-gpu-py${{ matrix.python-version }} | |
| fail_ci_if_error: false | |
| - name: Upload coverage artifacts | |
| uses: actions/upload-artifact@v4 | |
| if: matrix.python-version == '3.10' | |
| 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 | |
| - 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 black isort ruff flake8 pylint mypy | |
| - name: Check code formatting with Black | |
| run: | | |
| black --check src/ tests/ || echo "Black check failed" | |
| continue-on-error: true | |
| - name: Check import sorting with isort | |
| run: | | |
| isort --check-only src/ tests/ || echo "isort check failed" | |
| continue-on-error: true | |
| - name: Lint with Ruff | |
| run: | | |
| ruff check src/ tests/ || echo "Ruff check failed" | |
| continue-on-error: true | |
| - name: Lint with Flake8 | |
| run: | | |
| flake8 src/ tests/ || echo "Flake8 check failed" | |
| 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) | |
| # | |
| # 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 |