name: clang-tidy

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

permissions:
  contents: read

jobs:
  clang-tidy:
    runs-on: ubuntu-24.04
    strategy:
      fail-fast: false
      matrix:
        include:
          - cmake_options: all-options-abiv1-preview
            warning_limit: 418
          - cmake_options: all-options-abiv2-preview
            warning_limit: 424
    env:
      CC: /usr/bin/clang-22
      CXX: /usr/bin/clang++-22
      CXX_STANDARD: '14' # Run clang-tidy on the minimum supported c++ standard
    steps:
      - name: Harden the runner (Audit all outbound calls)
        uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1
        with:
          egress-policy: audit

      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          submodules: recursive

      - name: Setup Environment
        run: |
          sudo apt update -y
          sudo apt install -y --no-install-recommends --no-install-suggests \
          build-essential \
          cmake \
          zlib1g-dev \
          libssl-dev \
          libcurl4-openssl-dev \
          nlohmann-json3-dev \
          libabsl-dev \
          libprotobuf-dev \
          libgrpc++-dev \
          protobuf-compiler \
          protobuf-compiler-grpc \
          libgmock-dev \
          libgtest-dev \
          libbenchmark-dev

      - name: Install clang-22 toolchain
        run: |
          wget -qO- https://apt.llvm.org/llvm.sh | sudo bash -s -- 22
          sudo apt install -y clang-22 clang-tidy-22
          sudo update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-22 200
          sudo update-alternatives --config clang-tidy
          echo "Using clang-tidy version: $(clang-tidy --version)"
          echo "clang-tidy installed at: $(which clang-tidy)"

      - name: Install rapidyaml
        run: |
          sudo -E ./ci/install_thirdparty.sh --install-dir /usr/local --tags-file third_party_release --packages "ryml"

      - name: Build and run clang-tidy
        id: build
        env:
          OTELCPP_CMAKE_CACHE_FILE: ${{ matrix.cmake_options }}.cmake
          BUILD_DIR: build-${{ matrix.cmake_options }}
        run: |
          ./ci/do_ci.sh cmake.clang_tidy.test
          echo "build_log=${BUILD_DIR}/opentelemetry-cpp-clang-tidy.log" >> "$GITHUB_OUTPUT"

      - name: Analyze clang-tidy output
        id: analyze
        run: |
          SCRIPT_OUTPUT=$(python3 ./ci/create_clang_tidy_report.py \
            --build_log ${{ steps.build.outputs.build_log }} \
            --output ./clang_tidy_report-${{ matrix.cmake_options }}.md)
          export $SCRIPT_OUTPUT
          echo "Found $TOTAL_WARNINGS unique warnings"
          echo "clang-tidy report generated at $REPORT_PATH"
          echo "warning_count=$TOTAL_WARNINGS" >> "$GITHUB_OUTPUT"
          echo "report_path=$REPORT_PATH" >> "$GITHUB_OUTPUT"
          cat $REPORT_PATH >> $GITHUB_STEP_SUMMARY

      - name: Upload build log
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
        with:
          name: Logs-clang-tidy-${{ matrix.cmake_options }}
          path: ${{ steps.build.outputs.build_log }}

      - name: Upload warning report
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
        with:
          name: Report-clang-tidy-${{ matrix.cmake_options }}
          path: ${{ steps.analyze.outputs.report_path }}

      - name: Check Warning Limits
        run: |
          readonly COUNT="${{ steps.analyze.outputs.warning_count }}"
          readonly LIMIT="${{ matrix.warning_limit }}"

          echo "clang-tidy reported ${COUNT} unique warning(s) with preset '${{ matrix.cmake_options }}'"
          echo "Limit is ${LIMIT}"

          if [ "$COUNT" -gt "$LIMIT" ]; then
            echo "::error::clang-tidy reported ${COUNT} warning(s) exceeding the limit of ${LIMIT}"
            exit 1
          elif [ "$COUNT" -gt 0 ]; then
            echo "::warning::clang-tidy reported ${COUNT} warning(s) within the limit of ${LIMIT}"
          fi

