# SPDX-License-Identifier: Apache-2.0
# Copyright Contributors to the OpenImageIO Project.
#
# This workflow will run on under two independent conditions:
#   1) On the official AcademySoftwareFoundation repo, according to a nightly schedule.
#   2) On forks, when submitting a PR that modifies Python-related files.

name: Wheel

permissions:
  contents: read
  id-token: write

on:
  push:
    # Workflow run on tags for v3 only, or pre-tagged pushes of release, or
    # dev-3.* branches. Also if the branch name itself contains the substrings
    # 'wheel' or 'python'.
    tags:
      - v3.*
    branches:
      - release
      - dev-3.*
      - "*wheel*"
      - "*python*"
  pull_request:
    # Workflow run on pull_request only when related files change, or when the
    # branch name itself contains the substrings 'wheel' or 'python'.
    paths:
      - .github/workflows/wheel.yml
      - pyproject.toml
      - src/python/*.py
      - src/python/*.h
      - src/python/*.cpp
      - src/cmake/*.cmake
  schedule:
    # Nightly build
    - cron:  "0 8 * * *"
  workflow_dispatch:
    # This allows manual triggering of the workflow from the web

jobs:
  # Linux jobs run in Docker containers (manylinux), so the latest OS version
  # is OK. macOS and Windows jobs need to be locked to specific virtual
  # environment versions to mitigate issues from OS updates, and will require
  # maintenance as OS versions are retired.

  # ---------------------------------------------------------------------------
  # Source Distribution
  # ---------------------------------------------------------------------------

  sdist:
    name: Build SDist
    runs-on: ubuntu-latest
    if: |
      github.event_name != 'schedule' ||
      github.repository == 'AcademySoftwareFoundation/OpenImageIO'

    steps:

    - name: Checkout repo
      uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

    - name: Build SDist
      run: pipx run build --sdist

    - name: Check metadata
      run: pipx run twine check dist/*

    - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
      with:
        name: cibw-sdist
        path: dist/*.tar.gz

  # ---------------------------------------------------------------------------
  # Linux Wheels
  # ---------------------------------------------------------------------------

  linux:
    name: Build wheels on Linux
    runs-on: ubuntu-latest
    if: |
      github.event_name != 'schedule' ||
      github.repository == 'AcademySoftwareFoundation/OpenImageIO'
    strategy:
      matrix:
        include:
          # -------------------------------------------------------------------
          # CPython 64 bits manylinux_2_28
          # -------------------------------------------------------------------
          - build: CPython 3.8 64 bits manylinux_2_28
            manylinux: manylinux_2_28
            python: cp38-manylinux_x86_64
            arch: x86_64
          - build: CPython 3.9 64 bits manylinux_2_28
            manylinux: manylinux_2_28
            python: cp39-manylinux_x86_64
            arch: x86_64
          - build: CPython 3.10 64 bits manylinux_2_28
            manylinux: manylinux_2_28
            python: cp310-manylinux_x86_64
            arch: x86_64
          - build: CPython 3.11 64 bits manylinux_2_28
            manylinux: manylinux_2_28
            python: cp311-manylinux_x86_64
            arch: x86_64
          - build: CPython 3.12 64 bits manylinux_2_28
            manylinux: manylinux_2_28
            python: cp312-manylinux_x86_64
            arch: x86_64
          - build: CPython 3.13 64 bits manylinux_2_28
            manylinux: manylinux_2_28
            python: cp313-manylinux_x86_64
            arch: x86_64
          # -------------------------------------------------------------------
          # CPython 64 bits manylinux2014
          # -------------------------------------------------------------------
          - build: CPython 3.8 64 bits manylinux2014
            manylinux: manylinux2014
            python: cp38-manylinux_x86_64
            arch: x86_64
          - build: CPython 3.9 64 bits manylinux2014
            manylinux: manylinux2014
            python: cp39-manylinux_x86_64
            arch: x86_64
          - build: CPython 3.10 64 bits manylinux2014
            manylinux: manylinux2014
            python: cp310-manylinux_x86_64
            arch: x86_64
          - build: CPython 3.11 64 bits manylinux2014
            manylinux: manylinux2014
            python: cp311-manylinux_x86_64
            arch: x86_64
          - build: CPython 3.12 64 bits manylinux2014
            manylinux: manylinux2014
            python: cp312-manylinux_x86_64
            arch: x86_64
          - build: CPython 3.13 64 bits manylinux2014
            manylinux: manylinux2014
            python: cp313-manylinux_x86_64
            arch: x86_64

    steps:
      - name: Checkout repo
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

      - name: Install Python
        uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
        with:
          python-version: '3.9'

      - name: Build wheels
        # Note: the version of cibuildwheel should be kept in sync with src/python/stubs/CMakeLists.txt
        uses: pypa/cibuildwheel@d4a2945fcc8d13f20a1b99d461b8e844d5fc6e23 # v2.21.1
        env:
          # pass GITHUB_ACTIONS through to the build container so that custom
          # processes can tell they are running in CI.
          CIBW_ENVIRONMENT_PASS_LINUX: GITHUB_ACTIONS
          CIBW_BUILD: ${{ matrix.python }}
          CIBW_ARCHS: ${{ matrix.arch }}
          CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.manylinux }}

      - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
        with:
          name: cibw-wheels-${{ matrix.python }}-${{ matrix.manylinux }}
          path: |
            ./wheelhouse/*.whl
            ./wheelhouse/OpenImageIO/__init__.pyi
        # if stub validation fails we want to upload the stubs for users to review
        if: success() || failure()

  # ---------------------------------------------------------------------------
  # Linux ARM Wheels
  # ---------------------------------------------------------------------------

  linux-arm:
      name: Build wheels on Linux ARM
      runs-on: ubuntu-24.04-arm
      if: |
        github.event_name != 'schedule' ||
        github.repository == 'AcademySoftwareFoundation/OpenImageIO'
      strategy:
        matrix:
          include:
            # -------------------------------------------------------------------
            # CPython ARM 64 bits manylinux2014
            # -------------------------------------------------------------------
            - build: CPython 3.8 ARM 64 bits manylinux2014
              manylinux: manylinux2014
              python: cp38-manylinux_aarch64
              arch: aarch64
            - build: CPython 3.9 ARM 64 bits manylinux2014
              manylinux: manylinux2014
              python: cp39-manylinux_aarch64
              arch: aarch64
            - build: CPython 3.10 ARM 64 bits manylinux2014
              manylinux: manylinux2014
              python: cp310-manylinux_aarch64
              arch: aarch64
            - build: CPython 3.11 ARM 64 bits manylinux2014
              manylinux: manylinux2014
              python: cp311-manylinux_aarch64
              arch: aarch64
            - build: CPython 3.12 ARM 64 bits manylinux2014
              manylinux: manylinux2014
              python: cp312-manylinux_aarch64
              arch: aarch64
            - build: CPython 3.13 ARM 64 bits manylinux2014
              manylinux: manylinux2014
              python: cp313-manylinux_aarch64
              arch: aarch64

      steps:
        - name: Checkout repo
          uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

        - name: Install Python
          uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
          with:
            python-version: '3.9'
        
        - name: Build wheels
          uses: pypa/cibuildwheel@d4a2945fcc8d13f20a1b99d461b8e844d5fc6e23 # v2.21.1
          env:
            CIBW_BUILD: ${{ matrix.python }}
            CIBW_ARCHS: ${{ matrix.arch }}
            CIBW_MANYLINUX_AARCH64_IMAGE: ${{ matrix.manylinux }}

        - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
          with:
            name: cibw-wheels-${{ matrix.python }}-${{ matrix.manylinux }}
            path: |
              ./wheelhouse/*.whl
              ./wheelhouse/OpenImageIO/__init__.pyi
          # if stub validation fails we want to upload the stubs for users to review
          if: success() || failure()

  # ---------------------------------------------------------------------------
  # macOS Wheels
  # ---------------------------------------------------------------------------

  macos:
    name: Build wheels on macOS
    runs-on: macos-13
    if: |
      github.event_name != 'schedule' ||
      github.repository == 'AcademySoftwareFoundation/OpenImageIO'
    strategy:
      matrix:
        include:
          # -------------------------------------------------------------------
          # CPython 64 bits
          # -------------------------------------------------------------------
          - build: CPython 3.8 64 bits
            python: cp38-macosx_x86_64
            arch: x86_64
          - build: CPython 3.9 64 bits
            python: cp39-macosx_x86_64
            arch: x86_64
          - build: CPython 3.10 64 bits
            python: cp310-macosx_x86_64
            arch: x86_64
          - build: CPython 3.11 64 bits
            python: cp311-macosx_x86_64
            arch: x86_64
          - build: CPython 3.12 64 bits
            python: cp312-macosx_x86_64
            arch: x86_64
          - build: CPython 3.13 64 bits
            python: cp313-macosx_x86_64
            arch: x86_64

    steps:
      - name: Checkout repo
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

      - name: Install Python
        uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
        with:
          python-version: '3.9'

      - name: Build wheels
        uses: pypa/cibuildwheel@d4a2945fcc8d13f20a1b99d461b8e844d5fc6e23 # v2.21.1
        env:
          CIBW_BUILD: ${{ matrix.python }}
          CIBW_ARCHS: ${{ matrix.arch }}
          CMAKE_GENERATOR: "Unix Makefiles"
          # TODO: Re-enable HEIF when we provide a build recipe that does 
          # not include GPL-licensed dynamic libraries.
          USE_Libheif: 'OFF'

      - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
        with:
          name: cibw-wheels-${{ matrix.python }}
          path: ./wheelhouse/*.whl

  # ---------------------------------------------------------------------------
  # macOS ARM Wheels
  # ---------------------------------------------------------------------------

  macos-arm:
    name: Build wheels on macOS ARM
    runs-on: macos-14
    if: |
      github.event_name != 'schedule' ||
      github.repository == 'AcademySoftwareFoundation/OpenImageIO'
    strategy:
      matrix:
        include:
          # -------------------------------------------------------------------
          # CPython ARM 64 bits
          # -------------------------------------------------------------------
          - build: CPython 3.8 ARM 64 bits
            python: cp38-macosx_arm64
            arch: arm64
          - build: CPython 3.9 ARM 64 bits
            python: cp39-macosx_arm64
            arch: arm64
          - build: CPython 3.10 ARM 64 bits
            python: cp310-macosx_arm64
            arch: arm64
          - build: CPython 3.11 ARM 64 bits
            python: cp311-macosx_arm64
            arch: arm64
          - build: CPython 3.12 ARM 64 bits
            python: cp312-macosx_arm64
            arch: arm64
          - build: CPython 3.13 ARM 64 bits
            python: cp313-macosx_arm64
            arch: arm64

    steps:
      - name: Checkout repo
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        
      - name: Install Python
        uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
        # https://cibuildwheel.pypa.io/en/stable/faq/#macos-building-cpython-38-wheels-on-arm64
        with:
          python-version: '3.8'
        

      - name: Build wheels
        uses: pypa/cibuildwheel@d4a2945fcc8d13f20a1b99d461b8e844d5fc6e23 # v2.21.1
        env:
          CIBW_BUILD: ${{ matrix.python }}
          CIBW_ARCHS: ${{ matrix.arch }}
          CMAKE_GENERATOR: "Unix Makefiles"

      - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
        with:
          name: cibw-wheels-${{ matrix.python }}
          path: ./wheelhouse/*.whl

  # ---------------------------------------------------------------------------
  # Windows Wheels
  # ---------------------------------------------------------------------------

  windows:
    name: Build wheels on Windows
    runs-on: windows-2022
    if: |
      github.event_name != 'schedule' ||
      github.repository == 'AcademySoftwareFoundation/OpenImageIO'
    strategy:
      matrix:
        include:
          # -------------------------------------------------------------------
          # CPython 64 bits
          # -------------------------------------------------------------------
          - build: CPython 3.8 64 bits
            python: cp38-win_amd64
            arch: AMD64
          - build: CPython 3.9 64 bits
            python: cp39-win_amd64
            arch: AMD64
          - build: CPython 3.10 64 bits
            python: cp310-win_amd64
            arch: AMD64
          - build: CPython 3.11 64 bits
            python: cp311-win_amd64
            arch: AMD64
          - build: CPython 3.12 64 bits
            python: cp312-win_amd64
            arch: AMD64
          - build: CPython 3.13 64 bits
            python: cp313-win_amd64
            arch: AMD64

    steps:
      - name: Checkout repo
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

      - name: Install Python
        uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
        with:
          python-version: '3.9'

      - name: Build wheels
        uses: pypa/cibuildwheel@d4a2945fcc8d13f20a1b99d461b8e844d5fc6e23 # v2.21.1
        env:
          CIBW_BUILD: ${{ matrix.python }}
          CIBW_ARCHS: ${{ matrix.arch }}
          CMAKE_POLICY_VERSION_MINIMUM: 3.5

      - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
        with:
          name: cibw-wheels-${{ matrix.python }}
          path: ./wheelhouse/*.whl


  upload_pypi:
    needs: [sdist, linux, linux-arm, macos, macos-arm, windows]
    runs-on: ubuntu-latest
    permissions:
      id-token: write
    if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v3.0.') && github.repository == 'AcademySoftwareFoundation/OpenImageIO'
    steps:
      - uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0

      - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
        with:
          pattern: cibw-*
          path: dist
          merge-multiple: true

      - uses: pypa/gh-action-pypi-publish@897895f1e160c830e369f9779632ebc134688e1b # release/v1
