name: Test Windows on: push: branches: - "**" paths-ignore: - ".github/workflows/docs.yml" - ".github/workflows/wheels*" - ".gitmodules" - "docs/**" - "wheels/**" pull_request: paths-ignore: - ".github/workflows/docs.yml" - ".github/workflows/wheels*" - ".gitmodules" - "docs/**" - "wheels/**" workflow_dispatch: permissions: contents: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: COVERAGE_CORE: sysmon jobs: build: runs-on: windows-latest strategy: fail-fast: false matrix: python-version: ["pypy3.10", "3.9", "3.10", "3.11", "3.12", "3.13"] timeout-minutes: 30 name: Python ${{ matrix.python-version }} steps: - name: Checkout Pillow uses: actions/checkout@v4 - name: Checkout cached dependencies uses: actions/checkout@v4 with: repository: python-pillow/pillow-depends path: winbuild\depends - name: Checkout extra test images uses: actions/checkout@v4 with: repository: python-pillow/test-images path: Tests\test-images # sets env: pythonLocation - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} allow-prereleases: true cache: pip cache-dependency-path: ".github/workflows/test-windows.yml" - name: Print build system information run: python3 .github/workflows/system-info.py - name: Install Python dependencies run: > python3 -m pip install coverage>=7.4.2 defusedxml olefile pyroma pytest pytest-cov pytest-timeout - name: Install dependencies id: install run: | choco install nasm --no-progress echo "C:\Program Files\NASM" >> $env:GITHUB_PATH choco install ghostscript --version=10.3.1 --no-progress echo "C:\Program Files\gs\gs10.03.1\bin" >> $env:GITHUB_PATH # Install extra test images xcopy /S /Y Tests\test-images\* Tests\images # make cache key depend on VS version & "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" ` | find """catalog_buildVersion""" ` | ForEach-Object { $a = $_.split(" ")[1]; echo "vs=$a" >> $env:GITHUB_OUTPUT } shell: pwsh - name: Cache build id: build-cache uses: actions/cache@v4 with: path: winbuild\build key: ${{ hashFiles('winbuild\build_prepare.py') }}-${{ hashFiles('.github\workflows\test-windows.yml') }}-${{ env.pythonLocation }}-${{ steps.install.outputs.vs }} - name: Prepare build if: steps.build-cache.outputs.cache-hit != 'true' run: | & python.exe winbuild\build_prepare.py -v shell: pwsh - name: Build dependencies / libjpeg-turbo if: steps.build-cache.outputs.cache-hit != 'true' run: "& winbuild\\build\\build_dep_libjpeg.cmd" - name: Build dependencies / zlib if: steps.build-cache.outputs.cache-hit != 'true' run: "& winbuild\\build\\build_dep_zlib.cmd" - name: Build dependencies / xz if: steps.build-cache.outputs.cache-hit != 'true' run: "& winbuild\\build\\build_dep_xz.cmd" - name: Build dependencies / WebP if: steps.build-cache.outputs.cache-hit != 'true' run: "& winbuild\\build\\build_dep_libwebp.cmd" - name: Build dependencies / LibTiff if: steps.build-cache.outputs.cache-hit != 'true' run: "& winbuild\\build\\build_dep_libtiff.cmd" # for FreeType CBDT/SBIX font support - name: Build dependencies / libpng if: steps.build-cache.outputs.cache-hit != 'true' run: "& winbuild\\build\\build_dep_libpng.cmd" # for FreeType WOFF2 font support - name: Build dependencies / brotli if: steps.build-cache.outputs.cache-hit != 'true' run: "& winbuild\\build\\build_dep_brotli.cmd" - name: Build dependencies / FreeType if: steps.build-cache.outputs.cache-hit != 'true' run: "& winbuild\\build\\build_dep_freetype.cmd" - name: Build dependencies / LCMS2 if: steps.build-cache.outputs.cache-hit != 'true' run: "& winbuild\\build\\build_dep_lcms2.cmd" - name: Build dependencies / OpenJPEG if: steps.build-cache.outputs.cache-hit != 'true' run: "& winbuild\\build\\build_dep_openjpeg.cmd" # GPL licensed - name: Build dependencies / libimagequant if: steps.build-cache.outputs.cache-hit != 'true' run: "& winbuild\\build\\build_dep_libimagequant.cmd" # Raqm dependencies - name: Build dependencies / HarfBuzz if: steps.build-cache.outputs.cache-hit != 'true' run: "& winbuild\\build\\build_dep_harfbuzz.cmd" # Raqm dependencies - name: Build dependencies / FriBidi if: steps.build-cache.outputs.cache-hit != 'true' run: "& winbuild\\build\\build_dep_fribidi.cmd" # trim ~150MB for each job - name: Optimize build cache if: steps.build-cache.outputs.cache-hit != 'true' run: rmdir /S /Q winbuild\build\src shell: cmd - name: Build Pillow run: | $FLAGS="-C raqm=vendor -C fribidi=vendor" cmd /c "winbuild\build\build_env.cmd && $env:pythonLocation\python.exe -m pip install -v $FLAGS ." & $env:pythonLocation\python.exe selftest.py --installed shell: pwsh # skip PyPy for speed - name: Enable heap verification if: "!contains(matrix.python-version, 'pypy')" run: | & reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\python.exe" /v "GlobalFlag" /t REG_SZ /d "0x02000000" /f - name: Test Pillow run: | path %GITHUB_WORKSPACE%\\winbuild\\build\\bin;%PATH% python.exe -m pytest -vx -W always --cov PIL --cov Tests --cov-report term --cov-report xml Tests shell: cmd - name: Prepare to upload errors if: failure() run: | mkdir -p Tests/errors shell: bash - name: Upload errors uses: actions/upload-artifact@v4 if: failure() with: name: errors path: Tests/errors - name: After success run: | .ci/after_success.sh shell: pwsh - name: Upload coverage uses: codecov/codecov-action@v4 with: file: ./coverage.xml flags: GHA_Windows name: ${{ runner.os }} Python ${{ matrix.python-version }} token: ${{ secrets.CODECOV_ORG_TOKEN }} success: permissions: contents: none needs: build runs-on: ubuntu-latest name: Windows Test Successful steps: - name: Success run: echo Windows Test Successful