name: Build, Test, and Benchmark

on:
  push:
    branches:
    - master
    - ci-*
    - release*
    paths-ignore: &ignore_path_list
    - '.github/*'
    - '.github/workflows/cabal.yml'
    - '.github/workflows/cabal-test.yml'
    - '.github/workflows/haddock.yml'
    - '.github/workflows/lint.yml'
    - '.github/workflows/deploy.yml'
    - '.github/workflows/stack.yml'
    - '.github/workflows/user_manual.yml'
    - '.github/workflows/whitespace.yml'
    - 'src/agda-bisect/**'
    - 'src/fix-whitespace/**'
    - 'src/github/workflows/cabal.yml'
    - 'src/github/workflows/cabal-test.yml'
    - 'src/github/workflows/haddock.yml'
    - 'src/github/workflows/lint.yml'
    - 'src/github/workflows/deploy.yml'
    - 'src/github/workflows/stack.yml'
    - 'src/github/workflows/user_manual.yml'
    - 'src/github/workflows/whitespace.yml'
    - 'src/hs-tags/**'
    - 'src/release-tools/**'
    - '.travis'
    - 'macros/**'
    - 'notes/**'
    - '.mailmap'
    - '.ghci*'
    - '.gitignore'
    - '.hlint.yaml'
    - '.travis.yml'
    - 'CHANGELOG.md'
    - 'HACKING.md'
    - 'LICENSE'
    - 'README.md'
    - 'fix-whitespace.yaml'
    - 'hie.yaml'
    - 'stack-*.yaml'
    - 'touchup.sh'
  pull_request:
    paths-ignore: *ignore_path_list

  workflow_dispatch:

env:
  PARALLEL_TESTS: 2
  BUILD_DIR: "dist" # relative path, please!

  APT_GET_OPTS: "-yqq --no-install-suggests --no-install-recommends"
  AGDA_TESTS_OPTIONS: "-j${PARALLEL_TESTS} --hide-successes"
  TASTY_ANSI_TRICKS: "false"

