name: Python cibuildwheel

on:
  push:
    branches: [ 'master', 'main', 'develop', 'actions_pypi' ]
    tags: [ 'v*' ]
  pull_request:
    branches: [ 'master', 'main', 'develop' ]

jobs:
  set-version:
    runs-on: ubuntu-latest
    outputs:
      testpypiversion: ${{ steps.set.outputs.testpypiversion }}
    steps:
      - name: Set version for testpypi
        id: set
        run: echo "testpypiversion=$(date +%Y%m%d%H%M%S)" >> $GITHUB_OUTPUT
  
  python_source:
    needs: set-version
    name: Build source package
    runs-on: ubuntu-latest
    steps:
    
    - uses: actions/checkout@v3
      with:
        submodules: recursive

    - name: Set up Python
      uses: actions/setup-python@v5
      with:
        python-version: 3.13.x
        
    - name: Install dependencies
      run: pip install setuptools wheel Cython requests jinja2 pyyaml packaging

    - name: Figure out the TestPyPi/PyPi Version
      shell: bash
      run: |
        if [[ "$GITHUB_REF" == *"refs/tags"* ]]; then
          python dev/extract_version.py --pypi --replace-setup-py
        else
          python dev/extract_version.py --replace-setup-py --version "${{ needs.set-version.outputs.testpypiversion }}"
        fi;
        
    - name: Build package, sdist
      working-directory: ./wrappers/Python/pypi
      run: python prepare_pypi.py --dist-dir=${GITHUB_WORKSPACE}/Python

    - name: Store artifacts
      uses: actions/upload-artifact@v4
      with:
        name: Python-sdist
        path: |
          ./Python/*.tar.gz

  python_ubuntu:
    needs: set-version
    strategy:
      # Ensure that a wheel builder finishes even if another fails
      fail-fast: false
      matrix:
        os: [ubuntu-latest]
        python-version: [39, 310, 311, 312, 313]
        arch: [i686, x86_64, ppc64le, s390x]
        exclude:
          - os: ubuntu-latest
            arch: i686 # reduce the build time until people ask for the binaries
          - os: ubuntu-latest
            arch: ppc64le # reduce the build time until people ask for the binaries
          - os: ubuntu-latest
            arch: s390x # reduce the build time until people ask for the binaries
    uses: ./.github/workflows/python_cibuildwheel.yml
    with:
      os: ${{ matrix.os }}
      python-version: ${{ matrix.python-version }}
      arch: ${{ matrix.arch }}
      TESTPYPI_VERSION: ${{ needs.set-version.outputs.testpypiversion }}
      
  python_ubuntu_arm:
    needs: set-version
    strategy:
      # Ensure that a wheel builder finishes even if another fails
      fail-fast: false
      matrix:
        os: [ubuntu-24.04-arm]
        python-version: [39, 310, 311, 312, 313]
        arch: [aarch64]
    uses: ./.github/workflows/python_cibuildwheel.yml
    with:
      os: ${{ matrix.os }}
      python-version: ${{ matrix.python-version }}
      arch: ${{ matrix.arch }}
      TESTPYPI_VERSION: ${{ needs.set-version.outputs.testpypiversion }}
      
  python_windows:
    needs: set-version
    strategy:
      # Ensure that a wheel builder finishes even if another fails
      fail-fast: false
      matrix:
        os: [windows-latest]
        python-version: [39, 310, 311, 312, 313]
        arch: [AMD64, x86, ARM64]
        #exclude:
        #  - os: windows
        #    arch: ARM64 # creates problems with msgpack-c
    uses: ./.github/workflows/python_cibuildwheel.yml
    with:
      os: ${{ matrix.os }}
      python-version: ${{ matrix.python-version }}
      arch: ${{ matrix.arch }}
      TESTPYPI_VERSION: ${{ needs.set-version.outputs.testpypiversion }}
  
  python_macos:
    needs: set-version
    strategy:
      # Ensure that a wheel builder finishes even if another fails
      fail-fast: false
      matrix:
        os: [macos-latest]
        python-version: [39, 310, 311, 312, 313]
        arch: [x86_64, arm64, universal2]
        exclude:
          - os: macos-latest
            arch: universal2 # is redundant
    uses: ./.github/workflows/python_cibuildwheel.yml
    with:
      os: ${{ matrix.os }}
      python-version: ${{ matrix.python-version }}
      arch: ${{ matrix.arch }}
      TESTPYPI_VERSION: ${{ needs.set-version.outputs.testpypiversion }}
  
  merge_wheels:
   runs-on: ubuntu-latest
   needs: [python_source, python_ubuntu, python_ubuntu_arm, python_windows, python_macos]
   steps:
     - name: Merge Artifacts
       uses: actions/upload-artifact/merge@v4
       with:
         name: Python
         pattern: Python-*

  upload_python_bindings_to_pypi:
    needs: merge_wheels
    name: Upload to PyPi
    runs-on: ubuntu-latest
    steps:

    - name: Set up Python
      uses: actions/setup-python@v5
      with:
        python-version: 3.13.x

    - name: Install Python dependencies
      run: |
        python -m pip install --upgrade pip
        pip install setuptools wheel twine requests packaging

        if [[ "$GITHUB_REF" == *"refs/tags"* ]]; then
          TWINE_REPOSITORY=pypi
          TWINE_PASSWORD=${{ secrets.PYPI_TOKEN }}
        else
          TWINE_REPOSITORY=testpypi
          TWINE_PASSWORD=${{ secrets.TESTPYPI_TOKEN }}
        fi;
        echo "Using TWINE_REPOSITORY=$TWINE_REPOSITORY"
        echo "TWINE_REPOSITORY=$TWINE_REPOSITORY" >> $GITHUB_ENV
        echo "TWINE_PASSWORD=$TWINE_PASSWORD" >> $GITHUB_ENV

    - name: Download ALL wheels
      uses: actions/download-artifact@v4.1.7
      with:
        name: Python
        path: Python

    - name: Display structure of downloaded files
      run: |
        set -x
        ls -R
        du -sh

    - name: Publish wheels to (Test)PyPI
      if: ${{ github.event_name != 'pull_request' }}
      env:
        TWINE_USERNAME: __token__
      run: python -m twine upload --verbose --skip-existing Python/*.whl Python/*.tar.gz
