CI: Coverage #27
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
| # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | |
| # | |
| # SPDX-License-Identifier: Apache-2.0 | |
| name: "CI: Coverage" | |
| on: | |
| schedule: | |
| - cron: '0 0 * * *' # This runs the workflow every day at 12:00 AM UTC | |
| workflow_dispatch: {} | |
| env: | |
| PY_VER: "3.14" | |
| CUDA_VER: "13.1.0" | |
| LOCAL_CTK: "1" | |
| GPU: "a100" | |
| DRIVER: "latest" | |
| jobs: | |
| coverage-linux: | |
| name: Coverage (Linux) | |
| runs-on: "linux-amd64-gpu-a100-latest-1" | |
| defaults: | |
| run: | |
| shell: bash --noprofile --norc -xeuo pipefail {0} | |
| env: | |
| HOST_PLATFORM: "linux-64" | |
| ARCH: "x86_64" | |
| # Our self-hosted runners require a container | |
| # TODO: use a different (nvidia?) container | |
| container: | |
| options: -u root --security-opt seccomp=unconfined --shm-size 16g | |
| image: ubuntu:22.04 | |
| env: | |
| NVIDIA_VISIBLE_DEVICES: ${{ env.NVIDIA_VISIBLE_DEVICES }} | |
| steps: | |
| - name: Ensure GPU is working | |
| run: nvidia-smi | |
| # We have to install git before checking out the repo (so that we can | |
| # deploy the docs at the end). This means we can't use install_unix_deps | |
| # action so install the git package. | |
| - name: Install git | |
| run: | | |
| apt-get update | |
| apt-get install -y git | |
| - name: Checkout ${{ github.event.repository.name }} | |
| uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| - name: Install dependencies | |
| uses: ./.github/actions/install_unix_deps | |
| continue-on-error: false | |
| with: | |
| dependencies: "tree rsync libsqlite3-0 g++ jq wget libgl1 libegl1" | |
| dependent_exes: "tree rsync libsqlite3-0 g++ jq wget libgl1 libegl1" | |
| - name: Setup proxy cache | |
| uses: nv-gha-runners/setup-proxy-cache@main | |
| continue-on-error: true | |
| - name: Set environment variables | |
| env: | |
| BUILD_CUDA_VER: ${{ env.CUDA_VER }} | |
| CUDA_VER: ${{ env.CUDA_VER }} | |
| HOST_PLATFORM: ${{ env.HOST_PLATFORM }} | |
| LOCAL_CTK: ${{ env.LOCAL_CTK }} | |
| PY_VER: ${{ env.PY_VER }} | |
| SHA: ${{ github.sha }} | |
| run: | | |
| ./ci/tools/env-vars test | |
| echo "CUDA_PYTHON_COVERAGE=1" >> $GITHUB_ENV | |
| - name: Set up Python | |
| uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 | |
| with: | |
| python-version: ${{ env.PY_VER }} | |
| env: | |
| # we use self-hosted runners on which setup-python behaves weirdly... | |
| AGENT_TOOLSDIRECTORY: "/opt/hostedtoolcache" | |
| - name: Set up mini CTK | |
| if: ${{ env.LOCAL_CTK == '1' }} | |
| uses: ./.github/actions/fetch_ctk | |
| continue-on-error: false | |
| with: | |
| host-platform: ${{ env.HOST_PLATFORM }} | |
| cuda-version: ${{ env.CUDA_VER }} | |
| - name: Create venv | |
| run: | | |
| python -m venv .venv | |
| - name: Build cuda-pathfinder | |
| run: | | |
| .venv/bin/pip install -v ./cuda_pathfinder | |
| - name: Build cuda-python-test-helpers | |
| run: | | |
| .venv/bin/pip install -v ./cuda_python_test_helpers | |
| - name: Build cuda-bindings | |
| run: | | |
| cd cuda_bindings | |
| ../.venv/bin/pip install -v . --group test | |
| - name: Build cuda-core | |
| run: | | |
| cd cuda_core | |
| ../.venv/bin/pip install -v . --group test | |
| - name: Install coverage tools | |
| run: | | |
| .venv/bin/pip install coverage pytest-cov Cython | |
| - name: Set cuda package install root | |
| run: | | |
| echo "INSTALL_ROOT=$(.venv/bin/python -c 'import cuda; print(cuda.__path__[0])')/.." >> $GITHUB_ENV | |
| echo "REPO_ROOT=$(pwd)" >> $GITHUB_ENV | |
| - name: Run cuda.pathfinder tests | |
| continue-on-error: true | |
| run: | | |
| cd $INSTALL_ROOT | |
| $REPO_ROOT/.venv/bin/pytest -v --cov=./cuda --cov-append --cov-config=$REPO_ROOT/.coveragerc $REPO_ROOT/cuda_pathfinder/tests | |
| - name: Run cuda.bindings tests | |
| continue-on-error: true | |
| run: | | |
| cd $INSTALL_ROOT | |
| $REPO_ROOT/.venv/bin/pytest -v --cov=./cuda --cov-append --cov-config=$REPO_ROOT/.coveragerc $REPO_ROOT/cuda_bindings/tests | |
| - name: Run cuda.core tests | |
| continue-on-error: true | |
| run: | | |
| cd $INSTALL_ROOT | |
| $REPO_ROOT/.venv/bin/pytest -v --cov=./cuda --cov-append --cov-config=$REPO_ROOT/.coveragerc $REPO_ROOT/cuda_core/tests | |
| - name: Upload Linux coverage data | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 | |
| with: | |
| name: coverage-data-linux | |
| path: ${{ env.INSTALL_ROOT }}/.coverage | |
| include-hidden-files: true | |
| if-no-files-found: error | |
| - name: Upload cuda source code for coverage mapping | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 | |
| with: | |
| name: cuda-source-linux | |
| path: ${{ env.INSTALL_ROOT }}/cuda/ | |
| if-no-files-found: error | |
| coverage-windows: | |
| name: Coverage (Windows) | |
| runs-on: "windows-amd64-gpu-a100-latest-1" | |
| env: | |
| HOST_PLATFORM: "win-64" | |
| ARCH: "amd64" | |
| PY_VER: "3.11" # Windows uses Python 3.11 | |
| CUDA_PYTHON_COVERAGE: "1" | |
| steps: | |
| - name: Ensure GPU is working | |
| run: nvidia-smi | |
| - name: Checkout ${{ github.event.repository.name }} | |
| uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| - name: Setup proxy cache | |
| uses: nv-gha-runners/setup-proxy-cache@main | |
| continue-on-error: true | |
| - name: Set environment variables | |
| shell: bash --noprofile --norc -xeuo pipefail {0} | |
| env: | |
| BUILD_CUDA_VER: ${{ env.CUDA_VER }} | |
| CUDA_VER: ${{ env.CUDA_VER }} | |
| HOST_PLATFORM: ${{ env.HOST_PLATFORM }} | |
| LOCAL_CTK: ${{ env.LOCAL_CTK }} | |
| PY_VER: ${{ env.PY_VER }} | |
| SHA: ${{ github.sha }} | |
| run: ./ci/tools/env-vars test | |
| - name: Set up Python | |
| uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 | |
| with: | |
| python-version: ${{ env.PY_VER }} | |
| - name: Set up mini CTK | |
| if: ${{ env.LOCAL_CTK == '1' }} | |
| uses: ./.github/actions/fetch_ctk | |
| continue-on-error: false | |
| with: | |
| host-platform: ${{ env.HOST_PLATFORM }} | |
| cuda-version: ${{ env.CUDA_VER }} | |
| - name: Create venv | |
| run: | | |
| python -m venv .venv | |
| - name: Build cuda-pathfinder | |
| run: | | |
| .venv\Scripts\pip install -v .\cuda_pathfinder | |
| - name: Build cuda-python-test-helpers | |
| run: | | |
| .venv\Scripts\pip install -v .\cuda_python_test_helpers | |
| - name: Build cuda-bindings | |
| run: | | |
| cd cuda_bindings | |
| ..\.venv\Scripts\pip install -v . --group test | |
| - name: Build cuda-core | |
| run: | | |
| cd cuda_core | |
| ..\.venv\Scripts\pip install -v . --group test | |
| - name: Install coverage tools | |
| run: | | |
| .venv\Scripts\pip install coverage pytest-cov Cython | |
| - name: Get install root | |
| id: install-root | |
| shell: bash | |
| run: | | |
| INSTALL_ROOT=$(.venv/Scripts/python -c 'import cuda; import os; print(os.path.dirname(cuda.__path__[0]))') | |
| echo "INSTALL_ROOT=$INSTALL_ROOT" >> $GITHUB_OUTPUT | |
| echo "Install root: $INSTALL_ROOT" | |
| - name: Run cuda.pathfinder tests | |
| shell: bash | |
| continue-on-error: true | |
| run: | | |
| cd "${{ steps.install-root.outputs.INSTALL_ROOT }}" | |
| "$GITHUB_WORKSPACE/.venv/Scripts/pytest" -v --cov=./cuda --cov-append --cov-config="$GITHUB_WORKSPACE/.coveragerc" "$GITHUB_WORKSPACE/cuda_pathfinder/tests" | |
| - name: Run cuda.bindings tests (skip if known stack overflow) | |
| shell: bash | |
| continue-on-error: true | |
| run: | | |
| cd "${{ steps.install-root.outputs.INSTALL_ROOT }}" | |
| "$GITHUB_WORKSPACE/.venv/Scripts/pytest" -v --cov=./cuda --cov-append --cov-config="$GITHUB_WORKSPACE/.coveragerc" "$GITHUB_WORKSPACE/cuda_bindings/tests" | |
| - name: Run cuda.core tests | |
| shell: bash | |
| continue-on-error: true | |
| run: | | |
| cd "${{ steps.install-root.outputs.INSTALL_ROOT }}" | |
| "$GITHUB_WORKSPACE/.venv/Scripts/pytest" -v --cov=./cuda --cov-append --cov-config="$GITHUB_WORKSPACE/.coveragerc" "$GITHUB_WORKSPACE/cuda_core/tests" | |
| - name: Upload Windows coverage data | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 | |
| with: | |
| name: coverage-data-windows | |
| path: ${{ steps.install-root.outputs.INSTALL_ROOT }}/.coverage | |
| include-hidden-files: true | |
| if-no-files-found: warn | |
| combine-and-deploy: | |
| name: Combine Coverage and Deploy | |
| needs: [coverage-linux, coverage-windows] | |
| runs-on: ubuntu-latest | |
| if: always() | |
| permissions: | |
| id-token: write | |
| contents: write | |
| steps: | |
| - name: Checkout ${{ github.event.repository.name }} | |
| uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| - name: Set up Python | |
| uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 | |
| with: | |
| python-version: ${{ env.PY_VER }} | |
| - name: Install coverage | |
| run: | | |
| # .coveragerc enables Cython.Coverage plugin; ensure it's available here too. | |
| pip install coverage[toml] Cython | |
| - name: Download Linux coverage data | |
| uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 | |
| with: | |
| name: coverage-data-linux | |
| path: ./coverage-data/linux/ | |
| - name: Download cuda source code | |
| uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 | |
| with: | |
| name: cuda-source-linux | |
| path: ./cuda/ | |
| - name: Download Windows coverage data | |
| uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 | |
| continue-on-error: true | |
| with: | |
| name: coverage-data-windows | |
| path: ./coverage-data/windows/ | |
| - name: List downloaded coverage files | |
| run: | | |
| echo "=== Coverage data structure ===" | |
| find ./coverage-data -type f -name ".coverage*" -ls | |
| - name: Combine coverage data | |
| run: | | |
| # Collect all .coverage files, copy them to uniquely named files to avoid overwrites, | |
| # then combine. | |
| i=0 | |
| while IFS= read -r -d '' f; do | |
| i=$((i+1)) | |
| cp "$f" "./.coverage.$i" | |
| done < <(find ./coverage-data -type f -name ".coverage*" -print0) | |
| if [ "$i" -eq 0 ]; then | |
| echo "ERROR: no .coverage files found under ./coverage-data" >&2 | |
| exit 1 | |
| fi | |
| echo "=== Coverage files (staged for combine) ===" | |
| ls -la .coverage.* | |
| echo "=== Cuda source structure ===" | |
| find ./cuda -type d | |
| # Combine all coverage files (with source code available in ./cuda) | |
| coverage combine --rcfile=./.coveragerc --keep .coverage.* | |
| # Generate reports (with source code available) | |
| coverage html --rcfile=./.coveragerc | |
| coverage xml --rcfile=./.coveragerc -o coverage.xml | |
| coverage report --rcfile=./.coveragerc | |
| # Prepare for upload | |
| mkdir -p ./docs/coverage | |
| mv htmlcov/* ./docs/coverage/ | |
| mv coverage.xml ./docs/coverage/ | |
| - name: Archive combined coverage results | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 | |
| with: | |
| name: coverage-combined | |
| path: docs/coverage/ | |
| include-hidden-files: true | |
| - name: Deploy to gh-pages | |
| uses: JamesIves/github-pages-deploy-action@9d877eea73427180ae43cf98e8914934fe157a1a # v4.7.6 | |
| with: | |
| git-config-name: cuda-python-bot | |
| git-config-email: cuda-python-bot@users.noreply.github.com | |
| folder: docs/ | |
| target-folder: docs/ | |
| commit-message: "Deploy combined coverage (Linux + Windows): ${{ github.sha }}" | |
| clean: false |