# Syntax reference https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions
# Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners
name: address sanitizer

on:
  push:
    branches:
      - 'main'
      - 'releases/**'
      - '2.*'
    tags:
      - '2.*'
  pull_request:

permissions:
  contents: read

jobs:
  build:

    runs-on: ubuntu-22.04

    env:
      QT_VERSION: 6.9.1
      ASAN_OPTIONS: detect_stack_use_after_return=1
      # TODO: figure out why there are cache misses with PCH enabled
      CCACHE_SLOPPINESS: pch_defines,time_macros

    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false

      - name: ccache
        uses: hendrikmuhs/ccache-action@v1.2
        with:
          key: ${{ github.workflow }}-${{ github.job }}-${{ matrix.os }}

      - name: Set up Python 3.13
        uses: actions/setup-python@v5
        with:
          python-version: '3.13'
          check-latest: true

      - name: Install missing software on ubuntu
        run: |
          sudo apt-get update
          sudo apt-get install -y cmake make libpcre3-dev libboost-container-dev libxml2-utils
          sudo apt-get install -y libcups2-dev  # required for Qt6PrintSupport in CMake since Qt 6.7.3

      - name: Install clang
        run: |
          sudo apt-get purge --auto-remove llvm python3-lldb-14 llvm-14
          wget https://apt.llvm.org/llvm.sh
          chmod +x llvm.sh
          sudo ./llvm.sh 20

      - name: Install Qt ${{ env.QT_VERSION }}
        uses: jurplel/install-qt-action@v4
        with:
          version: ${{ env.QT_VERSION }}
          modules: 'qtcharts'
          setup-python: 'false'
          cache: true

      - name: Install missing Python packages
        run: |
          python3 -m pip install pip --upgrade
          python3 -m pip install pytest
          python3 -m pip install pytest-timeout
          python3 -m pip install pytest-xdist
          python3 -m pip install psutil

      # TODO: disable all warnings
      - name: CMake
        run: |
          cmake -S . -B cmake.output -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DUSE_QT6=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DUSE_MATCHCOMPILER=Verify -DANALYZE_ADDRESS=On -DENABLE_CHECK_INTERNAL=On -DUSE_BOOST=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DFILESDIR= -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
        env:
          CC: clang-20
          CXX: clang++-20

      - name: Build cppcheck
        run: |
          cmake --build cmake.output --target cppcheck -- -j $(nproc)

      - name: Build test
        run: |
          cmake --build cmake.output --target testrunner -- -j $(nproc)

      - name: Build GUI tests
        run: |
          cmake --build cmake.output --target gui-tests -- -j $(nproc)

      - name: Run tests
        run: ./cmake.output/bin/testrunner

      - name: Run cfg tests
        run: |
          cmake --build cmake.output --target checkcfg -- -j $(nproc)

      - name: Run CTest
        run: |
          ctest --test-dir cmake.output --output-on-failure -j$(nproc)

      - name: Run test/cli
        run: |
          pwd=$(pwd)
          TEST_CPPCHECK_EXE_LOOKUP_PATH="$pwd/cmake.output" python3 -m pytest -Werror --strict-markers -vv -n auto test/cli

      - name: Run test/cli (-j2)
        run: |
          pwd=$(pwd)
          TEST_CPPCHECK_EXE_LOOKUP_PATH="$pwd/cmake.output" python3 -m pytest -Werror --strict-markers -vv -n auto test/cli
        env:
          TEST_CPPCHECK_INJECT_J: 2

      - name: Run test/cli (--clang)
        if: false
        run: |
          pwd=$(pwd)
          TEST_CPPCHECK_EXE_LOOKUP_PATH="$pwd/cmake.output" python3 -m pytest -Werror --strict-markers -vv -n auto test/cli
        env:
          TEST_CPPCHECK_INJECT_CLANG: clang

      - name: Run test/cli (--cppcheck-build-dir)
        run: |
          pwd=$(pwd)
          TEST_CPPCHECK_EXE_LOOKUP_PATH="$pwd/cmake.output" python3 -m pytest -Werror --strict-markers -vv -n auto test/cli
        env:
          TEST_CPPCHECK_INJECT_BUILDDIR: injected

      - name: Generate dependencies
        if: false
        run: |
          # make sure auto-generated GUI files exist
          make -C cmake.output autogen
          make -C cmake.output gui-build-deps triage-build-ui-deps

      # TODO: this is currently way too slow (~60 minutes) to enable it
      # TODO: only fail the step on sanitizer issues - since we use processes it will only fail the underlying process which will result in an cppcheckError
      - name: Self check
        if: false
        run: |
          selfcheck_options="-q -j$(nproc) --std=c++11 --template=selfcheck --showtime=file-total -D__GNUC__ --error-exitcode=1 --inline-suppr --suppressions-list=.selfcheck_suppressions --library=gnu --inconclusive --enable=style,performance,portability,warning,missingInclude --exception-handling --debug-warnings --check-level=exhaustive"
          cppcheck_options="-D__CPPCHECK__ -DCHECK_INTERNAL -DHAVE_RULES --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2"
          ec=0
          ./cmake.output/bin/cppcheck $selfcheck_options externals || ec=1
          ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options --addon=naming.json frontend || ec=1
          ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options --addon=naming.json -Ifrontend cli || ec=1
          ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options --addon=naming.json --enable=internal lib || ec=1
          ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --library=qt --addon=naming.json -Icmake.output/gui -Ifrontend -Igui gui/*.cpp cmake.output/gui/*.cpp || ec=1
          ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options -Icli -Ifrontend test/*.cpp || ec=1
          ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options -Icli tools/dmake/*.cpp || ec=1
          ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --library=qt -Icmake.output/tools/triage -Igui tools/triage/*.cpp cmake.output/tools/triage/*.cpp || ec=1
          exit $ec
