Build wheels (release + manual) #1
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: Build wheels (release + manual) | |
| on: | |
| release: | |
| types: [created] | |
| workflow_dispatch: {} | |
| permissions: | |
| contents: write # needed to upload assets to the Release | |
| jobs: | |
| build_wheels: | |
| name: Wheels (${{ matrix.os }} ${{ matrix.arch }}) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| # Linux x86_64 | |
| - os: ubuntu-latest | |
| arch: x86_64 | |
| cibw_archs: x86_64 | |
| # Linux aarch64 — native ARM runner, no QEMU (produces Raspberry Pi wheel) | |
| - os: ubuntu-24.04-arm | |
| arch: aarch64 | |
| cibw_archs: aarch64 | |
| # macOS x86_64 (Intel) | |
| - os: macos-15-intel | |
| arch: x86_64 | |
| cibw_archs: x86_64 | |
| # macOS arm64 (Apple Silicon) | |
| - os: macos-latest | |
| arch: arm64 | |
| cibw_archs: arm64 | |
| # Windows AMD64 | |
| - os: windows-latest | |
| arch: AMD64 | |
| cibw_archs: AMD64 | |
| # Windows ARM64 | |
| - os: windows-11-arm | |
| arch: ARM64 | |
| cibw_archs: ARM64 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Sync version to release tag | |
| if: github.event_name == 'release' | |
| shell: python | |
| run: | | |
| import re | |
| tag = "${{ github.event.release.tag_name }}" | |
| version = tag.lstrip("v") | |
| print(f"Setting version to {version} (from tag {tag})") | |
| with open("pyproject.toml", "r") as f: | |
| content = f.read() | |
| content = re.sub(r'^version = ".*"', f'version = "{version}"', content, flags=re.MULTILINE) | |
| with open("pyproject.toml", "w") as f: | |
| f.write(content) | |
| - name: Build wheels with cibuildwheel | |
| env: | |
| CIBW_BUILD: "cp311-* cp312-* cp313-* cp314-*" | |
| CIBW_SKIP: "pp* *musllinux*" | |
| CIBW_ARCHS: ${{ matrix.cibw_archs }} | |
| CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28 | |
| CIBW_MANYLINUX_AARCH64_IMAGE: manylinux_2_28 | |
| CIBW_TEST_COMMAND: "python -c \"import numpy as np; import importlib; import roboticstoolbox as rtb; importlib.import_module('roboticstoolbox.frne'); importlib.import_module('roboticstoolbox.fknm'); print(rtb.__version__)\"" | |
| CIBW_ENVIRONMENT_MACOS: "MACOSX_DEPLOYMENT_TARGET=11.0" | |
| run: | | |
| python -m pip install -U pip | |
| pip install -U cibuildwheel | |
| python -m cibuildwheel --output-dir wheelhouse | |
| # Always upload artifacts — the publish job downloads these on release, | |
| # and they are available for manual inspection on workflow_dispatch runs. | |
| - name: Upload wheels artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: wheels-${{ matrix.os }}-${{ matrix.arch }} | |
| path: wheelhouse/*.whl | |
| - name: Upload wheels to Release assets | |
| if: github.event_name == 'release' | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: wheelhouse/*.whl | |
| sdist: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Sync version to release tag | |
| if: github.event_name == 'release' | |
| run: | | |
| TAG="${{ github.event.release.tag_name }}" | |
| VERSION="${TAG#v}" | |
| echo "Setting version to $VERSION (from tag $TAG)" | |
| sed -i "s/^version = \".*\"/version = \"$VERSION\"/" pyproject.toml | |
| grep "^version" pyproject.toml | |
| - name: Build sdist | |
| run: | | |
| python -m pip install -U build | |
| python -m build --sdist | |
| # Always upload — publish job needs this on release runs too. | |
| - name: Upload sdist artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: sdist | |
| path: dist/*.tar.gz | |
| - name: Upload sdist to Release assets | |
| if: github.event_name == 'release' | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: dist/*.tar.gz | |
| # Publishes all wheels + sdist to PyPI using OIDC Trusted Publishing. | |
| # Runs only when a GitHub Release is created — never on pushes or | |
| # workflow_dispatch. No hardcoded tokens are needed; configure a Trusted | |
| # Publisher on PyPI (see RELEASING.md). | |
| publish: | |
| name: Publish to PyPI | |
| needs: [build_wheels, sdist] | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'release' | |
| environment: pypi | |
| permissions: | |
| id-token: write # required for OIDC Trusted Publishing | |
| steps: | |
| - name: Download all wheel artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: wheels-* | |
| path: dist/ | |
| merge-multiple: true | |
| - name: Download sdist artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: sdist | |
| path: dist/ | |
| - name: List files to publish | |
| run: ls -la dist/ | |
| - name: Publish to PyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| packages-dir: dist/ | |
| update-version: | |
| name: Update version in codebase | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'release' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: master | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Update version and commit | |
| run: | | |
| TAG="${{ github.event.release.tag_name }}" | |
| VERSION="${TAG#v}" | |
| # Get current version | |
| CURRENT=$(grep -E '^version = "' pyproject.toml | sed -E 's/.*"(.*)".*/\1/') | |
| if [[ "$CURRENT" == "$VERSION" ]]; then | |
| echo "Version already matches ($VERSION), skipping" | |
| exit 0 | |
| fi | |
| echo "Updating version from $CURRENT to $VERSION" | |
| sed -i "s/^version = \".*\"/version = \"$VERSION\"/" pyproject.toml | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add pyproject.toml | |
| git commit -m "Bump version from $CURRENT to $VERSION" | |
| git push |