name: CI

on: [push, pull_request]

jobs:
  bindings-coverage:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive
    - name: Bindings
      run: ./.ci/bindcov.sh
    - name: Docs
      run: ./.ci/docscov.sh

  clang-asan:
    runs-on: ubuntu-latest
    env:
      ASAN_OPTIONS: detect_leaks=1:check_initialization_order=1
      UBSAN_OPTIONS: print_stacktrace=1
      BUILD_TYPE: Debug
      WITH_LUA_ENGINE: Lua
      CC: clang
      CXX: clang++
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive
    - name: Build
      run: CMAKE_OPTIONS="-DCMAKE_C_FLAGS='-fsanitize=address,undefined -fno-sanitize-recover=all'" make
    - name: Test
      run: make test
    - name: Test with Aggressive GC
      # Run with extremely aggressive garbage collection to potentially find more problems
      run: ./build/lua -e "collectgarbage('incremental', 0, 10000000000000)" tests/run.lua

  clang-tsan:
    runs-on: ubuntu-latest
    env:
      BUILD_TYPE: Debug
      WITH_LUA_ENGINE: Lua
      CC: clang
      CXX: clang++
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive
    - name: Build
      run: CMAKE_OPTIONS="-DCMAKE_C_FLAGS=-fsanitize=thread -DCMAKE_SHARED_LINKER_FLAGS=-fsanitize=thread -DTSAN=ON" make
    - name: Test
      run: make test
    - name: Test with Aggressive GC
      # Run with extremely aggressive garbage collection to potentially find more problems
      run: ./build/lua -e "collectgarbage('incremental', 0, 10000000000000)" tests/run.lua

  valgrind:
    runs-on: ubuntu-latest
    env:
      BUILD_TYPE: Debug
      WITH_LUA_ENGINE: Lua
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive
    - name: Install Valgrind
      run: |
        sudo apt-get update
        sudo apt-get install -y valgrind
    - name: Build
      run: make
    - name: Test
      run: valgrind --suppressions=.ci/valgrind_mem.supp --error-exitcode=1 --leak-check=full --child-silent-after-fork=yes --keep-debuginfo=yes --track-origins=yes ./build/lua -e "collectgarbage('incremental', 0, 10000000000000)" tests/run.lua

  process-cleanup-test:
    runs-on: ubuntu-latest
    env:
      WITH_LUA_ENGINE: Lua
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive
    - run: ./tests/test-sigchld-after-lua_close.sh

  minimum-supported-libuv:
    runs-on: ubuntu-latest
    env:
      WITH_LUA_ENGINE: Lua
      WITH_SHARED_LIBUV: On
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive
    - name: Setup
      run: ./.ci/setup_min_libuv.sh
    - name: Build
      run: CMAKE_OPTIONS="-DCMAKE_PREFIX_PATH=$HOME/.libuv_min" make
    - name: Test
      run: make test

  build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [macos-latest, ubuntu-latest]
        luarocks_version: [3.8.0]
        lua_engine: [Lua, LuaJIT]
        include:
          - lua_engine: LuaJIT
            lua_version: luajit2.1
          - lua_engine: Lua
            lua_version: lua5.4
    env:
      # For LuaJIT 2.1, see https://github.com/LuaJIT/LuaJIT/commit/8961a92dd1607108760694af3486b4434602f8be
      MACOSX_DEPLOYMENT_TARGET: 10.12
      LUAROCKS: ${{ matrix.luarocks_version }}
      LUA: ${{ matrix.lua_version }}
      WITH_LUA_ENGINE: ${{ matrix.lua_engine }}

    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive

    - name: Build
      run: make

    - name: Test
      run: make test

    - name: Setup Luarocks
      run: |
        source .ci/setenv_lua.sh
        echo "$HOME/.lua" >> $GITHUB_PATH
        echo "LUA_PATH=$LUA_PATH" >> $GITHUB_ENV
        echo "LUA_CPATH=$LUA_CPATH" >> $GITHUB_ENV

    - name: Build with Luarocks
      run: |
        luarocks make
        test $PWD = `lua -e "print(require'luv'.cwd())"`
        luarocks remove luv

    - name: Build with Luarocks (alternate rockspec)
      run: |
        mkdir ${{github.workspace}}/build/lib
        cp ${{github.workspace}}/build/deps/libuv/libuv.a ${{github.workspace}}/build/lib/libuv.a
        cp -a ${{github.workspace}}/deps/libuv/include ${{github.workspace}}/build
        luarocks make rockspecs/$(ls rockspecs) LIBUV_DIR=${{github.workspace}}/build LUA_COMPAT53_INCDIR=${{github.workspace}}/deps/lua-compat-5.3/c-api
        test $PWD = `lua -e "print(require'luv'.cwd())"`

  deploy:
    if: startsWith(github.ref, 'refs/tags/')
    needs: [build, minimum-supported-libuv, process-cleanup-test, valgrind, clang-asan, bindings-coverage]
    runs-on: ubuntu-latest
    env:
      WITH_LUA_ENGINE: LuaJIT
      LUA: luajit2.1
      LUAROCKS: 3.8.0
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive

    - name: Get version
      id: get_version
      run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/}

    - name: Setup
      run: |
        source .ci/setenv_lua.sh
        echo "$HOME/.lua" >> $GITHUB_PATH
        echo "LUA_PATH=$LUA_PATH" >> $GITHUB_ENV
        echo "LUA_CPATH=$LUA_CPATH" >> $GITHUB_ENV

    - name: Build
      run: .ci/make_rockspec.sh ${{ steps.get_version.outputs.VERSION }}

    - name: Github Release
      id: create_release
      uses: softprops/action-gh-release@v1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        files: luv-${{ steps.get_version.outputs.VERSION }}.tar.gz
        draft: false
        prerelease: false

    - name: Luarocks Release
      # lua-cjson is required for luarocks upload
      env:
        LUAROCKS_API_KEY: ${{ secrets.LUAROCKS_API_KEY }}
      run: |
        luarocks install lua-cjson
        luarocks upload luv-${{ steps.get_version.outputs.VERSION }}.rockspec --api-key=$LUAROCKS_API_KEY --force
