| # Copyright 2026 The IREE Authors | |
| # | |
| # Licensed under the Apache License v2.0 with LLVM Exceptions. | |
| # See https://llvm.org/LICENSE.txt for license information. | |
| # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| # This workflow uses the newest clang-tidy binary built from source after the | |
| # latest integrate. This way we get the newest checks (incl., llvm-specific | |
| # ones). | |
| name: Clang Tidy | |
| on: | |
| pull_request: | |
| paths: | |
| - '**.h' | |
| - '**.c' | |
| - '**.cpp' | |
| - '.clang-tidy' | |
| - '.github/workflows/clang_tidy.yml' | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number }} | |
| cancel-in-progress: true | |
| jobs: | |
| clang-tidy: | |
| # Run expensive CI only for the lowest unmerged PR in a native stack. | |
| if: >- | |
| github.event.pull_request.stack == null || | |
| github.event.pull_request.stack.base.ref == github.event.pull_request.base.ref | |
| runs-on: ubuntu-24.04 | |
| container: | |
| image: ghcr.io/iree-org/cpubuilder_ubuntu_jammy@sha256:78a558b999b230f7e1da376639e14b44f095f30f1777d6a272ba48c0bbdd4ccb | |
| defaults: | |
| run: | |
| shell: bash | |
| env: | |
| BUILD_DIR: build | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| submodules: false | |
| fetch-depth: 0 | |
| - name: Initialize submodules | |
| run: | | |
| git config --global --add safe.directory "$GITHUB_WORKSPACE" | |
| git submodule update --init --depth=1 | |
| - name: Download iree-clang-tidy artifact | |
| uses: dawidd6/action-download-artifact@eab87c9830c39eff17e5a6eadb20bfb4bc880477 # v27 | |
| with: | |
| workflow: build_clang_tidy.yml | |
| name: iree-clang-tidy-linux-x86_64 | |
| path: .iree-clang-tidy | |
| - name: Setup iree-clang-tidy | |
| run: | | |
| # Make executable (artifact download doesn't preserve permissions). | |
| chmod +x .iree-clang-tidy/clang-tidy | |
| echo "Using clang-tidy from llvm-project revision:" | |
| cat .iree-clang-tidy/llvm-project-revision.txt | |
| .iree-clang-tidy/clang-tidy --version | |
| - name: Install Python requirements | |
| run: | | |
| # Use uv instead of plain pip since cpp-linter uses it anyway. | |
| curl -LsSf https://astral.sh/uv/install.sh | sh | |
| echo "$HOME/.local/bin" >> "$GITHUB_PATH" | |
| export PATH="$HOME/.local/bin:$PATH" | |
| uv pip install --system -r ./runtime/bindings/python/iree/runtime/build_requirements.txt | |
| uv pip install --system -r ./build_tools/github_actions/ci_requirements.txt | |
| - name: Generate compilation database (compile_commands.json) | |
| run: | | |
| IREE_CONFIGURE_ONLY=1 ./build_tools/cmake/build_all.sh "${BUILD_DIR}" | |
| - name: Select clang-tidy diff mode | |
| id: tidy-diff-mode | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| run: | | |
| status_code=$(curl -sS -o /tmp/pr.diff -w "%{http_code}" \ | |
| -H "Authorization: Bearer ${GITHUB_TOKEN}" \ | |
| -H "Accept: application/vnd.github.v3.diff" \ | |
| "${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}") | |
| if [[ "${status_code}" == "200" ]]; then | |
| echo "use_cpp_linter=true" >> "${GITHUB_OUTPUT}" | |
| else | |
| echo "GitHub PR diff request returned ${status_code}; running clang-tidy locally on changed files." | |
| echo "use_cpp_linter=false" >> "${GITHUB_OUTPUT}" | |
| fi | |
| - name: Run clang-tidy | |
| if: steps.tidy-diff-mode.outputs.use_cpp_linter == 'true' | |
| uses: cpp-linter/cpp-linter-action@8120e05c7fbd25fa09fa93424ec49f55f7b304ab # v1.11.4 | |
| id: linter | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| version: .iree-clang-tidy | |
| style: '' # Disable clang-format (already handled by pre-commit). | |
| tidy-checks: '' # Use .clang-tidy config files. | |
| database: ${{ env.BUILD_DIR }} | |
| files-changed-only: true | |
| lines-changed-only: diff | |
| ignore: 'third_party' | |
| thread-comments: false | |
| step-summary: true | |
| - name: Skip clang-tidy on large diff | |
| if: steps.tidy-diff-mode.outputs.use_cpp_linter == 'false' | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| run: | | |
| changed_files="${RUNNER_TEMP}/clang-tidy-changed-files.txt" | |
| git diff --name-only --diff-filter=ACMRT "${BASE_SHA}" "${HEAD_SHA}" \ | |
| | grep -E '\.(c|h|C|H|cpp|hpp|cc|hh|c\+\+|h\+\+|cxx|hxx)$' \ | |
| | grep -Ev '(^|/)third_party/' \ | |
| | sort -u > "${changed_files}" || true | |
| if [[ ! -s "${changed_files}" ]]; then | |
| echo "No changed C/C++ files found." | |
| exit 0 | |
| fi | |
| echo "::warning title=clang-tidy skipped::GitHub refused the PR diff because it exceeds the 20,000-line API limit, so cpp-linter cannot compute changed-line diagnostics for $(wc -l < "${changed_files}") changed C/C++ files." |