name: migraphx

on: 
  pull_request:
  push:
    branches: 
      - develop
      - master
      - 'release/**'


jobs:
  cancel:
    runs-on: ubuntu-latest
    steps:
      - name: Cancel Previous Runs
        uses: styfle/cancel-workflow-action@0.11.0
        with:
          access_token: ${{ github.token }}
  tidy:
    runs-on: ubuntu-20.04

    steps:
    - name: Free space
      uses: jlumbroso/free-disk-space@main
      with:
        tool-cache: true
        android: true
        dotnet: true
        haskell: true
        large-packages: true
        swap-storage: true

    - uses: actions/checkout@v3

    # In this step, this action saves a list of existing images,
    # the cache is created without them in the post run.
    # It also restores the cache if it exists.
    - name: Docker layer cache
      uses: jpribyl/action-docker-layer-caching@v0.1.1
      with:
        key: docker-layer-caching-migraphx-${{hashFiles('hip-clang.docker', '**/*requirements.txt', '**/install_prereqs.sh', 'rbuild.ini')}}
        restore-keys:
          docker-layer-caching-migraphx-
      # Ignore the failure of a step and avoid terminating the job.
      continue-on-error: true

    - name: Restore cache files for tidy
      uses: actions/cache/restore@v3 
      id: tidy_restore
      with:
        path: tidy-cache
        key: tidy-cache-${{ github.ref }}
        restore-keys: tidy-cache-
        
    - name: Build the Docker image
      run: |
        docker build . --file hip-clang.docker --tag migraphx

    - name: Clang tidy
      shell: bash -c "docker run -i -v=$GITHUB_WORKSPACE:/data -w /data migraphx bash < {0}"
      run: |
        mkdir build
        cd build
        CXX=/opt/rocm/llvm/bin/clang++ CC=/opt/rocm/llvm/bin/clang cmake \
          -DMIGRAPHX_ENABLE_GPU=On \
          -DMIGRAPHX_ENABLE_CPU=On \
          -DMIGRAPHX_ENABLE_FPGA=On \
          -DBUILD_DEV=On \
          -DROCM_ENABLE_GH_ANNOTATIONS=On \
          -DCLANG_TIDY_DEPEND_ON_TARGET=Off \
          -DCLANG_TIDY_CACHE=/data/tidy-cache \
          ..
        make -j2 -k onnx-proto tf-proto tidy

    # GH actions can not update existing cache, as a workaround clear cache and then save it
    - name: Clear tidy cache before saving
      if: ${{ steps.tidy_restore.outputs.cache-hit }}
      shell: bash
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
        gh extension install actions/gh-actions-cache --pin v1.0.1
        gh actions-cache delete ${{ steps.tidy_restore.outputs.cache-matched-key }} --confirm
      continue-on-error: true

    - name: Save cache files for tidy
      uses: actions/cache/save@v3 
      if: always()
      with:
        path: tidy-cache
        key: tidy-cache-${{ github.ref }}


  cppcheck:
    runs-on: ubuntu-20.04

    steps:
    - name: Free space
      uses: jlumbroso/free-disk-space@main
      with:
        tool-cache: true
        android: true
        dotnet: true
        haskell: true
        large-packages: true
        swap-storage: true


    - uses: actions/checkout@v3

    # In this step, this action saves a list of existing images,
    # the cache is created without them in the post run.
    # It also restores the cache if it exists.
    - name: Docker layer cache
      uses: jpribyl/action-docker-layer-caching@v0.1.1
      with:
        key: docker-layer-caching-migraphx-${{hashFiles('hip-clang.docker', '**/*requirements.txt', '**/install_prereqs.sh', 'rbuild.ini')}}
        restore-keys:
          docker-layer-caching-migraphx-
      # Ignore the failure of a step and avoid terminating the job.
      continue-on-error: true

    - name: Restore cache files for cppcheck
      id: cppcheck_restore
      uses: actions/cache/restore@v3
      with:
        path: cppcheck-cache
        key: cppcheck-cache-${{ hashFiles('cppcheck.rules', 'CMakeLists.txt') }}-${{ github.ref }}
        restore-keys: cppcheck-cache-${{ hashFiles('cppcheck.rules', 'CMakeLists.txt') }}-

    - name: Build the Docker image
      run: docker build . --file hip-clang.docker --tag migraphx

    - name: Cppcheck
      shell: bash -c "docker run -i -v=$GITHUB_WORKSPACE:/data -w /data migraphx bash < {0}"
      run: |
        mkdir build
        cd build
        CXX=/opt/rocm/llvm/bin/clang++ CC=/opt/rocm/llvm/bin/clang cmake \
          -DCPPCHECK_BUILD_DIR=/data/cppcheck-cache \
          -DBUILD_DEV=On \
          -DROCM_ENABLE_GH_ANNOTATIONS=On \
          ..
        make -j2 cppcheck

    # GH actions can not update existing cache, as a workaround clear cache and then save it
    - name: Clear cppcheck cache before saving
      if: ${{ steps.cppcheck_restore.outputs.cache-hit }}
      shell: bash
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
        gh extension install actions/gh-actions-cache --pin v1.0.1
        gh actions-cache delete ${{ steps.cppcheck_restore.outputs.cache-matched-key }} --confirm
      continue-on-error: true

    - name: Save cache files for cppcheck
      uses: actions/cache/save@v3
      if: always()
      with:
        path: cppcheck-cache
        key: cppcheck-cache-${{ hashFiles('cppcheck.rules', 'CMakeLists.txt') }}-${{ github.ref }}


  format:
    runs-on: ubuntu-20.04

    steps:
    - name: Free space
      uses: jlumbroso/free-disk-space@main
      with:
        tool-cache: true
        android: true
        dotnet: true
        haskell: true
        large-packages: true
        swap-storage: true
    - uses: actions/checkout@v3

    # In this step, this action saves a list of existing images,
    # the cache is created without them in the post run.
    # It also restores the cache if it exists.
    - name: Docker layer cache
      uses: jpribyl/action-docker-layer-caching@v0.1.1
      with:
        key: docker-layer-caching-migraphx-${{hashFiles('hip-clang.docker', '**/*requirements.txt', '**/install_prereqs.sh', 'rbuild.ini')}}
        restore-keys:
          docker-layer-caching-migraphx-
      # Ignore the failure of a step and avoid terminating the job.
      continue-on-error: true

    - name: Build the Docker image
      run: docker build . --file hip-clang.docker --tag migraphx

    - name: Check formatting
      shell: bash -c "docker run -i -v=$GITHUB_WORKSPACE:/data -w /data migraphx bash < {0}"
      run: |
        set -e
        find . -iname '*.h' \
              -o -iname '*.hpp' \
              -o -iname '*.cpp' \
              -o -iname '*.h.in' \
              -o -iname '*.hpp.in' \
              -o -iname '*.cpp.in' \
              -o -iname '*.cl' \
              -o -iname '*.c' \
          | grep -v 'build/' \
          | xargs -n 1 -P 1 -I{} -t sh -c 'clang-format-10 -style=file {} | diff - {}'
          find . -iname '*.py' \
          | grep -v 'build/'  \
          | xargs -n 1 -P 1 -I{} -t sh -c 'yapf {} | diff - {}'

  pyflakes:
    runs-on: ubuntu-20.04

    steps:
    - name: Free space
      uses: jlumbroso/free-disk-space@main
      with:
        tool-cache: true
        android: true
        dotnet: true
        haskell: true
        large-packages: true
        swap-storage: true

    - uses: actions/checkout@v3
    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: 3.8
    - name: Install pyflakes
      run: pip install pyflakes==2.4.0 mypy==0.931

    - name: Run pyflakes
      run: |
        pyflakes --version
        pyflakes examples/ tools/ src/ test/ docs/
        mypy --version
        mypy tools/api.py

  licensing:
    runs-on: ubuntu-20.04

    steps:
    - name: Free space
      uses: jlumbroso/free-disk-space@main
      with:
        tool-cache: true
        android: true
        dotnet: true
        haskell: true
        large-packages: true
        swap-storage: true

    - uses: actions/checkout@v3
    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: 3.8
    - name: run License Check
      run: python3 tools/check_stamped.py

  linux:

    runs-on: ${{ matrix.os }}

    env:
      CCACHE_COMPRESSLEVEL: 10
      CCACHE_DIR: ${{github.workspace}}/ccache
      CCACHE_NOHASHDIR: true
      CCACHE_BASEDIR: ${{github.workspace}}
      CCACHE_MAXSIZE: 1

    strategy:
      matrix:
        os:
          - ubuntu-20.04
        configuration:
          - debug
          - release
          - codecov

    steps:
    - name: Free space
      uses: jlumbroso/free-disk-space@main
      with:
        tool-cache: true
        android: true
        dotnet: true
        haskell: true
        large-packages: true
        swap-storage: true

    - name : Install rbuild and lld
      run: |
        sudo apt-get install -y lld
        python -m pip install --upgrade pip
        pip install https://github.com/RadeonOpenCompute/rbuild/archive/master.tar.gz

    - uses: actions/checkout@v3
    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: 3.7
    - name: Cache dependencies
      # Ignore the failure of a step and avoid terminating the job.
      continue-on-error: true
      uses: actions/cache@v3
      id: deps_cache
      with:
        # This path is specific to Ubuntu
        path: ${{ github.workspace }}/cget
        # Look to see if there is a cache hit for the corresponding requirements file
        key: ${{ matrix.os }}-cget-4-${{ hashFiles('requirements.txt', 'dev-requirements.txt') }}
        restore-keys: ${{ matrix.os }}-cget-4-

    - name: Install dependencies
      if: steps.deps_cache.outputs.cache-hit != 'true'
      run: rbuild prepare -d cget -s gh

    - name: Restore cache files for ccache
      uses: actions/cache/restore@v3 
      id: ccache_restore
      with:
        path: ${{ github.workspace }}/ccache
        key: ${{ matrix.os }}-${{ matrix.configuration }}-ccache-${{ github.ref }}
        restore-keys: ${{ matrix.os }}-${{ matrix.configuration }}-ccache-

    - name: Build and test
      env:
        CMAKE_PREFIX_PATH: ${{ github.workspace }}/cget
        CCACHE_LOGFILE: /tmp/ccache.log
        CXXFLAGS: -Werror -pthread --param ggc-min-expand=5 --param ggc-min-heapsize=8192
      run: |
        echo "leak:dnnl::impl::malloc" > suppressions.txt
        export LSAN_OPTIONS="suppressions=$(pwd)/suppressions.txt"
        rbuild build -d cget -s gh -T check \
          -DCMAKE_BUILD_TYPE=${{matrix.configuration}} \
          -DMIGRAPHX_ENABLE_PYTHON=${{matrix.configuration == 'release' && 'On' || 'Off'}} \
          -DBUILD_DEV=On \
          -DCMAKE_CXX_FLAGS_DEBUG="-g1 -Os -fdebug-prefix-map=$PWD=. -fdebug-types-section -fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize-recover=undefined" \
          -DCMAKE_CXX_FLAGS_CODECOV="-g1 -Og -fdebug-prefix-map=$PWD=. -fdebug-types-section -fprofile-arcs -ftest-coverage -fno-omit-frame-pointer" \
          -DCMAKE_EXE_LINKER_FLAGS='-fuse-ld=lld' \
          -DCMAKE_SHARED_LINKER_FLAGS='-fuse-ld=lld'
        ${{ github.workspace }}/cget/bin/ccache -s

    # GH actions can not update existing cache, as a workaround clear cache and then save it
    - name: Clear ccache cache before saving
      if: ${{ steps.ccache_restore.outputs.cache-hit }}
      shell: bash
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
        gh extension install actions/gh-actions-cache --pin v1.0.1
        gh actions-cache delete ${{ steps.ccache_restore.outputs.cache-matched-key }} --confirm

    - name: Save cache files for ccache
      uses: actions/cache/save@v3 
      if: always()
      with:
        path: ${{ github.workspace }}/ccache
        key: ${{ matrix.os }}-${{ matrix.configuration }}-ccache-${{ github.ref }}

    - name: Upload code coverage
      if: "matrix.configuration == 'codecov'"
      env:
        CODECOV_TOKEN: "8545af1c-f90b-4345-92a5-0d075503ca56"
      run: |
        sudo apt-get install -y lcov
        cd build
        lcov --directory . --capture --output-file $(pwd)/coverage.info
        lcov --remove $(pwd)/coverage.info '/usr/*' --output-file $(pwd)/coverage.info
        lcov --list $(pwd)/coverage.info
        curl -Os https://uploader.codecov.io/latest/linux/codecov
        chmod +x codecov
        ./codecov -t ${CODECOV_TOKEN}
        echo "Uploaded"

  linux-fpga:
    continue-on-error: true
    runs-on: ${{ matrix.os }}

    env:
      CCACHE_COMPRESSLEVEL: 10
      CCACHE_DIR: ${{github.workspace}}/ccache
      CCACHE_NOHASHDIR: true
      CCACHE_BASEDIR: ${{github.workspace}}
      CCACHE_MAXSIZE: 1

    strategy:
      matrix:
        os:
          - ubuntu-20.04
        configuration:
          - debug
          #- release  Uncomment when ready to test release builds
          #- codecov  Uncomment when ready for codecov

    steps:
    - name: Free space
      uses: jlumbroso/free-disk-space@main
      with:
        tool-cache: true
        android: true
        dotnet: true
        haskell: true
        large-packages: true
        swap-storage: true

    - uses: actions/checkout@v3
    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: 3.7

    - name: Cache dependencies
      # Ignore the failure of a step and avoid terminating the job.
      continue-on-error: true
      uses: actions/cache@v3
      with:
        # This path is specific to Ubuntu
        path: ${{ github.workspace }}/cget
        # Look to see if there is a cache hit for the corresponding requirements file
        key: ${{ matrix.os }}-cget-4-${{ hashFiles('requirements.txt', 'dev-requirements.txt') }}
        restore-keys: ${{ matrix.os }}-cget-4-


    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install https://github.com/RadeonOpenCompute/rbuild/archive/master.tar.gz
        rbuild prepare -d cget -s gh
        sudo apt-get install -y lld

    - name: Restore cache files for ccache
      id: ccache_restore_fpga
      uses: actions/cache/restore@v3 
      with:
        path: ${{ github.workspace }}/ccache
        key: ${{ matrix.os }}-${{ matrix.configuration }}-ccache-${{ github.ref }}
        restore-keys: ${{ matrix.os }}-${{ matrix.configuration }}-ccache-
    
    - name: Build and test
      env:
        CMAKE_PREFIX_PATH: ${{ github.workspace }}/cget
        CCACHE_LOGFILE: /tmp/ccache.log
        CXXFLAGS: -Werror -pthread --param ggc-min-expand=5 --param ggc-min-heapsize=8192
      run: |
        echo "leak:dnnl::impl::malloc" > suppressions.txt
        export LSAN_OPTIONS="suppressions=$(pwd)/suppressions.txt"
        rbuild build -d cget -s gh -T check \
          -DCMAKE_BUILD_TYPE=${{matrix.configuration}} \
          -DMIGRAPHX_ENABLE_PYTHON=${{matrix.configuration == 'release' && 'On' || 'Off'}} \
          -DBUILD_DEV=On \
          -DCMAKE_CXX_FLAGS_DEBUG="-g1 -Os -fdebug-prefix-map=$PWD=. -fdebug-types-section -fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize-recover=undefined" \
          -DCMAKE_CXX_FLAGS_CODECOV="-g1 -Og -fdebug-prefix-map=$PWD=. -fdebug-types-section -fprofile-arcs -ftest-coverage -fno-omit-frame-pointer" \
          -DCMAKE_EXE_LINKER_FLAGS='-fuse-ld=lld' \
          -DCMAKE_SHARED_LINKER_FLAGS='-fuse-ld=lld' \
          -DMIGRAPHX_ENABLE_FPGA=On
        ${{ github.workspace }}/cget/bin/ccache -s

    # this is a workaround, with GH actions can not update existing cache
    - name: Clear ccache cache before saving
      if: ${{ steps.ccache_restore_fpga.outputs.cache-hit }}
      shell: bash
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
        gh extension install actions/gh-actions-cache
        gh actions-cache delete ${{ steps.ccache_restore_fpga.outputs.cache-matched-key }} --confirm
      continue-on-error: true

    - name: Save cache files for ccache
      uses: actions/cache/save@v3 
      if: always()
      with:
        path: ${{ github.workspace }}/ccache
        key: ${{ matrix.os }}-${{ matrix.configuration }}-ccache-${{ github.ref }}

      #- name: Upload code coverage
      #  if: "matrix.configuration == 'codecov'"
      #  env:
      #    CODECOV_TOKEN: "8545af1c-f90b-4345-92a5-0d075503ca56"
      #  run: |
      #    sudo apt-get install -y lcov
      #    cd build
      #    lcov --directory . --capture --output-file $(pwd)/coverage.info
      #    lcov --remove $(pwd)/coverage.info '/usr/*' --output-file $(pwd)/coverage.info
      #    lcov --list $(pwd)/coverage.info
      #    curl -Os https://uploader.codecov.io/latest/linux/codecov
      #    chmod +x codecov
      #    ./codecov -t ${CODECOV_TOKEN}
      #    echo "Uploaded"