jobs:
  build:
    strategy:
      matrix:
        # TODO (Andreas, 2021-11-13)
        # Upgrade to 9.2.1 once this does not cause problems with shelltestrunner
        # https://github.com/agda/agda/pull/5648#issuecomment-968100273
        ghc-ver: [9.0.2]
        stack-ver: [latest]
        os: [ubuntu-18.04]

    if: |
      !contains(github.event.head_commit.message, '[skip ci]')
      && !contains(github.event.head_commit.message, '[ci skip]')
      && !contains(github.event.head_commit.message, '[github skip]')
      && !contains(github.event.head_commit.message, '[skip github]')

    outputs:
      ghc-ver: ${{ matrix.ghc-ver }}
      stack-ver: ${{ matrix.stack-ver }}
      os: ${{ matrix.os }}

    runs-on: ${{ matrix.os }}
    steps:
    - uses: styfle/cancel-workflow-action@0.6.0
      with:
        access_token: ${{ github.token }}

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

    - uses: haskell/actions/setup@v1
      with:
        ghc-version: ${{ matrix.ghc-ver }}
        stack-version: ${{ matrix.stack-ver }}
        enable-stack: true

    - name: "Update and configure stack"
      run: |
        stack update --silent
        echo "system-ghc: true" >> ~/.stack/config.yaml

    - name: "Copy stack-${{ matrix.ghc-ver}}.yaml to stack.yaml"
      run: |
        cp stack-${{ matrix.ghc-ver }}.yaml stack.yaml
        make STACK_INSTALL_OPTS='--dry-run' install-deps

    - uses: actions/cache@v2
      name: Cache dependencies
      id: cache
      with:
        path: "~/.stack"
        # A unique cache is used for each stack.yaml.
        key: ${{ runner.os }}-stack-01-${{ matrix.stack-ver }}-${{ hashFiles('stack.yaml') }}-${{ hashFiles('stack.yaml.lock') }}

    - name: "Install and configure the icu library"
      run: sudo apt-get install libicu-dev ${APT_GET_OPTS}

    - name: "Install dependencies for Agda and its test suites"
      if: ${{ !steps.cache.outputs.cache-hit }}
      run: make STACK_OPTS=--silent install-deps

    - name: "Build Agda"
      run: make BUILD_DIR="${BUILD_DIR}" install-bin

    - name: "Run tests for the size solver"
      run: |
        export PATH=${HOME}/.local/bin:${PATH}
        make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" size-solver-test

    - name: "Pack artifacts"
      # This step should go to Makefile.
      run: |
        strip ${BUILD_DIR}/build/agda-tests/agda-tests \
          ${BUILD_DIR}/build/agda/agda \
          ${BUILD_DIR}/build/agda-mode/agda-mode

        tar --use-compress-program zstd -cvf dist.tzst \
          ${BUILD_DIR}/build/agda-tests/agda-tests \
          ${BUILD_DIR}/build/agda/agda \
          ${BUILD_DIR}/build/agda-mode/agda-mode

        tar --use-compress-program zstd -cvf stack-work.tzst .stack-work stack.yaml stack.yaml.lock

    - name: "Upload artifacts"
      uses: actions/upload-artifact@v2
      with:
        if-no-files-found: error
        retention-days: 1
        name: agda-${{ runner.os }}-${{ github.sha }}
        path: |
          dist.tzst
          stack-work.tzst

  test:
    needs: build
    runs-on: ${{ needs.build.outputs.os }}
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive

    - uses: haskell/actions/setup@v1
      with:
        ghc-version: ${{ needs.build.outputs.ghc-ver }}
        stack-version: ${{ needs.build.outputs.stack-ver }}
        enable-stack: true

    - uses: actions/download-artifact@v2
      with:
        name: agda-${{ runner.os }}-${{ github.sha }}

    - name: "Unpack artifacts"
      run: |
        tar --use-compress-program zstd -xvf dist.tzst
        tar --use-compress-program zstd -xvf stack-work.tzst

    - uses: actions/cache@v2
      name: Cache dependencies
      id: cache
      with:
        path: "~/.stack"
        # A unique cache is used for each stack.yaml.
        key: ${{ runner.os }}-stack-01-${{ needs.build.outputs.stack-ver }}-${{ hashFiles('stack.yaml') }}-${{ hashFiles('stack.yaml.lock') }}

    - name: "Suite of tests for bugs"
      run: make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" bugs

    - name: "Suite of successful tests: mini-library Common"
      run: make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" common

    - name: "Suite of successful tests"
      run: make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" succeed

    - name: "Suite of failing tests"
      run: make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" fail

    - name: "Compiler tests"
      run: make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" compiler-test

    - name: "Suite of interactive tests"
      run: make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" interactive

  stdlib-test:
    needs: build

    runs-on: ${{ needs.build.outputs.os }}
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive

    - uses: haskell/actions/setup@v1
      with:
        ghc-version: ${{ needs.build.outputs.ghc-ver }}
        stack-version: ${{ needs.build.outputs.stack-ver }}
        enable-stack: true

    - uses: actions/download-artifact@v2
      with:
        name: agda-${{ runner.os }}-${{ github.sha }}

    - name: "Unpack artifacts"
      run: |
        tar --use-compress-program zstd -xvf dist.tzst
        tar --use-compress-program zstd -xvf stack-work.tzst

    - uses: actions/cache@v2
      name: Cache dependencies
      id: cache
      with:
        path: "~/.stack"
        # A unique cache is used for each stack.yaml.
        key: ${{ runner.os }}-stack-01-${{ needs.build.outputs.stack-ver }}-${{ hashFiles('stack.yaml') }}-${{ hashFiles('stack.yaml.lock') }}

    - name: "Install and configure the icu library"
      run: sudo apt-get install libicu-dev ${APT_GET_OPTS}

    - name: "Standard library test"
      run: |
        # ASR (2021-01-17). `cabal update` is required due to #5138.
        # We should also use `stack` in this test.
        cabal update
        make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" std-lib-test

    - name: "Standard library compiler tests"
      run: make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" std-lib-compiler-test

    - name: "Successful tests using the standard library"
      run: make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" std-lib-succeed

    - name: "Interaction tests using the standard library"
      run: make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" std-lib-interaction

  cubical-benchmark-misc:
    needs: build

    runs-on: ${{ needs.build.outputs.os }}
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive

    - uses: haskell/actions/setup@v1
      with:
        ghc-version: ${{ needs.build.outputs.ghc-ver }}
        stack-version: ${{ needs.build.outputs.stack-ver }}
        enable-stack: true

    - uses: actions/download-artifact@v2
      with:
        name: agda-${{ runner.os }}-${{ github.sha }}

    - name: "Unpack artifacts"
      run: |
        tar --use-compress-program zstd -xvf dist.tzst
        tar --use-compress-program zstd -xvf stack-work.tzst

    - uses: actions/cache@v2
      name: Cache dependencies
      id: cache
      with:
        path: "~/.stack"
        # A unique cache is used for each stack.yaml.
        key: ${{ runner.os }}-stack-01-${{ needs.build.outputs.stack-ver }}-${{ hashFiles('stack.yaml') }}-${{ hashFiles('stack.yaml.lock') }}

    - name: "Install and configure the icu library"
      run: sudo apt-get install libicu-dev ${APT_GET_OPTS}

    - name: "Install Tex Live and Emacs"
      run: |
        sudo apt-get update
        sudo apt-get install texlive-binaries ${APT_GET_OPTS}
        sudo apt-get install emacs-nox ${APT_GET_OPTS}

    - name: "Benchmark"
      run: |
        make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" benchmark-without-logs
        make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" benchmark-summary

    - name: "Internal test suite"
      run: make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" internal-tests

    - name: "Suite of interaction tests"
      run: make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" DONT_RUN_LATEX=Y interaction

    - name: "Suite of tests for the LaTeX and HTML backends"
      run: make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" DONT_RUN_LATEX=Y latex-html-test

    - name: "Suite of examples"
      run: make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" examples

    - name: "Successful tests using Agda as a Haskell library"
      run: make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" api-test

    - name: "User manual (test)"
      run: make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" user-manual-test

    - name: "Testing the Emacs mode"
      run: make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" testing-emacs-mode

    # (Liang-Ting Chen, 2022-01-02): For testing breaking changes where
    # libraries need to be updated, cubical library test is moved to the end of
    # this job.
    - name: "Cubical library test"
      run: make BUILD_DIR="${GITHUB_WORKSPACE}/${BUILD_DIR}" cubical-test

