diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml new file mode 100644 index 00000000..ce5cc4b0 --- /dev/null +++ b/.github/workflows/build-macos.yml @@ -0,0 +1,119 @@ +name: build-macos + +on: + push: + branches: + - main + tags: + - "[0-9]*.[0-9]*.[0-9]*" + paths-ignore: + - ".github/workflows/build.yml" + - ".github/workflows/build-windows.yml" + pull_request: + branches: + - main + paths-ignore: + - ".github/workflows/build.yml" + - ".github/workflows/build-windows.yml" + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build-wheel: + if: ${{ github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'docs-only') }} + runs-on: macos-13 + permissions: + contents: read + env: + CIBW_BUILD: cp312-* + CIBW_ENVIRONMENT: SETUPTOOLS_SCM_PRETEND_VERSION_FOR_COMPAS_CGAL=${{ github.ref_type == 'tag' && github.ref_name || '' }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Build wheels + run: pipx run --spec cibuildwheel==2.23.1 cibuildwheel --output-dir wheelhouse . + + - uses: actions/upload-artifact@v4 + with: + name: python-cp312-macos + path: wheelhouse/*.whl + + test-wheel: + if: ${{ github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'docs-only') }} + needs: build-wheel + strategy: + fail-fast: false + matrix: + include: + - runner: macos-13 + python-version: "3.12" + wheel-glob: "*x86_64.whl" + - runner: macos-14 + python-version: "3.13" + wheel-glob: "*arm64.whl" + runs-on: ${{ matrix.runner }} + permissions: + contents: read + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - uses: actions/download-artifact@v4 + with: + name: python-cp312-macos + path: dist + + - name: Install wheel in a clean virtual environment + run: | + WHEEL=$(find dist -name "${{ matrix.wheel-glob }}" -print -quit) + [ -n "$WHEEL" ] || { echo "::error::No wheel found matching ${{ matrix.wheel-glob }}"; exit 1; } + python -m venv .venv + . .venv/bin/activate + python -m pip install --upgrade pip + python -m pip install pytest "$WHEEL" + python -c "import compas_cgal; print(compas_cgal.__version__)" + python -m pytest tests + + publish: + needs: + - build-wheel + - test-wheel + if: startsWith(github.ref, 'refs/tags/') + runs-on: ubuntu-latest + environment: macos + permissions: + contents: read + id-token: write + steps: + - uses: actions/download-artifact@v4 + with: + pattern: "python-*-macos*" + merge-multiple: true + path: dist + + - name: Assert wheel versions match the tag + run: | + [[ "$GITHUB_REF_NAME" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "::error::Expected a bare X.Y.Z tag, got $GITHUB_REF_NAME"; exit 1; } + shopt -s nullglob + wheels=(dist/*.whl) + [ ${#wheels[@]} -gt 0 ] || { echo "::error::No wheels were downloaded for publishing"; exit 1; } + for whl in "${wheels[@]}"; do + v=$(basename "$whl" | cut -d- -f2) + [ "$v" = "$GITHUB_REF_NAME" ] || { echo "::error::$whl is $v, expected $GITHUB_REF_NAME"; exit 1; } + done + + - uses: pypa/gh-action-pypi-publish@release/v1 + with: + skip-existing: true diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml new file mode 100644 index 00000000..6d2b66d7 --- /dev/null +++ b/.github/workflows/build-windows.yml @@ -0,0 +1,113 @@ +name: build-windows + +on: + push: + branches: + - main + tags: + - "[0-9]*.[0-9]*.[0-9]*" + paths-ignore: + - ".github/workflows/build.yml" + - ".github/workflows/build-macos.yml" + pull_request: + branches: + - main + paths-ignore: + - ".github/workflows/build.yml" + - ".github/workflows/build-macos.yml" + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build-wheel: + if: ${{ github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'docs-only') }} + runs-on: windows-2022 + permissions: + contents: read + env: + CIBW_BUILD: cp312-* + CIBW_ENVIRONMENT: SETUPTOOLS_SCM_PRETEND_VERSION_FOR_COMPAS_CGAL=${{ github.ref_type == 'tag' && github.ref_name || '' }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Build wheels + run: pipx run --spec cibuildwheel==2.23.1 cibuildwheel --output-dir wheelhouse . + + - uses: actions/upload-artifact@v4 + with: + name: python-cp312-windows-amd64 + path: wheelhouse/*.whl + + test-wheel: + if: ${{ github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'docs-only') }} + needs: build-wheel + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.12", "3.13"] + permissions: + contents: read + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - uses: actions/download-artifact@v4 + with: + name: python-cp312-windows-amd64 + path: dist + + - name: Install wheel in a clean virtual environment + shell: pwsh + run: | + python -m venv .venv + .\.venv\Scripts\python -m pip install --upgrade pip + $wheel = (Get-ChildItem dist\*.whl | Select-Object -First 1).FullName + if (-not $wheel) { throw "No wheel found in dist" } + .\.venv\Scripts\python -m pip install pytest $wheel + .\.venv\Scripts\python -c "import compas_cgal; print(compas_cgal.__version__)" + .\.venv\Scripts\python -m pytest tests + + publish: + needs: + - build-wheel + - test-wheel + if: startsWith(github.ref, 'refs/tags/') + runs-on: ubuntu-latest + environment: windows + permissions: + contents: read + id-token: write + steps: + - uses: actions/download-artifact@v4 + with: + pattern: "python-*-windows-*" + merge-multiple: true + path: dist + + - name: Assert wheel versions match the tag + run: | + [[ "$GITHUB_REF_NAME" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "::error::Expected a bare X.Y.Z tag, got $GITHUB_REF_NAME"; exit 1; } + shopt -s nullglob + wheels=(dist/*.whl) + [ ${#wheels[@]} -gt 0 ] || { echo "::error::No wheels were downloaded for publishing"; exit 1; } + for whl in "${wheels[@]}"; do + v=$(basename "$whl" | cut -d- -f2) + [ "$v" = "$GITHUB_REF_NAME" ] || { echo "::error::$whl is $v, expected $GITHUB_REF_NAME"; exit 1; } + done + + - uses: pypa/gh-action-pypi-publish@release/v1 + with: + skip-existing: true diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 12109340..a17b9899 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,87 +4,108 @@ on: push: branches: - main + tags: + - "[0-9]*.[0-9]*.[0-9]*" + paths-ignore: + - ".github/workflows/build-macos.yml" + - ".github/workflows/build-windows.yml" pull_request: branches: - main + paths-ignore: + - ".github/workflows/build-macos.yml" + - ".github/workflows/build-windows.yml" + workflow_dispatch: -jobs: - Build: - if: ${{ !contains(github.event.pull_request.labels.*.name, 'docs-only') }} - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - python: ["3.10"] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true +jobs: + build-wheel: + if: ${{ github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'docs-only') }} + runs-on: ubuntu-22.04 + permissions: + contents: read + env: + CIBW_BUILD: cp312-* + CIBW_ENVIRONMENT: SETUPTOOLS_SCM_PRETEND_VERSION_FOR_COMPAS_CGAL=${{ github.ref_type == 'tag' && github.ref_name || '' }} steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - - - name: Set up conda - uses: conda-incubator/setup-miniconda@v3 + + - uses: actions/setup-python@v5 with: - python-version: ${{ matrix.python }} - channels: conda-forge - activate-environment: "compas_123-dev" - - - name: Configure conda channels - shell: bash -el {0} - run: | - conda config --add channels defaults - conda config --set channel_priority strict - - - uses: compas-dev/compas-actions.build@v4 + python-version: "3.12" + + - name: Build wheels + run: pipx run --spec cibuildwheel==2.23.1 cibuildwheel --output-dir wheelhouse . + + - uses: actions/upload-artifact@v4 with: - invoke_lint: true - use_conda: true - check_import: true - python: ${{ matrix.python }} - - build_wheels: - name: cibuildwheel on ${{ matrix.platform }} - needs: [Build] # Only run if Build job succeeds - runs-on: ${{ matrix.os }} + name: python-cp312-linux-x86_64 + path: wheelhouse/*.whl + + test-wheel: + if: ${{ github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'docs-only') }} + needs: build-wheel + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: - include: - - os: ubuntu-latest - platform: manylinux - - os: macos-latest - platform: mac - - os: windows-latest - platform: windows - + python-version: ["3.12", "3.13"] + permissions: + contents: read steps: - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Install cibuildwheel - run: pipx install cibuildwheel==2.23.1 - - - name: Build wheels - run: cibuildwheel --output-dir wheelhouse . + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} - - uses: actions/upload-artifact@v4 + - uses: actions/download-artifact@v4 with: - name: wheels-${{ matrix.platform }} - path: wheelhouse/*.whl + name: python-cp312-linux-x86_64 + path: dist - build_sdist: - name: Test source distribution + - name: Install wheel in a clean virtual environment + run: | + python -m venv .venv + . .venv/bin/activate + python -m pip install --upgrade pip + python -m pip install pytest dist/*.whl + python -c "import compas_cgal; print(compas_cgal.__version__)" + python -m pytest tests + + publish: + needs: + - build-wheel + - test-wheel + if: startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest + environment: linux + permissions: + contents: read + id-token: write steps: - - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 with: - fetch-depth: 0 + pattern: "python-*-linux-*" + merge-multiple: true + path: dist - - name: Build SDist - run: pipx run build --sdist + - name: Assert wheel versions match the tag + run: | + [[ "$GITHUB_REF_NAME" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "::error::Expected a bare X.Y.Z tag, got $GITHUB_REF_NAME"; exit 1; } + shopt -s nullglob + wheels=(dist/*.whl) + [ ${#wheels[@]} -gt 0 ] || { echo "::error::No wheels were downloaded for publishing"; exit 1; } + for whl in "${wheels[@]}"; do + v=$(basename "$whl" | cut -d- -f2) + [ "$v" = "$GITHUB_REF_NAME" ] || { echo "::error::$whl is $v, expected $GITHUB_REF_NAME"; exit 1; } + done - - uses: actions/upload-artifact@v4 + - uses: pypa/gh-action-pypi-publish@release/v1 with: - name: sdist - path: dist/*.tar.gz \ No newline at end of file + skip-existing: true \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 0d2e13d8..00000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,96 +0,0 @@ -name: Release - -on: - push: - tags: - - "v*" # Runs only when a version tag (e.g., v1.0.0) is pushed. - -jobs: - create_release: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - - name: Create GitHub Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.ref }} - release_name: Release ${{ github.ref }} - draft: false - prerelease: false - - build_wheels: - name: Build wheels on ${{ matrix.platform }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu-latest - platform: manylinux - - os: macos-latest - platform: mac - - os: windows-latest - platform: windows - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Install cibuildwheel - run: pipx install cibuildwheel==2.23.1 - - - name: Build wheels - run: cibuildwheel --output-dir wheelhouse . - - - uses: actions/upload-artifact@v4 - with: - name: wheels-${{ matrix.platform }} - path: wheelhouse/*.whl - - build_sdist: - name: Build source distribution - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Build SDist - run: pipx run build --sdist - - - uses: actions/upload-artifact@v4 - with: - name: sdist - path: dist/*.tar.gz - - publish: - needs: [build_sdist, build_wheels] - runs-on: ubuntu-latest - environment: - name: pypi - url: https://pypi.org/project/compas_cgal - permissions: - id-token: write # Required for PyPI trusted publishing - - steps: - - uses: actions/download-artifact@v4 - with: - pattern: wheels-* - path: dist - merge-multiple: true - - - uses: actions/download-artifact@v4 - with: - name: sdist - path: dist - - - name: List files before upload - run: ls -lhR dist - - - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/pyproject.toml b/pyproject.toml index 67e629bb..bd4ad96f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["scikit-build-core >=0.10", "nanobind >=2.12"] +requires = ["scikit-build-core >=0.10", "nanobind >=2.12", "setuptools-scm >=8"] build-backend = "scikit_build_core.build" [project] @@ -69,8 +69,10 @@ cmake.version = ">=3.15" cmake.build-type = "Release" [tool.scikit-build.metadata.version] -provider = "scikit_build_core.metadata.regex" -input = "src/compas_cgal/__init__.py" +provider = "scikit_build_core.metadata.setuptools_scm" + +[tool.setuptools_scm] +local_scheme = "no-local-version" [tool.scikit-build.cmake.define] CMAKE_POLICY_DEFAULT_CMP0135 = "NEW" @@ -80,10 +82,10 @@ CMAKE_POLICY_DEFAULT_CMP0135 = "NEW" # ============================================================================ [tool.cibuildwheel] -# build = ["cp38-*", "cp39-*", "cp31?-*"] # Build for specific Python versions. +build = ["cp312-*"] build-verbosity = 3 -test-requires = ["numpy>=1.24", "compas>=2.15", "pytest", "build"] -test-command = "pip list && pytest {project}/tests" +test-requires = ["numpy>=2.4", "compas>=2.15,<3", "pytest"] +test-command = "python -m pip install --force-reinstall --no-deps {wheel} && python -c \"import compas_cgal; print(compas_cgal.__version__)\" && python -m pytest {project}/tests" build-frontend = "pip" manylinux-x86_64-image = "manylinux_2_28" skip = ["*_i686", "*-musllinux_*", "*-win32", "pp*"] @@ -101,9 +103,9 @@ commit = true tag = true [[tool.bumpversion.files]] -filename = "src/compas_cgal/__init__.py" -search = "{current_version}" -replace = "{new_version}" +filename = "pyproject.toml" +search = 'current_version = "{current_version}"' +replace = 'current_version = "{new_version}"' [[tool.bumpversion.files]] filename = "CHANGELOG.md" diff --git a/src/compas_cgal/__init__.py b/src/compas_cgal/__init__.py index 03b34a39..4b338d7d 100644 --- a/src/compas_cgal/__init__.py +++ b/src/compas_cgal/__init__.py @@ -1,11 +1,16 @@ import os +from importlib.metadata import PackageNotFoundError +from importlib.metadata import version __author__ = ["tom van mele", "petras vestartas"] __copyright__ = "Block Research Group - ETH Zurich" __license__ = "MIT License" __email__ = ["van.mele@arch.ethz.ch", "vestartas@arch.ethz.ch"] -__version__ = "0.9.5" +try: + __version__ = version("compas_cgal") +except PackageNotFoundError: + __version__ = "0.0.0" HERE = os.path.dirname(__file__)