---
name: Build, run, and test py-lmdb

'on':
  push:
    branches: [master, release]
    tags:
      - 'py-lmdb_*'
  pull_request:
    branches: [master]

jobs:
  build:

    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-20.04, macos-latest, windows-latest]
        python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9, '3.10', '3.11', pypy-2.7, pypy-3.9]
        impl: [cpython, cffi]
        purity: [pure, with-pylmdb-mods]

        exclude:
          - python-version: pypy-2.7
            impl: cpython
          - python-version: pypy-3.9
            impl: cpython
          # CFFI has trouble building on Windows for 3.5 "self.find_available_vc_vers()[-1]" fails
          - python-version: 3.5
            os: windows-latest
          # Microsoft removed VC 9.0 installer so Python 2.7 modules can no longer be built on Windows
          - python-version: 2.7
            os: windows-latest
          # Doesn't seem to exist on github MacOS
          - python-version: pypy-3.9
            os: macos-latest

    steps:
      - uses: actions/checkout@v2
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v2
        with:
          python-version: ${{ matrix.python-version }}
      - name: Set env vars Windows
        if: runner.os == 'Windows'
        run: >-
          if ( '${{ matrix.impl }}' -eq 'cpython' ) {
            echo "LMDB_FORCE_CPYTHON=1" |
              Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
          } else {
            echo "LMDB_FORCE_CFFI=1" |
              Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
          }
          if ( '${{ matrix.purity }}' -eq 'pure' ) {
            echo "LMDB_PURE=1" |
              Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
          } elseif ( '${{ matrix.purity }}' -eq 'system' ){
            echo "LMDB_FORCE_SYSTEM=1" |
              Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
          }
      - name: Set env vars *nix
        if: runner.os != 'Windows'
        run: |
          if [[ ${{ matrix.impl }} == cpython ]] ; then
            echo "LMDB_FORCE_CPYTHON=1" >> $GITHUB_ENV;
          else
            echo "LMDB_FORCE_CFFI=1" >> $GITHUB_ENV;
          fi
          if [[ ${{ matrix.purity }} == pure ]] ; then
            echo "LMDB_PURE=1" >> $GITHUB_ENV;
          elif [[ ${{ matrix.purity }} == system ]] ; then
            echo "LMDB_FORCE_SYSTEM=1" >> $GITHUB_ENV;
            sudo apt-get install liblmdb-dev;
          fi

      - name: Install dependencies
        run: |
          echo "Linux: Envs are cpython=$LMDB_FORCE_CPYTHON
            cffi=$LMDB_FORCE_CFFI pure=$LMDB_PURE system=$LMDB_FORCE_SYSTEM"
          echo "Windows: Envs are cpython=$Env:LMDB_FORCE_CPYTHON
            cffi=$Env:LMDB_FORCE_CFFI pure=$Env:LMDB_PURE system=$Env:LMDB_FORCE_SYSTEM"
          python -m pip install wheel
          # Install this separately since sometimes Github Actions can't find it
          python -m pip install cffi
          python -m pip install flake8 pytest patch-ng
          python setup.py develop sdist bdist_wheel
          ls dist
      # name: Lint with flake8
      # run: |
      #   # stop the build if there are Python syntax errors or undefined names
      #   flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
      #   # exit-zero treats all errors as warnings.
      #   flake8 . --count --exit-zero --max-complexity=10 --max-line-length=120 --statistics
      #
      - name: Test with pytest
        # Limit the test cycle a little
        if: matrix.python-version != '3.6' && matrix.python-version != '3.8'
        run: |
          echo "Envs are cpython=$LMDB_FORCE_CPYTHON cffi=$LMDB_FORCE_CFFI
            pure=$LMDB_PURE system=$LMDB_FORCE_SYSTEM"
          pytest

      - name: Save wheel
        uses: actions/upload-artifact@v2
        with:
          name: "${{ matrix.os }}-${{ matrix.python-version }}-${{ matrix.impl }}-${{ matrix.purity }}.whl"
          path: dist/lmdb-*.whl

      - name: Get version
        if: >-
          matrix.python-version == '3.10' && runner.os == 'Linux' &&
          matrix.purity == 'with-pylmdb-mods' && matrix.impl == 'cpython'
        run: |
          python -c 'import lmdb; print(lmdb.__version__, end="")' > vers.txt

      - name: Save version
        if: >-
          matrix.python-version == '3.10' && runner.os == 'Linux' &&
          matrix.purity == 'with-pylmdb-mods' && matrix.impl == 'cpython'
        uses: actions/upload-artifact@v2
        with:
          path: vers.txt
          name: vers.txt

      - name: Save source
        # We only need a single target to upload the source
        # (all targets have the same source)
        if: >-
          matrix.python-version == '3.10' && runner.os == 'Linux' &&
          matrix.purity == 'with-pylmdb-mods' && matrix.impl == 'cpython'

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

      - name: Build manylinux wheel
        if: >-
          matrix.python-version == '3.10' && runner.os == 'Linux' &&
          matrix.purity == 'with-pylmdb-mods' && matrix.impl == 'cpython'
        uses: RalfG/python-wheels-manylinux-build@v0.7.1
        with:
          python-versions: >-
              cp36-cp36m cp37-cp37m cp38-cp38 cp39-cp39 cp310-cp310 cp311-cp311
          build-requirements: 'patch-ng'

      - name: What do we have
        run: ls dist

      - name: Save manylinux wheel
        # We only need a single target to upload the source
        # (all targets have the same source)
        if: >-
          matrix.python-version == '3.10' && runner.os == 'Linux' &&
          matrix.purity == 'with-pylmdb-mods' && matrix.impl == 'cpython'
        uses: actions/upload-artifact@v2
        with:
          path: dist/lmdb*manylinux*.whl
          name: manylinux

  test_build_aarch64:
    name: "${{ matrix.PYTHON }} aarch64 ${{ matrix.impl }} ${{ matrix.purity }}"
    runs-on: ubuntu-20.04
    strategy:
       matrix:
        impl: [cpython, cffi]
        purity: [pure, with-pylmdb-mods]
        PYTHON: ["cp36-cp36m", "cp37-cp37m" , "cp38-cp38" , "cp39-cp39", "cp310-cp310", "cp311-cp311"]
    steps:
      - uses: actions/checkout@v2
      - run: |
          docker run --rm --privileged hypriot/qemu-register
      - uses: docker://quay.io/pypa/manylinux2014_aarch64
        with:
          args: |
              bash -c "set -xe;
              mkdir -p /github/home/.cache/pip;
              chown -R $(whoami) /github/home/.cache;
              python --version;
              /opt/python/${{ matrix.PYTHON }}/bin/python -m venv .venv;
              yum install -y libffi-devel;
              .venv/bin/pip install -U pip wheel cffi six;
              if \[ ${{ matrix.impl }} == cpython \] ; then
                echo LMDB_FORCE_CPYTHON=1
              else
                echo LMDB_FORCE_CFFI=1
              fi
              if \[ ${{ matrix.purity }} == pure \] ; then
                echo LMDB_PURE=1
              elif \[ ${{ matrix.purity }} == system \] ; then
                echo LMDB_FORCE_SYSTEM=1
              fi
              echo \"Linux: Envs are cpython=$LMDB_FORCE_CPYTHON
                cffi=$LMDB_FORCE_CFFI pure=$LMDB_PURE system=$LMDB_FORCE_SYSTEM\";
              echo \"Windows: Envs are cpython=$Env:LMDB_FORCE_CPYTHON
                cffi=$Env:LMDB_FORCE_CFFI pure=$Env:LMDB_PURE system=$Env:LMDB_FORCE_SYSTEM\";
              .venv/bin/pip install flake8 pytest patch-ng;
              /opt/python/${{ matrix.PYTHON }}/bin/python setup.py develop bdist_wheel;
              ls dist;
              /opt/python/${{ matrix.PYTHON }}/bin/python -m pip install pytest;
              if \[ ${{ matrix.PYTHON }} != cp36-cp36 \] && \[ ${{ matrix.PYTHON }} != cp38-cp38 \] ; then
                echo \"Envs are cpython=$LMDB_FORCE_CPYTHON cffi=$LMDB_FORCE_CFFI pure=$LMDB_PURE system=$LMDB_FORCE_SYSTEM\";
                /opt/python/${{ matrix.PYTHON }}/bin/python -m pytest;
              fi;
              if \[ ${{ matrix.PYTHON }} == cp310-cp310 \] && \[ ${{ runner.os }} == 'Linux' \] && \[ ${{ matrix.purity }} == 'with-pylmdb-mods' \] && \[ ${{ matrix.impl }} == 'cpython' \] ; then
                /opt/python/${{ matrix.PYTHON }}/bin/python -c \"import lmdb; print(lmdb.__version__, end='')\" > vers.txt;
              fi;"
      - uses: actions/upload-artifact@v2
        with:
          name: "${{ runner.os }}-${{ matrix.PYTHON }}-${{ matrix.impl }}-${{ matrix.purity }}.whl"
          path: dist/lmdb-*.whl

      - uses: actions/upload-artifact@v2
        if: >-
            matrix.PYTHON == 'cp310-cp310' && runner.os == 'Linux' && 
            matrix.purity == 'with-pylmdb-mods' && matrix.impl == 'cpython'
        with:
          path: vers.txt
          name: vers.txt
      - uses: actions/upload-artifact@v2
        if: >-
            matrix.PYTHON == 'cp310-cp310' && runner.os == 'Linux' && 
            matrix.purity == 'with-pylmdb-mods' && matrix.impl == 'cpython'
        with:
          path: dist/lmdb*.tar.gz
          name: source
      - uses: RalfG/python-wheels-manylinux-build@v0.7.1-manylinux2014_aarch64
        if: >-
            matrix.PYTHON == 'cp310-cp310' && runner.os == 'Linux' && 
            matrix.purity == 'with-pylmdb-mods' && matrix.impl == 'cpython'
        with:
          python-versions: >-
              cp36-cp36m cp37-cp37m cp38-cp38 cp39-cp39 cp310-cp310 cp311-cp311
          build-requirements: 'patch-ng'
      - uses: actions/upload-artifact@v2
        if: >-
            matrix.PYTHON == 'cp310-cp310' && runner.os == 'Linux' && 
            matrix.purity == 'with-pylmdb-mods' && matrix.impl == 'cpython'
        with:
          path: dist/lmdb*manylinux*.whl
          name: manylinux

  publish:
    needs: build
    # N.B. the host running twine to upload is distinct from the target image
    runs-on: ubuntu-20.04
    strategy:
      # We publish a subset of the targets we test
      matrix:
        os: [macos-latest, windows-latest]
        python-version: ['2.7', '3.5', '3.6', '3.7', '3.8', '3.9', '3.10', '3.11', pypy-2.7, pypy-3.9]
        impl: [cpython, cffi]
        purity: [with-pylmdb-mods]

        exclude:
          - python-version: 'pypy-2.7'
            impl: cpython
          - python-version: 'pypy-3.9'
            impl: cpython
          - python-version: '2.7'
            impl: cffi
          - python-version: '3.5'
            impl: cffi
          - python-version: '3.6'
            impl: cffi
          - python-version: '3.7'
            impl: cffi
          - python-version: '3.8'
            impl: cffi
          - python-version: '3.9'
            impl: cffi
          - python-version: '3.10'
            impl: cffi
          - python-version: '3.11'
            impl: cffi
          # CFFI has trouble building on Windows for 3.5 "self.find_available_vc_vers()[-1]" fails
          - python-version: 3.5
            os: windows-latest
          # Microsoft removed VC 9.0 installer so Python 2.7 modules can no longer be built on Windows
          - python-version: '2.7'
            os: windows-latest
          # Doesn't seem to exist on github MacOS
          - python-version: pypy-3.9
            os: macos-latest

        include:
          # Ubuntu artifacts apply to all python versions
          - os: ubuntu-20.04
            python-version: '3.10'
            impl: cpython
            purity: with-pylmdb-mods

    steps:
      - name: Download source
        if: matrix.os == 'ubuntu-20.04'
        uses: actions/download-artifact@v2
        with:
          name: source
          path: dist

      - name: Download manylinux artifact
        if: matrix.os == 'ubuntu-20.04'
        uses: actions/download-artifact@v2
        with:
          name: manylinux
          path: dist

      - name: Download non-Linux wheel
        if: matrix.os != 'ubuntu-20.04'
        uses: actions/download-artifact@v2
        with:
          name: "${{ matrix.os }}-${{ matrix.python-version }}-${{ matrix.impl }}-${{ matrix.purity }}.whl"
          path: dist

      - name: Inventory
        run: >-
          find .

      - name: Publish distribution 📦 to Test PyPI
        uses: pypa/gh-action-pypi-publish@master
        with:
          password: ${{ secrets.TEST_PYPI_API_TOKEN }}
          repository_url: https://test.pypi.org/legacy/
          skip_existing: true

      - name: Publish distribution 📦 to PyPI
        if: startsWith(github.ref, 'refs/tags')
        uses: pypa/gh-action-pypi-publish@master
        with:
          password: ${{ secrets.PYPI_API_TOKEN }}
