# SPDX-FileCopyrightText: 2022 James R. Barlow # SPDX-License-Identifier: MPL-2.0 name: Test and deploy on: push: branches: - main - ci - release/* - feature/* tags: - v* paths-ignore: - README* pull_request: jobs: test_linux: name: Test ${{ matrix.os }} with Python ${{ matrix.python }} runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-22.04, ubuntu-24.04] python: ["3.10", "3.11", "3.12", "3.13"] include: - os: ubuntu-22.04 tesseract_ppa: "ppa" python: "3.10" - os: ubuntu-24.04 python: "pypy3.10" env: OS: ${{ matrix.os }} PYTHON: ${{ matrix.python }} steps: - uses: actions/checkout@v4 with: fetch-depth: "0" # 0=all, needed for setuptools-scm to resolve version tags - name: Install uv uses: astral-sh/setup-uv@v5 with: version: "0.5.x" - name: "Set up Python" uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - name: Install Tesseract from PPA if: matrix.tesseract_ppa == 'ppa' run: | sudo add-apt-repository -y ppa:alex-p/tesseract-ocr5.3 - name: Install common packages run: | sudo apt-get update sudo apt-get install -y --no-install-recommends \ curl \ ghostscript \ jbig2dec \ img2pdf \ libexempi8 \ libffi-dev \ libsm6 libxext6 libxrender-dev \ pngquant \ poppler-utils \ tesseract-ocr \ tesseract-ocr-deu \ tesseract-ocr-eng \ tesseract-ocr-osd \ unpaper \ zlib1g - name: Install Ubuntu packages for PyPy if: startsWith(matrix.python, 'pypy') run: | sudo apt-get install -y --no-install-recommends \ libxml2-dev \ libxslt1-dev \ pypy3-dev - name: Install Python packages run: | uv sync --extra test --no-dev - name: Report versions run: | tesseract --version gs --version pngquant --version unpaper --version uv run --no-dev img2pdf --version - name: Test run: | uv run --no-dev pytest --cov-report xml --cov=ocrmypdf --cov=tests/ -n0 tests/ - name: Upload coverage to Codecov uses: codecov/codecov-action@v5 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} with: files: ./coverage.xml env_vars: OS,PYTHON test_macos: name: Test macOS runs-on: ${{ matrix.os }} strategy: matrix: os: [macos-latest, macos-13] # macos-latest is arm64, macos-13 is x86_64 python: ["3.10", "3.11", "3.12", "3.13"] env: OS: ${{ matrix.os }} PYTHON: ${{ matrix.python }} steps: - uses: actions/checkout@v4 with: fetch-depth: "0" # 0=all, needed for setuptools-scm to resolve version tags - name: Install Homebrew deps continue-on-error: true run: | brew update brew install \ exempi \ ghostscript \ jbig2enc \ openjpeg \ pngquant \ tesseract - name: Install uv uses: astral-sh/setup-uv@v5 with: version: "0.5.x" - name: "Set up Python" uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - name: Install Python packages run: | uv sync --extra test --no-dev - name: Report versions run: | tesseract --version gs --version pngquant --version uv run --no-dev img2pdf --version - name: Test run: | uv run --no-dev pytest --cov-report xml --cov=ocrmypdf --cov=tests/ -n0 tests/ - name: Upload coverage to Codecov uses: codecov/codecov-action@v5 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} with: files: ./coverage.xml env_vars: OS,PYTHON test_windows: name: Test Windows runs-on: ${{ matrix.os }} strategy: matrix: os: [windows-latest] python: ["3.10", "3.11", "3.12", "3.13"] env: OS: ${{ matrix.os }} PYTHON: ${{ matrix.python }} steps: - uses: actions/checkout@v4 with: fetch-depth: "0" # 0=all, needed for setuptools-scm to resolve version tags - name: Install uv uses: astral-sh/setup-uv@v5 with: version: "0.5.x" - name: "Set up Python" uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - name: Install system packages run: | choco install --yes --no-progress --pre tesseract choco install --yes --no-progress --ignore-checksums ghostscript --version 9.56.1 - name: Install Python packages run: | uv sync --extra test --no-dev - name: Test run: | uv run --no-dev pytest --cov-report xml --cov=ocrmypdf --cov=tests/ -n0 tests/ - name: Upload coverage to Codecov uses: codecov/codecov-action@v5 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} with: files: ./coverage.xml env_vars: OS,PYTHON wheel_sdist_linux: name: Build sdist and wheels runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: "0" # 0=all, needed for setuptools-scm to resolve version tags - name: Install uv uses: astral-sh/setup-uv@v5 with: version: "0.5.x" - name: Make wheels and sdist run: | uv build --sdist --wheel - uses: actions/upload-artifact@v4 with: name: artifact path: | ./dist/*.whl ./dist/*.tar.gz upload_pypi: name: Deploy artifacts to PyPI needs: [wheel_sdist_linux, test_linux, test_macos, test_windows] runs-on: ubuntu-latest environment: release permissions: id-token: write # mandatory for PyPI publishing if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v') steps: - uses: actions/download-artifact@v4 with: name: artifact path: dist - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 create_release: name: Create GitHub release needs: [upload_pypi] runs-on: ubuntu-latest if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v') permissions: # Required to create a release contents: write id-token: write steps: - uses: actions/download-artifact@v4 with: name: artifact path: dist - name: Sign the dists with Sigstore uses: sigstore/gh-action-sigstore-python@v3.0.0 with: inputs: | ./dist/*.tar.gz ./dist/*.whl - name: Create GitHub Release env: GITHUB_TOKEN: ${{ github.token }} run: >- gh release create "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" --notes "" - name: Upload artifact signatures to GitHub Release env: GITHUB_TOKEN: ${{ github.token }} # Upload to GitHub Release using the `gh` CLI. # `dist/` contains the built packages, and the # sigstore-produced signatures and certificates. run: >- gh release upload "$GITHUB_REF_NAME" dist/** --repo "$GITHUB_REPOSITORY" docker_ubuntu: name: Build Ubuntu-based Docker image needs: [wheel_sdist_linux, test_linux, test_macos, test_windows] runs-on: ubuntu-latest if: github.event_name != 'pull_request' steps: - name: Set image tag to release or branch run: echo "DOCKER_IMAGE_TAG=${GITHUB_REF##*/}" >> $GITHUB_ENV - name: If main, set to latest run: echo 'DOCKER_IMAGE_TAG=latest' >> $GITHUB_ENV if: env.DOCKER_IMAGE_TAG == 'main' - name: Set Docker Hub repository to username run: echo "DOCKER_REPOSITORY=jbarlow83" >> $GITHUB_ENV - name: Set image name run: echo "DOCKER_IMAGE_NAME=ocrmypdf" >> $GITHUB_ENV - uses: actions/checkout@v4 with: fetch-depth: "0" # 0=all, needed for setuptools-scm to resolve version tags - name: Login to Docker Hub uses: docker/login-action@v3 with: username: jbarlow83 password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx id: buildx uses: docker/setup-buildx-action@v3 - name: Print image tag run: echo "Building image ${DOCKER_REPOSITORY}/${DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_TAG}" - name: Build run: | docker buildx build \ --push \ --platform linux/arm64/v8,linux/amd64 \ --tag "${DOCKER_REPOSITORY}/${DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_TAG}" \ --tag "${DOCKER_REPOSITORY}/${DOCKER_IMAGE_NAME}-ubuntu:${DOCKER_IMAGE_TAG}" \ --file .docker/Dockerfile . docker_alpine: name: Build Alpine-based Docker images needs: [wheel_sdist_linux, test_linux, test_macos, test_windows] runs-on: ubuntu-latest if: github.event_name != 'pull_request' steps: - name: Set image tag to release or branch run: echo "DOCKER_IMAGE_TAG=${GITHUB_REF##*/}" >> $GITHUB_ENV - name: If main, set to latest run: echo 'DOCKER_IMAGE_TAG=latest' >> $GITHUB_ENV if: env.DOCKER_IMAGE_TAG == 'main' - name: Set Docker Hub repository to username run: echo "DOCKER_REPOSITORY=jbarlow83" >> $GITHUB_ENV - name: Set image name run: echo "DOCKER_IMAGE_NAME=ocrmypdf-alpine" >> $GITHUB_ENV - uses: actions/checkout@v4 with: fetch-depth: "0" # 0=all, needed for setuptools-scm to resolve version tags - name: Login to Docker Hub uses: docker/login-action@v3 with: username: jbarlow83 password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Set up Docker Buildx id: buildx uses: docker/setup-buildx-action@v3 - name: Print image tag run: echo "Building image ${DOCKER_REPOSITORY}/${DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_TAG}" - name: Build run: | docker buildx build \ --push \ --platform linux/amd64,linux/arm64 \ --tag "${DOCKER_REPOSITORY}/${DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_TAG}" \ --file .docker/Dockerfile.alpine .