# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the action will run. Triggers the workflow on push or pull request events
on:
  push:
    branches:
      - '**'
  pull_request:
    branches:
      - '**'
  workflow_dispatch:
    inputs:
      debug_enabled:
        description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'     
        required: false
        default: false

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # Build for posix systems
  posix:

    strategy:
      fail-fast: false
      matrix:
        platform: [ ubuntu-latest, macos-latest ]
        mpilib: [null, mpich, openmpi]
        plugins: [OFF, ON]
        exclude:
          - platform: macos-latest
            mpilib: openmpi

    # The type of runner that the job will run on
    runs-on: ${{ matrix.platform }}

    env:
      OMPI_MCA_btl_base_warn_component_unused: "0"
      CODECOV_TOKEN: "99465b5f-26b4-4487-8355-fbcac5249a05"

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2

      - name: Create source file with all required environment variables
        run: |
          # Create a source file that will contain environment variables used in additional steps
          # Environment variabls are not normally preserved between steps, so the source file is necessary
          touch env.source

          # Set MDI_TESTS, which defines which tests will be performed for this job
          export MDI_TESTS_TEMP=""
          [ "${{ matrix.mpilib }}" == "" ] && export MDI_TESTS_TEMP="not mpi"
          [ "${{ matrix.mpilib }}" != "" ] && [ "${{ matrix.platform }}" == "macos-latest" ] && export MDI_TESTS_TEMP="not mpi and not py_plug and not py_cxx_plug"

          # Ensure that plugins tests are not run if plugins are not enabled
          [ "${{ matrix.plugins }}" == "OFF" ] && [ "${MDI_TESTS_TEMP}" == "" ] && export MDI_TESTS_TEMP="not plug"
          [ "${{ matrix.plugins }}" == "OFF" ] && [ "${MDI_TESTS_TEMP}" != "" ] && export MDI_TESTS_TEMP="${MDI_TESTS_TEMP} and not plug"

          echo "export MDI_TESTS=\"${MDI_TESTS_TEMP}\"" >> env.source
          cat env.source

      # Only custom build python on ubuntu
      # On Mac, just use the prebuilt package
      #- uses: actions/setup-python@v2
      #  if: matrix.platform == 'ubuntu-latest'
      #  with:
      #    python-version: '3.7'

      - name: Install dependencies (ubuntu)
        if: matrix.platform == 'ubuntu-latest'
        run: |
          source env.source
          sudo apt-get clean
          sudo apt-get update
          sudo apt-get install gfortran
          sudo apt-get install valgrind
          sudo apt-get install libsqlite3-dev
          
          # Custom build Python with Valgrind compatibility
          git clone https://github.com/python/cpython.git
          cd cpython
          git checkout v3.10.15
          ./configure --with-pydebug --without-pymalloc --enable-shared --prefix /opt/debugpython
          make OPT=-g
          make install
          cd ..

      - name: Install dependencies (ubuntu, MPICH)
        if: ${{ matrix.platform == 'ubuntu-latest' && matrix.mpilib == 'mpich' }}
        run: |
          echo 'export PATH="${PATH}:/usr/mpich/bin"' >> env.source
          echo 'export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/usr/mpich/lib"' >> env.source
          source env.source
          wget https://github.com/pmodels/mpich/releases/download/v3.4.2/mpich-3.4.2.tar.gz
          tar -xvf ./mpich-3.4.2.tar.gz
          cd mpich-3.4.2
          ./configure --prefix="/usr/mpich" --with-device=ch4:ofi --enable-g=dbg,meminit CPPFLAGS='-I/usr/include/valgrind' FFLAGS='-fallow-argument-mismatch'
          make -j 2
          sudo make install

      - name: Install dependencies (ubuntu, OpenMPI)
        if: ${{ matrix.platform == 'ubuntu-latest' && matrix.mpilib == 'openmpi' }}
        run: |
          echo 'export PATH="${PATH}:/usr/openmpi/bin"' >> env.source
          echo 'export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/usr/openmpi/lib"' >> env.source
          echo 'export OMPI_MCA_rmaps_base_oversubscribe=1' >> env.source
          source env.source
          wget https://download.open-mpi.org/release/open-mpi/v4.0/openmpi-4.0.2.tar.gz
          tar -xvf ./openmpi-4.0.2.tar.gz
          cd openmpi-4.0.2
          ./configure --prefix="/usr/openmpi" --enable-debug --enable-memchecker --with-valgrind=/usr
          make -j 2
          sudo make install

      - name: Install Python dependencies (ubuntu)
        if: matrix.platform == 'ubuntu-latest'
        run: |
          source env.source
          sudo apt-get install python3-dev
          sudo apt-get install libpython3.12-dev
          python -m pip install --upgrade pip
          [ ! "${{ matrix.mpilib }}" == "" ] && python -m pip install mpi4py
          python -m pip install numpy
          python -m pip install -U pytest pytest-cov

      - name: Install Python dependencies for custom-built Python (ubuntu)
        if: matrix.platform == 'ubuntu-latest'
        run: |
          echo 'export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/opt/debugpython/lib"' >> env.source
          source env.source
          which python3
          python3 --version
          /opt/debugpython/bin/python3 --version
          /opt/debugpython/bin/python3 -m pip install --upgrade pip
          [ ! "${{ matrix.mpilib }}" == "" ] && /opt/debugpython/bin/python3 -m pip install mpi4py
          /opt/debugpython/bin/python3 -m pip install numpy
          /opt/debugpython/bin/python3 -m pip install -U pytest pytest-cov

      - name: Update Brew (MacOS)
        if: matrix.platform == 'macos-latest'
        run: |
          source env.source
          brew update > /dev/null

      - name: Install GCC (MacOS)
        if: matrix.platform == 'macos-latest'
        run: |
          source env.source
          brew uninstall --ignore-dependencies gcc || true
          brew install gcc || brew link --overwrite python@3.12

      - name: Install MPICH (MacOS)
        if: matrix.platform == 'macos-latest' && matrix.mpilib == 'mpich'
        run: |
          source env.source
          brew install mpich

      - name: Install OpenMPI (MacOS)
        if: matrix.platform == 'macos-latest' && matrix.mpilib == 'openmpi'
        run: |
          source env.source
          brew install open-mpi@4
          echo 'export OMPI_MCA_rmaps_base_oversubscribe=1' >> env.source
          : # OpenMPI needs access to a temporary directory
          mkdir -p ~/tempdir_${{ github.run_id }}
          echo "export TMPDIR=~/tempdir_${{ github.run_id }}" >> env.source
          echo 'ulimit -n 4096' >> env.source

      - name: Create and activate a virtual environment (MacOS)
        if: matrix.platform == 'macos-latest'
        run: |
          python3 -m venv venv
          cat venv/bin/activate >> env.source
          source env.source

      - name: Install Pip dependencies (MacOS)
        if: matrix.platform == 'macos-latest'
        run: |
          source env.source
          source venv/bin/activate
          python3 -m pip install --upgrade pip
          [ ! "${{ matrix.mpilib }}" == "" ] && python3 -m pip install mpi4py
          python3 -m pip install numpy
          python3 -m pip install -U pytest pytest-cov

      - name: Install MDI Library Python package
        run: |
          source env.source
          mkdir python_build
          cd python_build
          cmake -Dpython_package=ON -Dlanguage=Python ..
          make VERBOSE=1
          sudo make install
          cd ..
          python -c "import mdi; print(\"PATCH VERSION: \", mdi.MDI_PATCH_VERSION)"

      - name: Install local build
        run: |
          source env.source
          [ "${{ matrix.platform }}" == "macos-latest" ] && python3-config --include
          mkdir build
          cd build
          export FC=gfortran
          export CMAKE_COVERAGE_FLAGS=""
          [ "${{ matrix.platform }}" == "ubuntu-latest" ] && export CMAKE_COVERAGE_FLAGS="-O0 -coverage"
          cmake -Dtest_codes=ON -Dplugins=${{ matrix.plugins }} -DCMAKE_INSTALL_PREFIX=./install -DCMAKE_C_FLAGS="$CMAKE_COVERAGE_FLAGS" -DCMAKE_CXX_FLAGS="$CMAKE_COVERAGE_FLAGS" -DCMAKE_Fortran_FLAGS="$CMAKE_COVERAGE_FLAGS" ..
          make VERBOSE=1
          make install
          ls
          ls MDI_Library

      # Enable tmate debugging of manually-triggered workflows if the input option was provided
      - name: Setup tmate session
        uses: mxschmitt/action-tmate@v3
        if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}

      - name: Run test scripts
        run: |
          source env.source
          cd tests
          pytest -vv --cov-report=xml --cov=MDI_Library -k "${MDI_TESTS}"

      - name: Get code coverage report
        run: |
          source env.source
          cd tests
          ls -a -l
          ls -a -l ../build/MDI_Library/CMakeFiles/mdi.dir
          bash <(curl -s https://codecov.io/bash)

      - name: Install local valgrind build
        if: ${{ matrix.platform == 'ubuntu-latest' }}
        run: |
          source env.source
          rm -rf build
          mkdir build
          cd build
          export FC=gfortran
          cmake -Dtest_codes=ON -DPython_FIND_STRATEGY=LOCATION -DPython_ROOT_DIR=/opt/debugpython -DCMAKE_BUILD_TYPE=Debug ..
          make VERBOSE=1
          cd ..
          mkdir build2
          cd build2
          cmake -Dtest_codes=ON -DPython_FIND_STRATEGY=LOCATION -DPython_ROOT_DIR=/opt/debugpython -DCMAKE_BUILD_TYPE=Debug -Dtest_engines=OFF -Dlibtype=STATIC ..
          make VERBOSE=1

      - name: Run valgrind tests
        if: ${{ matrix.platform == 'ubuntu-latest' }}
        run: |
          source env.source
          cat env.source
          cd tests
          export PYTHONMALLOC=malloc
          /opt/debugpython/bin/python3 -m pytest -vv -k "${MDI_TESTS}" --valgrind

      - name: Print valgrind results
        if: ${{ matrix.platform == 'ubuntu-latest' && ( success() || failure() ) }}
        run: |
          source env.source
          cat tests/valgrind*.txt

      - name: Run valgrind tests that span two different MDI builds
        if: ${{ matrix.platform == 'ubuntu-latest' }}
        run: |
          source env.source
          cat env.source
          cd tests
          export PYTHONMALLOC=malloc
          /opt/debugpython/bin/python3 -m pytest -vv -k "${MDI_TESTS}" --driver_dir="../build2" --valgrind

      - name: Print valgrind results
        if: ${{ matrix.platform == 'ubuntu-latest' && ( success() || failure() ) }}
        run: |
          source env.source
          cat tests/valgrind*.txt

  windows:

    strategy:
      matrix:
        platform: [ windows-latest ]
        mpilib: [null]

    # The type of runner that the job will run on
    runs-on: ${{ matrix.platform }}

    env:
      TESTS: "not mpi"
      CODECOV_TOKEN: "99465b5f-26b4-4487-8355-fbcac5249a05"

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2

      # Set the Python version
      - uses: actions/setup-python@v2
        with:
          python-version: '3.6'

      - name: Install dependencies
        run: |
          choco install codecov
          python -m pip install --upgrade pip
          pip install -U pytest pytest-cov

      - name: Remove the sh.exe, which prevents MinGW from working
        run: |
          where sh > sh_loc.txt
          powershell -command "cat sh_loc.txt | rm"

      - name: Install MDI Library Python package
        run: |
          mkdir python_build
          cd python_build
          cmake -G "MinGW Makefiles" -Dpython_package=ON ..
          mingw32-make VERBOSE=1
          mingw32-make install
          cd ..
          python -c "import mdi; print(mdi.MDI_PATCH_VERSION)"

      - name: Install local build
        run: |
          mkdir build
          cd build
          echo "$(pwd)/install/lib" >> $GITHUB_PATH
          echo "$(pwd)/install/include" >> $GITHUB_PATH
          echo "$(pwd)/install/bin" >> $GITHUB_PATH
          cmake -G "MinGW Makefiles" -Dtest_codes=ON -DCMAKE_INSTALL_PREFIX="$(pwd)/install" ..
          mingw32-make VERBOSE=1
          mingw32-make install
          echo "$(dirname $(which gfortran))/../lib/mingw/tools/install/mingw64/bin" >> $GITHUB_PATH
          echo "$(dirname $(which gfortran))/../lib/mingw/tools/install/mingw64/lib" >> $GITHUB_PATH

      - name: Fortran executables don't seem to search the $PATH variable
        run: |
          cd build
          echo "ls---"
          ls
          echo "ls install---"
          ls install
          echo "ls install/bin---"
          ls install/bin
          echo "ls tests/MDI_Test_Codes/STUBS_MPI---"
          ls tests/MDI_Test_Codes/STUBS_MPI
          cp "$(pwd)/install/bin/*.dll*" "$(pwd)"
          cp "$(pwd)/tests/MDI_Test_Codes/STUBS_MPI/*.dll*" "$(pwd)"
          ls

      # Enable tmate debugging of manually-triggered workflows if the input option was provided
      # To execute: Click the GitHub "Actions" tab, then "CI", then "Run Workflow", then set debugging to "true"
      - name: Setup tmate session
        uses: mxschmitt/action-tmate@v3
        if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}

      - name: Run test scripts
        run: |
          ls
          cd tests
          pytest -vv --cov-report=xml --cov=MDI_Library -k "not mpi and not f90_plug and not py_plug and not py_cxx_plug"

      - name: Get code coverage report
        run: |
          codecov.exe -f coverage.xml -t "99465b5f-26b4-4487-8355-fbcac5249a05"



  # Build for posix systems
  conda:

    strategy:
      fail-fast: false
      matrix:
        platform: [ ubuntu-latest ]
        mpilib: [null]

    # The type of runner that the job will run on
    runs-on: ${{ matrix.platform }}

    env:
      OMPI_MCA_btl_base_warn_component_unused: "0"
      CODECOV_TOKEN: "99465b5f-26b4-4487-8355-fbcac5249a05"

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2

      # Install Miniconda
      - uses: conda-incubator/setup-miniconda@v2
        with:
          auto-activate-base: true
          activate-environment: ""

      - name: Create source file with all required environment variables
        shell: bash -el {0}
        run: |
          # Create a source file that will contain environment variables used in additional steps
          # Environment variabls are not normally preserved between steps, so the source file is necessary
          touch env.source

          # Set MDI_TESTS, which defines which tests will be performed for this job
          [ "${{ matrix.mpilib }}" == "" ] && echo 'export MDI_TESTS="not mpi"' >> env.source

          cat env.source

      - name: Install dependencies
        shell: bash -el {0}
        run: |
          source env.source
          sudo apt-get clean
          sudo apt-get update
          sudo apt-get install gfortran
          conda install -y -c conda-forge numpy
          conda install -y -c conda-forge pytest
          conda install -y -c conda-forge pymdi

      - name: Install local build
        shell: bash -el {0}
        run: |
          source env.source
          mkdir build
          cd build
          cmake -Dtest_codes=ON -DCMAKE_INSTALL_PREFIX=./install ..
          make VERBOSE=1
          #make install
          rm MDI_Library/__init__.py
          rm MDI_Library/mdi.py
          ls
          ls MDI_Library

      # Enable tmate debugging of manually-triggered workflows if the input option was provided
      # To execute: Click the GitHub "Actions" tab, then "CI", then "Run Workflow", then set debugging to "true"
      - name: Setup tmate session
        uses: mxschmitt/action-tmate@v3
        if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}

      - name: Run test scripts
        shell: bash -el {0}
        run: |
          source env.source
          conda list
          cd tests
          pytest -vv -k "${MDI_TESTS}"
