name: Build and test, upload to PyPI on release

on:
  push:
    branches:
      - master
    tags:
      - '*'
  pull_request:
    branches:
      - master

env:
  CIBW_TEST_REQUIRES: ddt
  CIBW_TEST_COMMAND: "cd {project} && python -m unittest -v"
  CIBW_MANYLINUX_X86_64_IMAGE: "manylinux2014"
  CIBW_MANYLINUX_I686_IMAGE: "manylinux2014"
  CIBW_MANYLINUX_PYPY_X86_64_IMAGE: "manylinux2014"
  CIBW_MANYLINUX_PYPY_I686_IMAGE: "manylinux2014"
  CIBW_SKIP: "cp36-*"
  MACOSX_DEPLOYMENT_TARGET: "10.9"  

jobs:
  build_wheel_linux:
    name: Build wheels on Linux (${{ matrix.wheel_arch }})
    runs-on: ubuntu-20.04
    strategy:
      matrix:
        wheel_arch: [x86_64, i686]

    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true
          fetch-depth: 0

      - uses: actions/setup-python@v2
        name: Install Python
        with:
          python-version: '3.8'

      - name: Build wheels (manylinux)
        uses: pypa/cibuildwheel@v2.10.2
        env:
          CIBW_BEFORE_BUILD: "yum install -y flex bison && pip install cmake wheel && python setup.py build_c_core"
          CIBW_ARCHS_LINUX: ${{ matrix.wheel_arch }}          
          CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}"

      - name: Build wheels (musllinux)
        uses: pypa/cibuildwheel@v2.10.2
        env:
          CIBW_BEFORE_BUILD: "apk add flex bison zlib-dev && pip install cmake wheel && python setup.py build_c_core"
          CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}"
          CIBW_TEST_EXTRAS: "test-musl"

      - uses: actions/upload-artifact@v2
        with:
          path: ./wheelhouse/*.whl

  build_wheel_linux_aarch64:
    name: Build wheels on Linux (aarch64)
    runs-on: ubuntu-20.04
    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true
          fetch-depth: 0

      - name: Set up QEMU
        id: qemu
        uses: docker/setup-qemu-action@v2

      - name: Build wheels (manylinux)
        uses: pypa/cibuildwheel@v2.10.2
        env:
          CIBW_BEFORE_BUILD: "yum install -y flex bison zlib-devel && pip install cmake wheel && python setup.py build_c_core"
          CIBW_ARCHS_LINUX: aarch64
          CIBW_BUILD: "*-manylinux_aarch64"

      - uses: actions/upload-artifact@v2
        with:
          path: ./wheelhouse/*.whl

  build_wheel_macos:
    name: Build wheels on macOS (${{ matrix.wheel_arch }})
    runs-on: macos-latest
    env:
      LLVM_VERSION: "14.0.5"
    strategy:
      matrix:
        include:
          - cmake_arch: x86_64
            wheel_arch: x86_64
          - cmake_arch: arm64
            cmake_extra_args: -DF2C_EXTERNAL_ARITH_HEADER=../../../etc/arith_apple_m1.h -DIEEE754_DOUBLE_ENDIANNESS_MATCHES=ON
            wheel_arch: arm64

    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true
          fetch-depth: 0

      - name: Cache installed C core
        id: cache-c-core
        uses: actions/cache@v2
        with:
          path: vendor/install
          key: C-core-cache-${{ runner.os }}-${{ matrix.cmake_arch }}-llvm${{ env.LLVM_VERSION }}-${{ hashFiles('.git/modules/**/HEAD') }}

      - name: Cache C core dependencies
        id: cache-c-deps
        uses: actions/cache@v2
        with:
          path: ~/local
          key: deps-cache-v2-${{ runner.os }}-${{ matrix.cmake_arch }}-llvm${{ env.LLVM_VERSION }}

      - uses: actions/setup-python@v2
        name: Install Python
        with:
          python-version: '3.8'

      - name: Install OS dependencies
        if: steps.cache-c-core.outputs.cache-hit != 'true' || steps.cache-c-deps.outputs.cache-hit != 'true' # Only needed when building the C core
        run:
          brew install ninja autoconf automake libtool cmake

      - name: Build wheels
        uses: pypa/cibuildwheel@v2.10.2
        env:
          CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}"
          CIBW_BEFORE_BUILD: "python setup.py build_c_core"
          CIBW_ENVIRONMENT: "LDFLAGS=-L$HOME/local/lib"
          IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_OSX_ARCHITECTURES=${{ matrix.cmake_arch }} ${{ matrix.cmake_extra_args }} -DCMAKE_PREFIX_PATH=$HOME/local

      - uses: actions/upload-artifact@v2
        with:
          path: ./wheelhouse/*.whl

  build_wheel_win:
    name: Build wheels on Windows (${{ matrix.cmake_arch }})
    runs-on: windows-2019
    strategy:
      matrix:
        include:
          - cmake_arch: Win32
            wheel_arch: win32
          - cmake_arch: x64
            wheel_arch: win_amd64

    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true
          fetch-depth: 0

      - uses: actions/setup-python@v2
        name: Install Python
        with:
          python-version: '3.8'

      - name: Cache installed C core
        id: cache-c-core
        uses: actions/cache@v2
        with:
          path: vendor/install
          key: C-core-cache-${{ runner.os }}-${{ matrix.cmake_arch }}-${{ hashFiles('.git/modules/**/HEAD') }}

      - name: Install build dependencies
        if: steps.cache-c-core.outputs.cache-hit != 'true' # Only needed when building the C core
        run: choco install winflexbison3 cmake ninja

      - name: Build wheels
        uses: pypa/cibuildwheel@v2.10.2
        env:
          CIBW_BEFORE_BUILD: "python setup.py build_c_core"
          CIBW_BUILD: "*-${{ matrix.wheel_arch }}"
          IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_BUILD_TYPE=RelWithDebInfo -A ${{ matrix.cmake_arch }}
          IGRAPH_STATIC_EXTENSION: True
          CIBW_TEST_COMMAND: "cd /d {project} && python -m unittest -v"

      - uses: actions/upload-artifact@v2
        with:
          path: ./wheelhouse/*.whl

  build_sdist:
    name: Build sdist
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true
          fetch-depth: 0

      - name: Cache installed C core
        id: cache-c-core
        uses: actions/cache@v2
        with:
          path: |
            vendor/install
          key: C-core-cache-${{ runner.os }}-${{ hashFiles('.git/modules/**/HEAD') }}

      - name: Install OS dependencies
        if: steps.cache-c-core.outputs.cache-hit != 'true' # Only needed when building the C core
        run:
          sudo apt install ninja-build cmake flex bison

      - uses: actions/setup-python@v2
        name: Install Python
        with:
          python-version: '3.8'

      - name: Build sdist
        run: |
          pip install setuptools_scm
          python setup.py build_c_core
          python setup.py sdist
          python setup.py install

      - name: Test
        run: |
          pip install ddt
          python -m unittest -v

      - uses: actions/upload-artifact@v2
        with:
          path: dist/*.tar.gz

  upload_pypi:
    needs: [build_wheel_linux, build_wheel_macos, build_wheel_win, build_sdist]
    runs-on: ubuntu-latest
    # upload to PyPI on every push from the master branch
    if: github.event_name == 'push' &&
        startsWith(github.ref, 'refs/tags')
    steps:
      - uses: actions/download-artifact@v2
        with:
          name: artifact
          path: dist

      # Upload tagged versions to production PyPI
      - name: Publish distribution 📦 to PyPI
        uses: pypa/gh-action-pypi-publish@master
        with:
          password: ${{ secrets.PYPI_API_TOKEN }}