diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index de25603..6774b05 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,21 +10,42 @@ on: jobs: build-package: - name: Build package + name: Build on ${{ matrix.os }} (Torch ${{ matrix.torch }}, CUDA ${{ matrix.cuda }}) runs-on: ${{ matrix.os }} if: >- github.event_name != 'pull_request' || startsWith(github.event.pull_request.title, 'RELEASE') || - contains(github.event.pull_request.labels.*.name, 'build') + contains(github.event.pull_request.labels.*.name, 'build') || + contains(github.event.pull_request.labels.*.name, 'test-pypi') strategy: + fail-fast: false matrix: os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest, windows-latest] + torch: ["2.9.1", "2.10.0"] + cuda: [true, false] + exclude: + # Exclude CUDA builds for OS/Arch combinations that don't support it + - os: macos-latest + cuda: true + - os: ubuntu-24.04-arm + cuda: true steps: - uses: actions/checkout@v6 with: fetch-depth: 0 + - name: Rename package for TestPyPI + if: contains(github.event.pull_request.labels.*.name, 'test-pypi') + shell: bash + run: | + # Using -i.bak makes it compatible with both GNU (Linux/Windows) and BSD (macOS) sed + sed -i.bak 's/name = "digeo"/name = "digeo-test"/g' pyproject.toml + echo "Renamed package to digeo-test in pyproject.toml" + + sed -i.bak 's/library_name = "digeo"/library_name = "digeo-test"/g' setup.py + echo "Renamed package to digeo-test in setup.py" + - name: Set up Python uses: actions/setup-python@v6 with: @@ -33,21 +54,12 @@ jobs: - name: Free Disk Space if: runner.os == 'Linux' run: | - echo "Disk space before cleanup:" - df -h - - # Remove heavy software suites sudo rm -rf /usr/share/dotnet sudo rm -rf /usr/local/lib/android sudo rm -rf /opt/ghc sudo rm -rf /opt/hostedtoolcache/CodeQL - - # Clean up apt cache sudo apt-get clean - echo "Disk space after cleanup:" - df -h - - name: Install build tools run: | python -m pip install --upgrade pip setuptools wheel build cibuildwheel @@ -59,12 +71,15 @@ jobs: CIBW_BUILD_VERBOSITY: 1 CIBW_ARCHS_LINUX: "auto" CIBW_SKIP: "*musl*" + CIBW_BEFORE_BUILD: > + rm -rf /opt/python/*/lib/python*/site-packages/nvidia* /opt/python/*/lib/python*/site-packages/torch* /tmp/build-env-* /tmp/pip-* || true && + pip install torch==${{ matrix.torch }} CIBW_REPAIR_WHEEL_COMMAND_LINUX: > auditwheel repair -w {dest_dir} {wheel} --exclude libtorch* --exclude libc10* - # Only download and install CUDA on Intel (X64) runners + # Only download CUDA toolkit if matrix.cuda is true CIBW_BEFORE_ALL: > - if [ "${{ runner.arch }}" = "X64" ]; then + if [ "${{ matrix.cuda }}" = "true" ]; then if command -v dnf >/dev/null 2>&1; then dnf install -y dnf-plugins-core && dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel8/x86_64/cuda-rhel8.repo && @@ -78,16 +93,17 @@ jobs: fi && /usr/local/cuda-12.8/bin/nvcc --version; else - echo "ARM64 architecture detected. Skipping CUDA toolkit installation."; + echo "CPU-only build. Skipping CUDA toolkit installation."; fi - # Dynamically toggle USE_CUDA based on runner hardware, and add CUDA_HOME + # Dynamically toggle USE_CUDA and PyTorch index URL CIBW_ENVIRONMENT: > - USE_CUDA=${{ runner.arch == 'X64' && '1' || '0' }} + USE_CUDA=${{ matrix.cuda == true && '1' || '0' }} CUDA_HOME=/usr/local/cuda-12.8 PATH=$PATH:/usr/local/cuda-12.8/bin TORCH_CUDA_ARCH_LIST='7.5;8.0;8.6;8.9;9.0+PTX' PIP_NO_CACHE_DIR=1 + PIP_EXTRA_INDEX_URL=${{ matrix.cuda == true && 'https://download.pytorch.org/whl/cu128' || 'https://download.pytorch.org/whl/cpu' }} - name: Build macOS CPU Wheels if: runner.os == 'macOS' @@ -95,12 +111,13 @@ jobs: env: CIBW_BUILD_VERBOSITY: 1 CIBW_ARCHS_MACOS: "x86_64 arm64" + CIBW_BEFORE_BUILD: "pip install torch==${{ matrix.torch }}" CIBW_REPAIR_WHEEL_COMMAND_MACOS: > delocate-wheel -w {dest_dir} {wheel} --exclude libtorch* --exclude libc10* --ignore-missing-dependencies - CIBW_ENVIRONMENT: "USE_CUDA=0" + CIBW_ENVIRONMENT: "USE_CUDA=0 PIP_NO_CACHE_DIR=1" - name: Install CUDA Toolkit on Windows - if: runner.os == 'Windows' + if: runner.os == 'Windows' && matrix.cuda == true shell: pwsh run: | # Use the LOCAL installer @@ -130,32 +147,37 @@ jobs: env: CIBW_BUILD_VERBOSITY: 1 CIBW_ARCHS_WINDOWS: "auto" - CIBW_BEFORE_BUILD: "pip install ninja" + CIBW_BEFORE_BUILD: > + rm -rf /opt/python/*/lib/python*/site-packages/nvidia* /opt/python/*/lib/python*/site-packages/torch* /tmp/build-env-* /tmp/pip-* || true && + pip install torch==${{ matrix.torch }} ninja CIBW_ENVIRONMENT: > - USE_CUDA=1 + USE_CUDA=${{ matrix.cuda == true && '1' || '0' }} CUDA_HOME="C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v12.8" PATH="$PATH;C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v12.8/bin" TORCH_CUDA_ARCH_LIST="7.5;8.0;8.6;8.9;9.0+PTX" PIP_NO_CACHE_DIR=1 - PIP_EXTRA_INDEX_URL="https://download.pytorch.org/whl/cu128" + PIP_EXTRA_INDEX_URL=${{ matrix.cuda == true && 'https://download.pytorch.org/whl/cu128' || 'https://download.pytorch.org/whl/cpu' }} - name: Upload dist artifacts uses: actions/upload-artifact@v7 with: - name: python-package-${{ matrix.os }} + # Appends -cuda or -cpu to the folder name so they don't overwrite + name: python-package-${{ matrix.os }}-torch${{ matrix.torch }}-${{ matrix.cuda == true && 'cuda' || 'cpu' }} path: dist/* publish-to-pypi: - name: Publish package on PyPI + name: Publish package to PyPI or Test PyPI needs: build-package runs-on: ubuntu-latest - # Only run when the ref is a tag pushed (push event with tags) - if: ${{ startsWith(github.ref, 'refs/tags') }} + if: >- + github.event_name != 'pull_request' || + contains(github.event.pull_request.labels.*.name, 'test-pypi') environment: name: pypi url: https://pypi.org/p/digeo/ permissions: id-token: write + steps: - name: Wait for all tests to succeed uses: fountainhead/action-wait-for-check@v1.2.0 @@ -163,27 +185,45 @@ jobs: with: token: ${{ github.token }} checkName: report_test - timeoutSeconds: 1600 # timeout after 30min - intervalSeconds: 30 # check every 30sec - ref: ${{ github.sha }} + timeoutSeconds: 1600 + intervalSeconds: 30 + ref: ${{ github.event.pull_request.head.sha || github.sha }} + - name: Download dist artifacts uses: actions/download-artifact@v8 with: pattern: python-package-* merge-multiple: true path: dist - - name: Publish distribution to PyPI + + - name: Determine PyPI target + id: pypi_target + run: | + if [[ "${GITHUB_EVENT_NAME}" == "pull_request" ]]; then + if [[ $(jq -r '.pull_request.labels[].name' "$GITHUB_EVENT_PATH") == *"test-pypi"* ]]; then + echo "TARGET=testpypi" >> $GITHUB_ENV + else + echo "TARGET=pypi" >> $GITHUB_ENV + fi + else + echo "TARGET=pypi" >> $GITHUB_ENV + fi + + - name: Publish distribution if: ${{ success() && steps.wait-for-tests.outputs.conclusion == 'success' }} uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: ${{ env.TARGET == 'testpypi' && 'https://test.pypi.org/legacy/' || '' }} + user: __token__ + password: ${{ secrets.PYPI_API_TOKEN }} github-release: - name: >- - Sign the distribution with Sigstore - and upload them to GitHub Release + name: Sign the distribution with Sigstore and upload to GitHub Release + if: >- + github.event_name != 'pull_request' needs: - publish-to-pypi runs-on: ubuntu-latest - permissions: contents: write id-token: write diff --git a/src/digeo/__init__.py b/src/digeo/__init__.py index 51aa98c..e9a09be 100644 --- a/src/digeo/__init__.py +++ b/src/digeo/__init__.py @@ -1,7 +1,7 @@ from digeo.mesh import Mesh, MeshBatch, MeshPoint, MeshPointBatch from digeo.mesh_loader import load_mesh_from_file, load_mesh_from_trimesh -__version__ = "0.0.7" +__version__ = "0.0.7a" __all__ = [ "Mesh", "MeshBatch",