# 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", "3.14"]
        include:
          - os: ubuntu-22.04
            tesseract_ppa: "ppa"
            python: "3.10"

    env:
      OS: ${{ matrix.os }}
      PYTHON: ${{ matrix.python }}

    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: "0" # 0=all, needed for setuptools-scm to resolve version tags

      - name: Install uv
        uses: astral-sh/setup-uv@v7
        with:
          version: "0.9.x"

      - name: "Set up Python"
        uses: actions/setup-python@v6
        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

      - 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 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]
        python: ["3.10", "3.11", "3.12", "3.13", "3.14"]

    env:
      OS: ${{ matrix.os }}
      PYTHON: ${{ matrix.python }}

    steps:
      - uses: actions/checkout@v6
        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@v7
        with:
          version: "0.9.x"

      - name: "Set up Python"
        uses: actions/setup-python@v6
        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", "3.14"]

    env:
      OS: ${{ matrix.os }}
      PYTHON: ${{ matrix.python }}

    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: "0" # 0=all, needed for setuptools-scm to resolve version tags

      - name: Install uv
        uses: astral-sh/setup-uv@v7
        with:
          version: "0.9.x"

      - name: "Set up Python"
        uses: actions/setup-python@v6
        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@v6
        with:
          fetch-depth: "0" # 0=all, needed for setuptools-scm to resolve version tags

      - name: Install uv
        uses: astral-sh/setup-uv@v7
        with:
          version: "0.9.x"

      - name: Make wheels and sdist
        run: |
          uv build --sdist --wheel

      - uses: actions/upload-artifact@v6
        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@v7
        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@v7
        with:
          name: artifact
          path: dist

      - name: Sign the dists with Sigstore
        uses: sigstore/gh-action-sigstore-python@v3.2.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@v6
        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@v6
        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 .
