Add broad testing for Python 3.13 #608
Workflow file for this run
This file contains 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 and test | ||
# This file tests the claimed support range of NiBabel including | ||
# | ||
# * Operating systems: Linux, Windows (x64 & x86), OSX | ||
# * Dependencies: minimum requirements, optional requirements | ||
# * Installation methods: setup.py, sdist, wheel, archive | ||
on: | ||
push: | ||
branches: | ||
- master | ||
- maint/* | ||
tags: | ||
- "*" | ||
pull_request: | ||
branches: | ||
- master | ||
- maint/* | ||
schedule: | ||
- cron: '0 0 * * 1' | ||
# Allow job to be triggered manually from GitHub interface | ||
workflow_dispatch: | ||
defaults: | ||
run: | ||
shell: bash | ||
# Force tox and pytest to use color | ||
env: | ||
FORCE_COLOR: true | ||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.ref }} | ||
cancel-in-progress: true | ||
permissions: | ||
contents: read | ||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
with: | ||
fetch-depth: 0 | ||
- uses: actions/setup-python@v5 | ||
with: | ||
python-version: 3 | ||
- run: pip install --upgrade build twine | ||
- name: Build sdist and wheel | ||
run: python -m build | ||
- run: twine check dist/* | ||
- name: Build git archive | ||
run: mkdir archive && git archive -v -o archive/nibabel-archive.tgz HEAD | ||
- name: Upload sdist and wheel artifacts | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: dist | ||
path: dist/ | ||
- name: Upload git archive artifact | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: archive | ||
path: archive/ | ||
test-package: | ||
runs-on: ubuntu-latest | ||
needs: [build] | ||
strategy: | ||
matrix: | ||
package: ['wheel', 'sdist', 'archive'] | ||
steps: | ||
- name: Download sdist and wheel artifacts | ||
if: matrix.package != 'archive' | ||
uses: actions/download-artifact@v4 | ||
with: | ||
name: dist | ||
path: dist/ | ||
- name: Download git archive artifact | ||
if: matrix.package == 'archive' | ||
uses: actions/download-artifact@v4 | ||
with: | ||
name: archive | ||
path: archive/ | ||
- uses: actions/setup-python@v5 | ||
with: | ||
python-version: 3 | ||
- name: Display Python version | ||
run: python -c "import sys; print(sys.version)" | ||
- name: Update pip | ||
run: pip install --upgrade pip | ||
- name: Install wheel | ||
if: matrix.package == 'wheel' | ||
run: pip install dist/nibabel-*.whl | ||
- name: Install sdist | ||
if: matrix.package == 'sdist' | ||
run: pip install dist/nibabel-*.tar.gz | ||
- name: Install archive | ||
if: matrix.package == 'archive' | ||
run: pip install archive/nibabel-archive.tgz | ||
- run: python -c 'import nibabel; print(nibabel.__version__)' | ||
- name: Install minimum test dependencies | ||
run: pip install nibabel[test] | ||
- name: Run tests | ||
run: pytest --doctest-modules --doctest-plus -v --pyargs nibabel -n auto | ||
test: | ||
# Check each OS, all supported Python, minimum versions and latest releases | ||
runs-on: ${{ matrix.os }} | ||
continue-on-error: ${{ matrix.dependencies == 'pre' }} | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
os: ['ubuntu-latest', 'windows-latest', 'macos-13', 'macos-latest'] | ||
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.13t"] | ||
architecture: ['x86', 'x64', 'arm64'] | ||
dependencies: ['full', 'pre'] | ||
include: | ||
# Basic dependencies only | ||
- os: ubuntu-latest | ||
python-version: "3.9" | ||
architecture: 'x64' | ||
dependencies: 'none' | ||
# Absolute minimum dependencies | ||
- os: ubuntu-latest | ||
python-version: "3.9" | ||
architecture: 'x64' | ||
dependencies: 'min' | ||
exclude: | ||
# Use ubuntu-latest to cover the whole range of Python. For Windows | ||
# and OSX, checking oldest and newest should be sufficient. | ||
- os: windows-latest | ||
python-version: "3.10" | ||
- os: windows-latest | ||
python-version: "3.11" | ||
- os: windows-latest | ||
python-version: "3.12" | ||
- os: macos-13 | ||
python-version: "3.10" | ||
- os: macos-13 | ||
python-version: "3.11" | ||
- os: macos-13 | ||
python-version: "3.12" | ||
- os: macos-latest | ||
python-version: "3.10" | ||
- os: macos-latest | ||
python-version: "3.11" | ||
- os: macos-latest | ||
python-version: "3.12" | ||
## Unavailable architectures | ||
# x86 is available for Windows | ||
- os: ubuntu-latest | ||
architecture: x86 | ||
- os: macos-latest | ||
architecture: x86 | ||
- os: macos-13 | ||
architecture: x86 | ||
# arm64 is available for macos-14+ | ||
- os: ubuntu-latest | ||
architecture: arm64 | ||
- os: windows-latest | ||
architecture: arm64 | ||
- os: macos-13 | ||
architecture: arm64 | ||
# x64 is not available for macos-14+ | ||
- os: macos-latest | ||
architecture: x64 | ||
## Reduced support | ||
# Drop pre tests for macos-13 | ||
- os: macos-13 | ||
dependencies: pre | ||
# Drop pre tests for SPEC-0-unsupported Python versions | ||
- python-version: '3.9' | ||
dependencies: pre | ||
- python-version: '3.10' | ||
dependencies: pre | ||
env: | ||
DEPENDS: ${{ matrix.dependencies }} | ||
ARCH: ${{ !contains(fromJSON('["none", "min"]'), matrix.dependencies) && matrix.architecture }} | ||
steps: | ||
- uses: actions/checkout@v4 | ||
with: | ||
submodules: recursive | ||
fetch-depth: 0 | ||
- name: Install the latest version of uv | ||
uses: astral-sh/setup-uv@v4 | ||
- name: Set up Python ${{ matrix.python-version }} | ||
if: "!endsWith(matrix.python-version, 't')" | ||
uses: actions/setup-python@v5 | ||
with: | ||
python-version: ${{ matrix.python-version }} | ||
architecture: ${{ matrix.architecture }} | ||
allow-prereleases: true | ||
- name: Set up Python ${{ matrix.python-version }} | ||
if: endsWith(matrix.python-version, 't') | ||
run: | | ||
uv python install ${IMPL}-${VERSION}-${OS%-*}-${ARCH}-${LIBC} | ||
env: | ||
IMPL: cpython | ||
VERSION: ${{ matrix.python-version }} | ||
# uv expects linux|macos|windows, we can drop the -* but need to rename ubuntu | ||
OS: ${{ matrix.os == 'ubuntu-latest' && 'linux' || matrix.os }} | ||
# uv expects x86, x86_64, aarch64 (among others) | ||
ARCH: ${{ fromJSON('{"x86": "x86", "x64": "x86_64", "arm64": "aarch64"}')[matrix.architecture] }} | ||
# windows and macos have no options, gnu is the only option for the archs | ||
LIBC: ${{ matrix.os == 'ubuntu-latest' && 'gnu' || 'none' }} | ||
- name: Display Python version | ||
run: python -c "import sys; print(sys.version)" | ||
- name: Install tox | ||
run: | | ||
uv tool install tox --with=git+https://github.com/effigies/tox-gh-actions@abiflags --with=tox-uv | ||
env: | ||
UV_PYTHON: ${{ matrix.python-version }} | ||
- name: Show tox config | ||
run: tox c | ||
- name: Run tox | ||
run: tox -vv --exit-and-dump-after 1200 | ||
- uses: codecov/codecov-action@v5 | ||
if: ${{ always() }} | ||
with: | ||
files: cov.xml | ||
token: ${{ secrets.CODECOV_TOKEN }} | ||
- name: Upload pytest test results | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: pytest-results-${{ matrix.os }}-${{ matrix.python-version }}-${{ matrix.dependencies }}-${{ matrix.architecture }} | ||
path: test-results.xml | ||
if: ${{ always() }} | ||
checks: | ||
runs-on: 'ubuntu-latest' | ||
continue-on-error: true | ||
strategy: | ||
matrix: | ||
check: ['style', 'doctest', 'typecheck', 'spellcheck'] | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Set up Python ${{ matrix.python-version }} | ||
uses: actions/setup-python@v5 | ||
with: | ||
python-version: 3 | ||
- name: Display Python version | ||
run: python -c "import sys; print(sys.version)" | ||
- name: Show tox config | ||
run: pipx run tox c | ||
- name: Show tox config (this call) | ||
run: pipx run tox c -e ${{ matrix.check }} | ||
- name: Run check | ||
run: pipx run tox -e ${{ matrix.check }} | ||
publish: | ||
runs-on: ubuntu-latest | ||
environment: "Package deployment" | ||
needs: [test, test-package] | ||
permissions: | ||
# Required for trusted publishing | ||
id-token: write | ||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') | ||
steps: | ||
- uses: actions/download-artifact@v4 | ||
with: | ||
name: dist | ||
path: dist/ | ||
- uses: pypa/gh-action-pypi-publish@release/v1 |