Skip to content

ENH: Test wheels

ENH: Test wheels #23

Workflow file for this run

# Build wheels, sdist, and upload to PyPI
# code adapted from antio and openmeeg
name: Build
concurrency:
group: ${{ github.workflow }}-${{ github.event.number }}-${{ github.event.ref }}
cancel-in-progress: true
on: # yamllint disable-line rule:truthy
# Non-PR triggers build all wheels.
workflow_dispatch:
push:
tags:
- 'v*.*.*'
branches:
- master
# By default, PRs do not build wheels (for speed/efficiency). However,
# a PR's commit message containing the following text will build:
# - "[wheels]" : all wheels
# - "[wheels thin]" : just the wheels required for the test_wheels jobs (3.8, 3.11-abi3)
pull_request:
branches:
- master
jobs:
# Adapted from dipy (BSD)
check-commit:
name: Triage wheel build
runs-on: ubuntu-latest
outputs:
proceed: ${{ steps.commit-message.outputs.PROCEED }}
cibw_skip: ${{ steps.commit-message.outputs.CIBW_SKIP }}
defaults:
run:
shell: bash -el {0}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 2
- name: Check commit message for [wheels]
id: commit-message
run: |
PROCEED=true
CIBW_SKIP="cp38-*musllinux* cp39-musllinux_aarch64"
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
MSG=$(git show -s --format=%s ${{ github.event.pull_request.head.sha }})
echo "Got commit message: $MSG"
if echo "$MSG" | grep -iq '\[wheels\]'; then
PROCEED=true
elif echo "$MSG" | grep -iq '\[wheels thin\]'; then
PROCEED=true
# We don't need the Intel macOS or Ubuntu aarch64 builds at all
CIBW_SKIP="*musllinux* cp39-* cp310-* *-macosx*x86_64 *-*linux*aarch64"
else
PROCEED=false
fi
fi
echo "PROCEED=$PROCEED" | tee -a $GITHUB_OUTPUT
echo "CIBW_SKIP=$CIBW_SKIP" | tee -a $GITHUB_OUTPUT
build_wheels:
name: Wheels ${{ matrix.os }}
needs: [check-commit]
if: needs.check-commit.outputs.proceed == 'true'
runs-on: ${{ matrix.os }}
timeout-minutes: 20
strategy:
matrix:
os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest, macos-15-intel, windows-latest] # windows-11-arm
fail-fast: false
steps:
- uses: actions/checkout@v6
- uses: pypa/cibuildwheel@v3.3.1
env:
CIBW_SKIP: ${{ needs.check-commit.outputs.cibw_skip }}
CIBW_ALLOW_EMPTY: "True"
- uses: actions/upload-artifact@v6
with:
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
path: ./wheelhouse/*.whl
test_wheels:
needs: [build_wheels]
name: Test wheels
runs-on: ${{ matrix.os }}
timeout-minutes: 5
defaults:
run:
shell: bash -el {0}
strategy:
matrix:
os: [ubuntu-22.04, macos-14, windows-2022]
# oldest using oldest deps, one with newest using prerelease deps
python: ['3.8', '3.14']
fail-fast: false
steps:
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
- uses: actions/download-artifact@v6
with:
pattern: cibw-wheels-*
merge-multiple: true
path: dist
- run: ls -alt dist/
# Choose versions from 2022 (somewhat arbitrarily)
- name: Triage env vars
run: |
NUMPY_SCIPY="numpy scipy"
if [[ "${{ matrix.python }}" == "3.8" ]]; then
NUMPY_SCIPY="numpy==1.23 scipy==1.8"
elif [[ "${{ matrix.python }}" == "3.14" ]]; then
NUMPY_SCIPY="numpy scipy --pre --extra-index-url=https://pypi.anaconda.org/scientific-python-nightly-wheels/simple"
fi
echo "NUMPY_SCIPY=$NUMPY_SCIPY" | tee -a $GITHUB_ENV
- run: pip install $NUMPY_SCIPY nibabel pillow xxhash --only-binary=":all:"
- run: pip install --no-index --find-links=dist/ surfa
- run: python -c "import surfa; print(surfa.__version__)"
sdist:
timeout-minutes: 10
name: Create sdist
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: astral-sh/setup-uv@v6
- run: uv build --sdist
- uses: actions/upload-artifact@v6
with:
name: cibw-wheels-sdist
path: ./dist/*.tar.gz
check:
needs: [build_wheels, sdist]
timeout-minutes: 10
name: Twine check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/download-artifact@v6
with:
pattern: cibw-wheels-*
merge-multiple: true
path: dist
- run: ls -alt . && ls -alt dist/
- uses: astral-sh/setup-uv@v6
with:
activate-environment: true
- run: uv pip install twine -q --upgrade
- run: twine check --strict dist/*
publish:
# once ready to cut wheels to PyPI (e.g., numpy 1 support is dropped), remove the
# "false &&" below
if: false && github.repository == 'freesurfer/surfa' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
needs: [check]
name: publish PyPI
runs-on: ubuntu-latest
permissions:
id-token: write
environment:
name: pypi
url: https://pypi.org/p/surfa
timeout-minutes: 10
steps:
- uses: actions/download-artifact@v6
with:
pattern: cibw-wheels-*
merge-multiple: true
path: dist
- uses: pypa/gh-action-pypi-publish@release/v1
- uses: softprops/action-gh-release@v2
with:
files: dist/*
tag_name: ${{ github.event.release.tag_name }}