name: Wheels on: schedule: # ┌───────────── minute (0 - 59) # │ ┌───────────── hour (0 - 23) # │ │ ┌───────────── day of the month (1 - 31) # │ │ │ ┌───────────── month (1 - 12 or JAN-DEC) # │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT) # │ │ │ │ │ - cron: "42 1 * * 0,3" push: paths: - ".ci/requirements-cibw.txt" - ".github/workflows/wheel*" - "setup.py" - "wheels/*" - "winbuild/build_prepare.py" - "winbuild/fribidi.cmake" tags: - "*" pull_request: paths: - ".ci/requirements-cibw.txt" - ".github/workflows/wheel*" - "setup.py" - "wheels/*" - "winbuild/build_prepare.py" - "winbuild/fribidi.cmake" workflow_dispatch: permissions: contents: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: FORCE_COLOR: 1 jobs: build-1-QEMU-emulated-wheels: if: github.event_name != 'schedule' name: aarch64 ${{ matrix.python-version }} ${{ matrix.spec }} runs-on: ubuntu-latest strategy: fail-fast: false matrix: python-version: - pp310 - cp3{9,10,11} - cp3{12,13} spec: - manylinux2014 - manylinux_2_28 - musllinux exclude: - { python-version: pp310, spec: musllinux } steps: - uses: actions/checkout@v4 with: persist-credentials: false submodules: true - uses: actions/setup-python@v5 with: python-version: "3.x" # https://github.com/docker/setup-qemu-action - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Install cibuildwheel run: | python3 -m pip install -r .ci/requirements-cibw.txt - name: Build wheels run: | python3 -m cibuildwheel --output-dir wheelhouse env: # Build only the currently selected Linux architecture (so we can # parallelise for speed). CIBW_ARCHS: "aarch64" # Likewise, select only one Python version per job to speed this up. CIBW_BUILD: "${{ matrix.python-version }}-${{ matrix.spec == 'musllinux' && 'musllinux' || 'manylinux' }}*" CIBW_ENABLE: cpython-prerelease # Extra options for manylinux. CIBW_MANYLINUX_AARCH64_IMAGE: ${{ matrix.spec }} CIBW_MANYLINUX_PYPY_AARCH64_IMAGE: ${{ matrix.spec }} - uses: actions/upload-artifact@v4 with: name: dist-qemu-${{ matrix.python-version }}-${{ matrix.spec }} path: ./wheelhouse/*.whl build-2-native-wheels: if: github.event_name != 'schedule' || github.repository_owner == 'python-pillow' name: ${{ matrix.name }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: include: - name: "macOS 10.10 x86_64" os: macos-13 cibw_arch: x86_64 build: "cp3{9,10,11}*" macosx_deployment_target: "10.10" - name: "macOS 10.13 x86_64" os: macos-13 cibw_arch: x86_64 build: "cp3{12,13}*" macosx_deployment_target: "10.13" - name: "macOS 10.15 x86_64" os: macos-13 cibw_arch: x86_64 build: "pp310*" macosx_deployment_target: "10.15" - name: "macOS arm64" os: macos-latest cibw_arch: arm64 macosx_deployment_target: "11.0" - name: "manylinux2014 and musllinux x86_64" os: ubuntu-latest cibw_arch: x86_64 - name: "manylinux_2_28 x86_64" os: ubuntu-latest cibw_arch: x86_64 build: "*manylinux*" manylinux: "manylinux_2_28" steps: - uses: actions/checkout@v4 with: persist-credentials: false submodules: true - uses: actions/setup-python@v5 with: python-version: "3.x" - name: Install cibuildwheel run: | python3 -m pip install -r .ci/requirements-cibw.txt - name: Build wheels run: | python3 -m cibuildwheel --output-dir wheelhouse env: CIBW_ARCHS: ${{ matrix.cibw_arch }} CIBW_BUILD: ${{ matrix.build }} CIBW_ENABLE: cpython-prerelease cpython-freethreading CIBW_MANYLINUX_PYPY_X86_64_IMAGE: ${{ matrix.manylinux }} CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.manylinux }} CIBW_SKIP: pp39-* MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }} - uses: actions/upload-artifact@v4 with: name: dist-${{ matrix.os }}${{ matrix.macosx_deployment_target && format('-{0}', matrix.macosx_deployment_target) }}-${{ matrix.cibw_arch }}${{ matrix.manylinux && format('-{0}', matrix.manylinux) }} path: ./wheelhouse/*.whl windows: if: github.event_name != 'schedule' || github.repository_owner == 'python-pillow' name: Windows ${{ matrix.cibw_arch }} runs-on: windows-latest strategy: fail-fast: false matrix: include: - cibw_arch: x86 - cibw_arch: AMD64 - cibw_arch: ARM64 steps: - uses: actions/checkout@v4 with: persist-credentials: false - name: Checkout extra test images uses: actions/checkout@v4 with: persist-credentials: false repository: python-pillow/test-images path: Tests\test-images - uses: actions/setup-python@v5 with: python-version: "3.x" - name: Install cibuildwheel run: | python.exe -m pip install -r .ci/requirements-cibw.txt - name: Prepare for build run: | choco install nasm --no-progress echo "C:\Program Files\NASM" >> $env:GITHUB_PATH # Install extra test images xcopy /S /Y Tests\test-images\* Tests\images & python.exe winbuild\build_prepare.py -v --no-imagequant --architecture=${{ matrix.cibw_arch }} shell: pwsh - name: Build wheels run: | setlocal EnableDelayedExpansion for %%f in (winbuild\build\license\*) do ( set x=%%~nf rem Skip FriBiDi license, it is not included in the wheel. set fribidi=!x:~0,7! if NOT !fribidi!==fribidi ( rem Skip imagequant license, it is not included in the wheel. set libimagequant=!x:~0,13! if NOT !libimagequant!==libimagequant ( echo. >> LICENSE echo ===== %%~nf ===== >> LICENSE echo. >> LICENSE type %%f >> LICENSE ) ) ) call winbuild\\build\\build_env.cmd %pythonLocation%\python.exe -m cibuildwheel . --output-dir wheelhouse env: CIBW_ARCHS: ${{ matrix.cibw_arch }} CIBW_BEFORE_ALL: "{package}\\winbuild\\build\\build_dep_all.cmd" CIBW_CACHE_PATH: "C:\\cibw" CIBW_ENABLE: cpython-prerelease cpython-freethreading CIBW_SKIP: pp39-* CIBW_TEST_SKIP: "*-win_arm64" CIBW_TEST_COMMAND: 'docker run --rm -v {project}:C:\pillow -v C:\cibw:C:\cibw -v %CD%\..\venv-test:%CD%\..\venv-test -e CI -e GITHUB_ACTIONS mcr.microsoft.com/windows/servercore:ltsc2022 powershell C:\pillow\.github\workflows\wheels-test.ps1 %CD%\..\venv-test' shell: cmd - name: Upload wheels uses: actions/upload-artifact@v4 with: name: dist-windows-${{ matrix.cibw_arch }} path: ./wheelhouse/*.whl - name: Upload fribidi.dll uses: actions/upload-artifact@v4 with: name: fribidi-windows-${{ matrix.cibw_arch }} path: winbuild\build\bin\fribidi* sdist: if: github.event_name != 'schedule' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: persist-credentials: false - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.x" cache: pip cache-dependency-path: "Makefile" - run: make sdist - uses: actions/upload-artifact@v4 with: name: dist-sdist path: dist/*.tar.gz scientific-python-nightly-wheels-publish: if: github.repository_owner == 'python-pillow' && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') needs: [build-2-native-wheels, windows] runs-on: ubuntu-latest name: Upload wheels to scientific-python-nightly-wheels steps: - uses: actions/download-artifact@v4 with: pattern: dist-* path: dist merge-multiple: true - name: Upload wheels to scientific-python-nightly-wheels uses: scientific-python/upload-nightly-action@82396a2ed4269ba06c6b2988bb4fd568ef3c3d6b # 0.6.1 with: artifacts_path: dist anaconda_nightly_upload_token: ${{ secrets.ANACONDA_ORG_UPLOAD_TOKEN }} pypi-publish: if: github.repository_owner == 'python-pillow' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags') needs: [build-1-QEMU-emulated-wheels, build-2-native-wheels, windows, sdist] runs-on: ubuntu-latest name: Upload release to PyPI environment: name: release-pypi url: https://pypi.org/p/Pillow permissions: id-token: write steps: - uses: actions/download-artifact@v4 with: pattern: dist-* path: dist merge-multiple: true - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: attestations: true