Merge pull request #300 from bgilbert/release #352
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: Python | |
on: | |
push: | |
branches: [main] | |
tags: ["*"] | |
pull_request: | |
branches: [main] | |
permissions: | |
contents: read | |
env: | |
PYTHONUNBUFFERED: 1 | |
jobs: | |
pre-commit: | |
name: Rerun pre-commit checks | |
runs-on: ubuntu-latest | |
outputs: | |
dist-base: ${{ steps.paths.outputs.dist }} | |
docs-base: ${{ steps.paths.outputs.docs }} | |
steps: | |
- name: Check out repo | |
uses: actions/checkout@v4 | |
- name: Set up Python | |
uses: actions/setup-python@v5 | |
with: | |
python-version: '3.13' | |
- name: Run pre-commit hooks | |
uses: pre-commit/[email protected] | |
- name: Define artifact paths | |
id: paths | |
run: | | |
suffix="$GITHUB_RUN_NUMBER-$(echo $GITHUB_SHA | cut -c-10)" | |
echo "dist=openslide-python-dist-$suffix" >> $GITHUB_OUTPUT | |
echo "docs=openslide-python-docs-$suffix" >> $GITHUB_OUTPUT | |
tests: | |
name: Tests | |
needs: pre-commit | |
runs-on: ${{ matrix.os }} | |
strategy: | |
matrix: | |
os: [ubuntu-latest, ubuntu-24.04-aarch64, macos-latest] | |
python-version: [3.8, 3.9, "3.10", "3.11", "3.12", "3.13"] | |
openslide: [system, wheel] | |
include: | |
- os: ubuntu-latest | |
python-version: "3.13" | |
openslide: system | |
sdist: sdist | |
# Python 3.8 is too old to support universal binaries, and | |
# setup-python's Python 3.9 and 3.10 won't build them. Use the | |
# last upstream patch releases that ship with installers. | |
# https://github.com/actions/setup-python/issues/439#issuecomment-1247646682 | |
- os: macos-latest | |
python-version: "3.9" | |
upstream-python: 3.9.13 | |
- os: macos-latest | |
python-version: "3.10" | |
upstream-python: 3.10.11 | |
steps: | |
- name: Check out repo | |
uses: actions/checkout@v4 | |
- name: Set up Python ${{ matrix.python-version }} | |
if: matrix.upstream-python == null | |
uses: actions/setup-python@v5 | |
with: | |
python-version: ${{ matrix.python-version }} | |
- name: Set up Python ${{ matrix.python-version }} (macOS fallback) | |
if: matrix.upstream-python != null | |
run: | | |
pkgdir="${{ runner.temp }}/python" | |
mkdir -p "$pkgdir/bin" | |
pkg="$pkgdir/python.pkg" | |
curl -Lfo "$pkg" \ | |
"https://www.python.org/ftp/python/${{ matrix.upstream-python }}/python-${{ matrix.upstream-python }}-macos11.pkg" | |
sudo installer -pkg "$pkg" -target / | |
for bin in python pip; do | |
ln -s /usr/local/bin/${bin}3 $pkgdir/bin/${bin} | |
done | |
export PATH="$pkgdir/bin:$PATH" | |
echo "PATH=$PATH" >> $GITHUB_ENV | |
python -V | |
pip -V | |
- name: Install Python tools | |
run: | | |
python -m pip install --upgrade pip | |
pip install auditwheel build jinja2 pytest | |
- name: Install OpenSlide (system) | |
if: matrix.openslide == 'system' | |
run: | | |
case "${{ matrix.os }}" in | |
ubuntu-latest) | |
echo OS_ARCH_TAG=linux-x86_64 >> $GITHUB_ENV | |
sudo apt-get install libopenslide0 | |
;; | |
ubuntu-24.04-aarch64) | |
echo OS_ARCH_TAG=linux-aarch64 >> $GITHUB_ENV | |
sudo apt-get install libopenslide0 | |
;; | |
macos-latest) | |
echo OS_ARCH_TAG=macos-arm64-x86_64 >> $GITHUB_ENV | |
echo DYLD_LIBRARY_PATH=/opt/homebrew/lib >> $GITHUB_ENV | |
brew install openslide | |
;; | |
esac | |
- name: Install OpenSlide (wheel) | |
if: matrix.openslide == 'wheel' | |
run: pip install openslide-bin | |
- name: Build dist | |
run: | | |
if [ -z "${{ matrix.sdist }}" ]; then | |
wheel_only=-w | |
fi | |
python -m build $wheel_only | |
case "${{ matrix.os }}" in | |
ubuntu-*) | |
mkdir old | |
mv dist/*.whl old/ | |
auditwheel repair --only-plat -w dist old/*whl | |
;; | |
macos-*) | |
if [ "${{ matrix.python-version }}" != 3.8 -a ! -e dist/*universal2* ]; then | |
echo "Wheel is not universal:" | |
ls dist | |
exit 1 | |
fi | |
esac | |
if [ -z "$wheel_only" ]; then | |
mkdir -p "artifacts/src/${{ needs.pre-commit.outputs.dist-base }}" | |
mv dist/*.tar.gz "artifacts/src/${{ needs.pre-commit.outputs.dist-base }}" | |
fi | |
mkdir -p "artifacts/whl/${{ needs.pre-commit.outputs.dist-base }}" | |
mv dist/* "artifacts/whl/${{ needs.pre-commit.outputs.dist-base }}" | |
# from system builds, save version-specific wheels and oldest abi3 wheel | |
python -c 'import sys | |
if sys.version_info < (3, 12) and "${{ matrix.openslide }}" == "system": | |
print("archive_wheel=1")' >> $GITHUB_ENV | |
- name: Install | |
run: pip install artifacts/whl/${{ needs.pre-commit.outputs.dist-base }}/*.whl | |
- name: Run tests | |
run: pytest -v | |
- name: Tile slide | |
run: python examples/deepzoom/deepzoom_tile.py --viewer -o tiled tests/fixtures/small.svs | |
- name: Archive sdist | |
if: matrix.sdist | |
uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ needs.pre-commit.outputs.dist-base }}-source | |
path: artifacts/src | |
compression-level: 0 | |
- name: Archive wheel | |
if: env.archive_wheel | |
uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ needs.pre-commit.outputs.dist-base }}-${{ env.OS_ARCH_TAG }}-${{ matrix.python-version }} | |
path: artifacts/whl | |
compression-level: 0 | |
windows: | |
name: Windows | |
needs: pre-commit | |
runs-on: windows-latest | |
defaults: | |
run: | |
shell: bash | |
strategy: | |
matrix: | |
python-version: [3.8, 3.9, "3.10", "3.11", "3.12", "3.13"] | |
openslide: [zip, wheel] | |
steps: | |
- name: Check out repo | |
uses: actions/checkout@v4 | |
- name: Set up Python ${{ matrix.python-version }} | |
uses: actions/setup-python@v5 | |
with: | |
python-version: ${{ matrix.python-version }} | |
- name: Install Python tools | |
run: | | |
python -m pip install --upgrade pip | |
pip install build flask pytest | |
- name: Install OpenSlide (zip) | |
if: matrix.openslide == 'zip' | |
env: | |
GH_TOKEN: ${{ github.token }} | |
run: | | |
mkdir -p c:\\openslide | |
cd c:\\openslide | |
release=$(gh release list -R openslide/openslide-bin -L 1 \ | |
--json tagName --exclude-drafts --exclude-pre-releases | \ | |
jq -r .[0].tagName | \ | |
tr -d v) | |
zipname="openslide-bin-${release}-windows-x64" | |
gh release download -R openslide/openslide-bin "v${release}" \ | |
--pattern "${zipname}.zip" | |
7z x ${zipname}.zip | |
echo "OPENSLIDE_PATH=c:\\openslide\\${zipname}\\bin" >> $GITHUB_ENV | |
- name: Install OpenSlide (wheel) | |
if: matrix.openslide == 'wheel' | |
run: pip install openslide-bin | |
- name: Build wheel | |
run: | | |
python -m build -w | |
mkdir -p "artifacts/whl/${{ needs.pre-commit.outputs.dist-base }}" | |
mv dist/*.whl "artifacts/whl/${{ needs.pre-commit.outputs.dist-base }}" | |
# from zip builds, save version-specific wheels and oldest abi3 wheel | |
python -c 'import sys | |
if sys.version_info < (3, 12) and "${{ matrix.openslide }}" == "zip": | |
print("archive_wheel=1")' >> $GITHUB_ENV | |
- name: Install | |
run: pip install artifacts/whl/${{ needs.pre-commit.outputs.dist-base }}/*.whl | |
- name: Run tests | |
# Reads OPENSLIDE_PATH | |
run: pytest -v | |
- name: Test library loading in examples | |
# Reads OPENSLIDE_PATH | |
run: | | |
python examples/deepzoom/deepzoom_multiserver.py -h >/dev/null | |
python examples/deepzoom/deepzoom_server.py -h >/dev/null | |
python examples/deepzoom/deepzoom_tile.py -h >/dev/null | |
- name: Tile slide | |
# Reads OPENSLIDE_PATH | |
run: python examples/deepzoom/deepzoom_tile.py --viewer -o tiled tests/fixtures/small.svs | |
- name: Archive wheel | |
if: env.archive_wheel | |
uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ needs.pre-commit.outputs.dist-base }}-windows-x64-${{ matrix.python-version }} | |
path: artifacts/whl | |
compression-level: 0 | |
docs: | |
name: Docs | |
needs: pre-commit | |
runs-on: ubuntu-latest | |
steps: | |
- name: Check out repo | |
uses: actions/checkout@v4 | |
- name: Set up Python | |
uses: actions/setup-python@v5 | |
with: | |
python-version: '3.13' | |
- name: Install Python tools | |
run: | | |
python -m pip install --upgrade pip | |
pip install sphinx | |
- name: Build | |
run: sphinx-build -d doctrees doc artifact/${{ needs.pre-commit.outputs.docs-base }} | |
- name: Archive | |
uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ needs.pre-commit.outputs.docs-base }} | |
path: artifact | |
release: | |
name: Release | |
if: github.ref_type == 'tag' | |
environment: | |
name: pypi | |
url: https://pypi.org/p/openslide-python | |
needs: [pre-commit, tests, windows] | |
runs-on: ubuntu-latest | |
concurrency: release-${{ github.ref }} | |
permissions: | |
contents: write | |
id-token: write | |
steps: | |
- name: Download artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
pattern: "${{ needs.pre-commit.outputs.dist-base }}-*" | |
merge-multiple: true | |
- name: Release to PyPI | |
uses: pypa/gh-action-pypi-publish@release/v1 | |
with: | |
packages-dir: ${{ needs.pre-commit.outputs.dist-base }} | |
repository-url: ${{ vars.PYPI_URL }} | |
- name: Release to GitHub | |
env: | |
GITHUB_TOKEN: ${{ github.token }} | |
run: | | |
version=$(echo "${{ github.ref_name }}" | sed "s/^v//") | |
# recompress tarball with xz | |
gunzip -k "${{ needs.pre-commit.outputs.dist-base }}/openslide-python-${version}.tar.gz" | |
tar xf "${{ needs.pre-commit.outputs.dist-base }}/openslide-python-${version}.tar" | |
xz -9 "${{ needs.pre-commit.outputs.dist-base }}/openslide-python-${version}.tar" | |
# extract changelog | |
awk -e '/^## / && ok {exit}' \ | |
-e '/^## / {ok=1; next}' \ | |
-e 'ok {print}' \ | |
"openslide-python-$version/CHANGELOG.md" > changes | |
gh release create --latest --verify-tag \ | |
--repo "${{ github.repository }}" \ | |
--title "OpenSlide Python $version" \ | |
--notes-file changes \ | |
"${{ github.ref_name }}" \ | |
"${{ needs.pre-commit.outputs.dist-base }}/"* |