From 0595440685f9a01a25b6147150bcc284cf6be0ea Mon Sep 17 00:00:00 2001 From: Douglas Barker Date: Sun, 23 Nov 2025 17:37:50 -0500 Subject: [PATCH 1/6] upgrade to clang-tidy 20 --- .clang-tidy | 2 +- .devcontainer/Dockerfile.dev | 11 ++++++++--- .github/workflows/clang-tidy.yaml | 11 +++++------ ci/do_ci.sh | 4 +++- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 452fbaf014..599a02fd88 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -38,4 +38,4 @@ Checks: > -cppcoreguidelines-macro-usage, -cppcoreguidelines-non-private-member-variables-in-classes, -cppcoreguidelines-avoid-non-const-global-variables, - -cppcoreguidelines-pro-* \ No newline at end of file + -cppcoreguidelines-pro-* diff --git a/.devcontainer/Dockerfile.dev b/.devcontainer/Dockerfile.dev index 60efed9723..fec4e16c6a 100644 --- a/.devcontainer/Dockerfile.dev +++ b/.devcontainer/Dockerfile.dev @@ -15,13 +15,18 @@ COPY ci /opt/ci RUN apt update && apt install -y wget \ ninja-build \ - llvm-dev \ - libclang-dev \ - clang-tidy \ + llvm-20-dev \ + libclang-20-dev \ + clang-tidy-20 \ shellcheck \ sudo \ cmake +RUN update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-20 200 && \ + update-alternatives --install /usr/bin/llvm-config llvm-config /usr/bin/llvm-config-20 200 && \ + update-alternatives --config clang-tidy && \ + update-alternatives --config llvm-config + RUN cd /opt/ci && bash setup_ci_environment.sh RUN cd /opt/ci && bash install_iwyu.sh diff --git a/.github/workflows/clang-tidy.yaml b/.github/workflows/clang-tidy.yaml index 16623b4b28..1a7d6f8c85 100644 --- a/.github/workflows/clang-tidy.yaml +++ b/.github/workflows/clang-tidy.yaml @@ -53,12 +53,11 @@ jobs: run: | sudo -E ./ci/install_thirdparty.sh --install-dir /usr/local --tags-file third_party_release --packages "ryml" - - name: Check clang-tidy + - name: Install clang-tidy-20 run: | - if ! command -v clang-tidy &> /dev/null; then - echo "clang-tidy could not be found" - exit 1 - fi + sudo apt install -y clang-tidy-20 + sudo update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-20 200 + sudo update-alternatives --config clang-tidy echo "Using clang-tidy version: $(clang-tidy --version)" echo "clang-tidy installed at: $(which clang-tidy)" @@ -75,7 +74,7 @@ jobs: -DWITH_OPENTRACING=OFF \ -DCMAKE_CXX_FLAGS="-Wno-deprecated-declarations" \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DCMAKE_CXX_CLANG_TIDY="clang-tidy;--quiet;-p;build-${{ matrix.cmake_options }}" + -DCMAKE_CXX_CLANG_TIDY="clang-tidy;--header-filter=.*;--exclude-header-filter=.*internal/absl/.*;--quiet" - name: Run clang-tidy run: | diff --git a/ci/do_ci.sh b/ci/do_ci.sh index ddeffe74da..0c609a8afb 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -342,6 +342,8 @@ elif [[ "$1" == "cmake.clang_tidy.test" ]]; then cd "${BUILD_DIR}" rm -rf * export BUILD_ROOT="${BUILD_DIR}" + clang-tidy --version + cmake -S ${SRC_DIR} \ -B ${BUILD_DIR} \ -C ${SRC_DIR}/test_common/cmake/all-options-abiv2-preview.cmake \ @@ -349,7 +351,7 @@ elif [[ "$1" == "cmake.clang_tidy.test" ]]; then -DWITH_OPENTRACING=OFF \ -DCMAKE_CXX_FLAGS="-Wno-deprecated-declarations" \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DCMAKE_CXX_CLANG_TIDY="clang-tidy;--quiet;-p;${BUILD_DIR}" + -DCMAKE_CXX_CLANG_TIDY="clang-tidy;--header-filter=.*;--exclude-header-filter=.*internal/absl/.*;--quiet" make -j $(nproc) make test exit 0 From 3de21e8cbfe8fcdd9e1509e33879f61b54517af4 Mon Sep 17 00:00:00 2001 From: Douglas Barker Date: Mon, 24 Nov 2025 00:34:22 -0500 Subject: [PATCH 2/6] add python script to create a markdown report for clang-tidy warnings. Filter out generated third-party headers --- .github/workflows/clang-tidy.yaml | 58 +++++++--- ci/create_clang_tidy_report.py | 172 ++++++++++++++++++++++++++++++ ci/do_ci.sh | 13 ++- 3 files changed, 223 insertions(+), 20 deletions(-) create mode 100644 ci/create_clang_tidy_report.py diff --git a/.github/workflows/clang-tidy.yaml b/.github/workflows/clang-tidy.yaml index 1a7d6f8c85..2f5f99ef13 100644 --- a/.github/workflows/clang-tidy.yaml +++ b/.github/workflows/clang-tidy.yaml @@ -67,37 +67,63 @@ jobs: CXX: clang++ run: | echo "Running cmake..." - cmake -B build-${{ matrix.cmake_options }} \ + cmake + -S . \ + -B build-${{ matrix.cmake_options }} \ -C ./test_common/cmake/${{ matrix.cmake_options }}.cmake \ -DCMAKE_CXX_STANDARD=14 \ -DWITH_STL=CXX14 \ -DWITH_OPENTRACING=OFF \ -DCMAKE_CXX_FLAGS="-Wno-deprecated-declarations" \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DCMAKE_CXX_CLANG_TIDY="clang-tidy;--header-filter=.*;--exclude-header-filter=.*internal/absl/.*;--quiet" + -DCMAKE_CXX_CLANG_TIDY="clang-tidy;--header-filter=.*/opentelemetry-cpp/.*;--exclude-header-filter=.*(internal/absl|third_party|third-party)/.*;--quiet" - - name: Run clang-tidy + - name: Run clang-tidy and Build + id: build run: | - cmake --build build-${{ matrix.cmake_options }} -- -j$(nproc) 2>&1 | tee clang-tidy-${{ matrix.cmake_options }}.log + BUILD_LOG=clang-tidy-${{ matrix.cmake_options }}.log + set -o pipefail + cmake --build build-${{ matrix.cmake_options }} -- -j$(nproc) 2>&1 | tee $BUILD_LOG + echo "build_log=$BUILD_LOG" >> "$GITHUB_OUTPUT" - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + - name: Analyze clang-tidy build log + id: analyze + run: | + SCRIPT_OUTPUT=$(python3 ./ci/create_clang_tidy_report.py \ + --job_name ${{ matrix.cmake_options }} \ + --build_log clang-tidy-${{ matrix.cmake_options }}.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: ./clang-tidy-${{ matrix.cmake_options }}.log + 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: Count warnings + - name: Check Warning Limits run: | - COUNT=$(grep -c "warning:" clang-tidy-${{ matrix.cmake_options }}.log) - echo "clang-tidy reported ${COUNT} warning(s) with cmake options preset '${{ matrix.cmake_options }}'" + readonly COUNT="${{ steps.analyze.outputs.warning_count }}" + readonly LIMIT="${{ matrix.warning_limit }}" - readonly WARNING_LIMIT=${{ matrix.warning_limit }} + echo "clang-tidy reported ${COUNT} unique warning(s) with preset '${{ matrix.cmake_options }}'" + echo "Limit is ${LIMIT}" - # FAIL the build if COUNT > WARNING_LIMIT - if [ $COUNT -gt $WARNING_LIMIT ] ; then - echo "clang-tidy reported ${COUNT} warning(s) exceeding the existing warning limit of ${WARNING_LIMIT} with cmake options preset '${{ matrix.cmake_options }}'" + if [ "$COUNT" -gt "$LIMIT" ]; then + echo "::error::clang-tidy reported ${COUNT} warning(s) exceeding the limit of ${LIMIT}" exit 1 - # WARN in annotations if COUNT > 0 - elif [ $COUNT -gt 0 ] ; then - echo "::warning::clang-tidy reported ${COUNT} warning(s) with cmake options preset '${{ matrix.cmake_options }}'" + elif [ "$COUNT" -gt 0 ]; then + echo "::warning::clang-tidy reported ${COUNT} warning(s) within the limit of ${LIMIT}" fi diff --git a/ci/create_clang_tidy_report.py b/ci/create_clang_tidy_report.py new file mode 100644 index 0000000000..c66840b09a --- /dev/null +++ b/ci/create_clang_tidy_report.py @@ -0,0 +1,172 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +import argparse +import re +import sys +from collections import defaultdict +from enum import Enum +from pathlib import Path +from typing import Dict, List, NamedTuple, Optional, Set + +# --- Configuration --- +REPO_NAME = "opentelemetry-cpp" +MAX_ROWS = 1000 +WARNING_RE = re.compile( + r"^(?P.+):(?P\d+):(?P\d+): warning: (?P.+) " + r"\[(?P.+)\]$" +) +ANSI_RE = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])") + + +class OutputKeys(str, Enum): + TOTAL_WARNINGS = "TOTAL_WARNINGS" + REPORT_PATH = "REPORT_PATH" + + +class ClangTidyWarning(NamedTuple): + file: str + line: int + col: int + msg: str + check: str + + +def clean_path(path: str) -> str: + """Strip path prefix to make it relative to the repo or CWD.""" + if f"{REPO_NAME}/" in path: + return path.split(f"{REPO_NAME}/", 1)[1] + try: + return str(Path(path).relative_to(Path.cwd())) + except ValueError: + return path + + +def parse_log(log_path: Path) -> Set[ClangTidyWarning]: + if not log_path.exists(): + sys.exit(f"[ERROR] Log not found: {log_path}") + unique = set() + with log_path.open("r", encoding="utf-8", errors="replace") as f: + for line in f: + line = ANSI_RE.sub("", line.strip()) + if "warning:" not in line: + continue + match = WARNING_RE.match(line) + if match: + unique.add( + ClangTidyWarning( + clean_path(match.group("file")), + int(match.group("line")), + int(match.group("col")), + match.group("msg"), + match.group("check"), + ) + ) + return unique + + +def generate_report( + warnings: Set[ClangTidyWarning], + output_path: Path, + job_name: Optional[str] = None, +): + by_check: Dict[str, List[ClangTidyWarning]] = defaultdict(list) + by_file: Dict[str, List[ClangTidyWarning]] = defaultdict(list) + + for w in warnings: + by_check[w.check].append(w) + by_file[w.file].append(w) + + with output_path.open("w", encoding="utf-8") as md: + title = "# " + if job_name: + title += f"{job_name}" + + md.write( + f"{title} `clang-tidy` job \t[**{len(warnings)} warnings**]\n\n" + ) + md.write(f"
{'Warnings breakdown'} - Click to expand\n\n") + + def write_section( + title, data, item_sort_key, header, row_fmt, group_key, reverse + ): + md.write(f"## {title}\n") + sorted_groups = sorted( + data.items(), key=group_key, reverse=reverse + ) + for key, items in sorted_groups: + md.write( + f"
{key} ({len(items)})" + f"\n\n{header}\n" + ) + for i, w in enumerate(sorted(items, key=item_sort_key)): + if i >= MAX_ROWS: + remaining = len(items) - i + md.write( + f"| ... | ... | *{remaining} more omitted...* |\n" + ) + break + md.write(row_fmt(w) + "\n") + md.write("\n
\n\n") + + # Warnings by File: Sorted Alphabetically + write_section( + "Warnings by File", + by_file, + item_sort_key=lambda w: w.line, + header="| Line | Check | Message |\n|---|---|---|", + row_fmt=lambda w: f"| {w.line} | `{w.check}` | {w.msg} |", + group_key=lambda x: x[0], + reverse=False, + ) + + # Warnings by clang-tidy check: Sort by Warning count + write_section( + "Warnings by `clang-tidy` Check", + by_check, + item_sort_key=lambda w: (w.file, w.line), + header="| File | Line | Message |\n|---|---|---|", + row_fmt=lambda w: f"| `{w.file}` | {w.line} | {w.msg} |", + group_key=lambda x: len(x[1]), + reverse=True, + ) + + md.write(f"
\n") + md.write("\n----\n") + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "-l", + "--build_log", + type=Path, + required=True, + help="Clang-tidy log file", + ) + parser.add_argument( + "-o", + "--output", + type=Path, + default="clang_tidy_report.md", + help="Output report path", + ) + parser.add_argument( + "-j", + "--job_name", + type=str, + help="Job name to include in the report title", + ) + args = parser.parse_args() + + warnings = parse_log(args.build_log) + generate_report(warnings, args.output, args.job_name) + + sys.stdout.write(f"{OutputKeys.TOTAL_WARNINGS.value}={len(warnings)}\n") + if args.output.exists(): + sys.stdout.write(f"{OutputKeys.REPORT_PATH.value}={args.output.resolve()}\n") + else: + sys.exit(f"[ERROR] Failed to write report: {args.output.resolve()}") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/ci/do_ci.sh b/ci/do_ci.sh index 0c609a8afb..714a284f89 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -341,9 +341,8 @@ elif [[ "$1" == "cmake.legacy.test" ]]; then elif [[ "$1" == "cmake.clang_tidy.test" ]]; then cd "${BUILD_DIR}" rm -rf * - export BUILD_ROOT="${BUILD_DIR}" clang-tidy --version - + LOG_FILE="${BUILD_DIR}/opentelemetry-cpp-clang-tidy.log" cmake -S ${SRC_DIR} \ -B ${BUILD_DIR} \ -C ${SRC_DIR}/test_common/cmake/all-options-abiv2-preview.cmake \ @@ -351,9 +350,15 @@ elif [[ "$1" == "cmake.clang_tidy.test" ]]; then -DWITH_OPENTRACING=OFF \ -DCMAKE_CXX_FLAGS="-Wno-deprecated-declarations" \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DCMAKE_CXX_CLANG_TIDY="clang-tidy;--header-filter=.*;--exclude-header-filter=.*internal/absl/.*;--quiet" - make -j $(nproc) + -DCMAKE_CXX_CLANG_TIDY="clang-tidy;--header-filter=.*/opentelemetry-cpp/.*;--exclude-header-filter=.*(internal/absl|third_party|third-party)/.*;--quiet" + make -j $(nproc) 2>&1 | tee "$LOG_FILE" make test + SCRIPT_OUTPUT=$(python3 ${SRC_DIR}/ci/create_clang_tidy_report.py \ + --build_log "$LOG_FILE" \ + --output clang_tidy_report.md) + export $SCRIPT_OUTPUT + echo "total warnings = $TOTAL_WARNINGS" + echo "clang-tidy report generated at $REPORT_PATH" exit 0 elif [[ "$1" == "cmake.legacy.exporter.otprotocol.test" ]]; then cd "${BUILD_DIR}" From 4dc631accd02ef4e296728cec7debd478eeb7ae8 Mon Sep 17 00:00:00 2001 From: Douglas Barker Date: Mon, 24 Nov 2025 00:39:05 -0500 Subject: [PATCH 3/6] ci fix --- .github/workflows/clang-tidy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/clang-tidy.yaml b/.github/workflows/clang-tidy.yaml index 2f5f99ef13..8d41e58c24 100644 --- a/.github/workflows/clang-tidy.yaml +++ b/.github/workflows/clang-tidy.yaml @@ -67,7 +67,7 @@ jobs: CXX: clang++ run: | echo "Running cmake..." - cmake + cmake \ -S . \ -B build-${{ matrix.cmake_options }} \ -C ./test_common/cmake/${{ matrix.cmake_options }}.cmake \ From 01e7425799d4403daa1309fe06bb62e228e2cd33 Mon Sep 17 00:00:00 2001 From: Douglas Barker Date: Sun, 14 Dec 2025 13:43:49 -0500 Subject: [PATCH 4/6] update report format and clang-tidy header regex exclusions --- .github/workflows/clang-tidy.yaml | 3 ++- ci/create_clang_tidy_report.py | 37 +++++++++++++++++++++++-------- ci/do_ci.sh | 3 ++- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/.github/workflows/clang-tidy.yaml b/.github/workflows/clang-tidy.yaml index 8d41e58c24..b9f4da77ae 100644 --- a/.github/workflows/clang-tidy.yaml +++ b/.github/workflows/clang-tidy.yaml @@ -61,6 +61,7 @@ jobs: echo "Using clang-tidy version: $(clang-tidy --version)" echo "clang-tidy installed at: $(which clang-tidy)" + # Note - if the --header-filter or --exclude-header-filter are modified please also modify the ci/do_ci.sh cmake.clang_tidy command to match - name: Prepare CMake env: CC: clang @@ -76,7 +77,7 @@ jobs: -DWITH_OPENTRACING=OFF \ -DCMAKE_CXX_FLAGS="-Wno-deprecated-declarations" \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DCMAKE_CXX_CLANG_TIDY="clang-tidy;--header-filter=.*/opentelemetry-cpp/.*;--exclude-header-filter=.*(internal/absl|third_party|third-party)/.*;--quiet" + -DCMAKE_CXX_CLANG_TIDY="clang-tidy;--header-filter=.*/opentelemetry-cpp/.*;--exclude-header-filter=.*(internal/absl|third_party|third-party|/usr/|/opt/|.*\.pb\.h|.*\.pb\.cc)/.*;--quiet" - name: Run clang-tidy and Build id: build diff --git a/ci/create_clang_tidy_report.py b/ci/create_clang_tidy_report.py index c66840b09a..044b264ceb 100644 --- a/ci/create_clang_tidy_report.py +++ b/ci/create_clang_tidy_report.py @@ -78,26 +78,43 @@ def generate_report( by_file[w.file].append(w) with output_path.open("w", encoding="utf-8") as md: - title = "# " + title = "### " if job_name: title += f"{job_name}" md.write( f"{title} `clang-tidy` job \t[**{len(warnings)} warnings**]\n\n" ) - md.write(f"
{'Warnings breakdown'} - Click to expand\n\n") def write_section( - title, data, item_sort_key, header, row_fmt, group_key, reverse + title, + data, + item_sort_key, + header, + row_fmt, + group_key, + reverse, + summary_col_name, ): - md.write(f"## {title}\n") + md.write(f"
{title} - Click to expand \n\n") sorted_groups = sorted( data.items(), key=group_key, reverse=reverse ) + + # Summary Table (Sorted by Count Descending) + summary_groups = sorted( + data.items(), key=lambda x: len(x[1]), reverse=True + ) + md.write("#### Summary\n\n") + md.write(f"| {summary_col_name} | Count |\n|---|---|\n") + for key, items in summary_groups: + md.write(f"| {key} | {len(items)} |\n") + md.write("\n") + + md.write("#### Details\n\n") for key, items in sorted_groups: md.write( - f"
{key} ({len(items)})" - f"\n\n{header}\n" + f"\n----\n\n**{key}** ({len(items)} warnings)\n\n{header}\n" ) for i, w in enumerate(sorted(items, key=item_sort_key)): if i >= MAX_ROWS: @@ -107,7 +124,8 @@ def write_section( ) break md.write(row_fmt(w) + "\n") - md.write("\n
\n\n") + md.write("\n") + md.write("
\n\n") # Warnings by File: Sorted Alphabetically write_section( @@ -118,20 +136,21 @@ def write_section( row_fmt=lambda w: f"| {w.line} | `{w.check}` | {w.msg} |", group_key=lambda x: x[0], reverse=False, + summary_col_name="File", ) # Warnings by clang-tidy check: Sort by Warning count write_section( - "Warnings by `clang-tidy` Check", + "Warnings by clang-tidy Check", by_check, item_sort_key=lambda w: (w.file, w.line), header="| File | Line | Message |\n|---|---|---|", row_fmt=lambda w: f"| `{w.file}` | {w.line} | {w.msg} |", group_key=lambda x: len(x[1]), reverse=True, + summary_col_name="Check", ) - md.write(f"
\n") md.write("\n----\n") diff --git a/ci/do_ci.sh b/ci/do_ci.sh index 714a284f89..2943eab00f 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -339,6 +339,7 @@ elif [[ "$1" == "cmake.legacy.test" ]]; then make test exit 0 elif [[ "$1" == "cmake.clang_tidy.test" ]]; then + # Note - if the --header-filter or --exclude-header-filter are modified please also modify the clang-tidy github workflow file (.github/workflows/clang-tidy.yaml) to match cd "${BUILD_DIR}" rm -rf * clang-tidy --version @@ -350,7 +351,7 @@ elif [[ "$1" == "cmake.clang_tidy.test" ]]; then -DWITH_OPENTRACING=OFF \ -DCMAKE_CXX_FLAGS="-Wno-deprecated-declarations" \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DCMAKE_CXX_CLANG_TIDY="clang-tidy;--header-filter=.*/opentelemetry-cpp/.*;--exclude-header-filter=.*(internal/absl|third_party|third-party)/.*;--quiet" + -DCMAKE_CXX_CLANG_TIDY="clang-tidy;--header-filter=.*/opentelemetry-cpp/.*;--exclude-header-filter=.*(internal/absl|third_party|third-party|/usr/|/opt/|.*\.pb\.h|.*\.pb\.cc)/.*;--quiet" make -j $(nproc) 2>&1 | tee "$LOG_FILE" make test SCRIPT_OUTPUT=$(python3 ${SRC_DIR}/ci/create_clang_tidy_report.py \ From 719584011b6dd7653ec1e9986e60a30b100f3b90 Mon Sep 17 00:00:00 2001 From: Douglas Barker Date: Sun, 14 Dec 2025 18:47:29 -0500 Subject: [PATCH 5/6] call the ci/do_ci.sh cmake.clang_tidy.test command in the github clang-tidy workflow --- .github/workflows/clang-tidy.yaml | 42 +++++++++++-------------------- ci/create_clang_tidy_report.py | 19 +++++--------- ci/do_ci.sh | 35 +++++++++++++++----------- 3 files changed, 40 insertions(+), 56 deletions(-) diff --git a/.github/workflows/clang-tidy.yaml b/.github/workflows/clang-tidy.yaml index b9f4da77ae..b444a313aa 100644 --- a/.github/workflows/clang-tidy.yaml +++ b/.github/workflows/clang-tidy.yaml @@ -17,9 +17,13 @@ jobs: matrix: include: - cmake_options: all-options-abiv1-preview - warning_limit: 63 + warning_limit: 581 - cmake_options: all-options-abiv2-preview - warning_limit: 63 + warning_limit: 583 + env: + CC: /usr/bin/clang-18 + CXX: /usr/bin/clang++-18 + 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@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 @@ -61,38 +65,20 @@ jobs: echo "Using clang-tidy version: $(clang-tidy --version)" echo "clang-tidy installed at: $(which clang-tidy)" - # Note - if the --header-filter or --exclude-header-filter are modified please also modify the ci/do_ci.sh cmake.clang_tidy command to match - - name: Prepare CMake - env: - CC: clang - CXX: clang++ - run: | - echo "Running cmake..." - cmake \ - -S . \ - -B build-${{ matrix.cmake_options }} \ - -C ./test_common/cmake/${{ matrix.cmake_options }}.cmake \ - -DCMAKE_CXX_STANDARD=14 \ - -DWITH_STL=CXX14 \ - -DWITH_OPENTRACING=OFF \ - -DCMAKE_CXX_FLAGS="-Wno-deprecated-declarations" \ - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DCMAKE_CXX_CLANG_TIDY="clang-tidy;--header-filter=.*/opentelemetry-cpp/.*;--exclude-header-filter=.*(internal/absl|third_party|third-party|/usr/|/opt/|.*\.pb\.h|.*\.pb\.cc)/.*;--quiet" - - - name: Run clang-tidy and Build + - name: Build and run clang-tidy id: build + env: + OTELCPP_CMAKE_CACHE_FILE: ${{ matrix.cmake_options }}.cmake + BUILD_DIR: build-${{ matrix.cmake_options }} run: | - BUILD_LOG=clang-tidy-${{ matrix.cmake_options }}.log - set -o pipefail - cmake --build build-${{ matrix.cmake_options }} -- -j$(nproc) 2>&1 | tee $BUILD_LOG - echo "build_log=$BUILD_LOG" >> "$GITHUB_OUTPUT" + ./ci/do_ci.sh cmake.clang_tidy.test + echo "build_log=${BUILD_DIR}/opentelemetry-cpp-clang-tidy.log" >> "$GITHUB_OUTPUT" - - name: Analyze clang-tidy build log + - name: Analyze clang-tidy output id: analyze run: | SCRIPT_OUTPUT=$(python3 ./ci/create_clang_tidy_report.py \ - --job_name ${{ matrix.cmake_options }} \ - --build_log clang-tidy-${{ matrix.cmake_options }}.log \ + --build_log ${{ steps.build.outputs.build_log }} \ --output ./clang_tidy_report-${{ matrix.cmake_options }}.md) export $SCRIPT_OUTPUT echo "Found $TOTAL_WARNINGS unique warnings" diff --git a/ci/create_clang_tidy_report.py b/ci/create_clang_tidy_report.py index 044b264ceb..dc8ae0a0f6 100644 --- a/ci/create_clang_tidy_report.py +++ b/ci/create_clang_tidy_report.py @@ -68,7 +68,6 @@ def parse_log(log_path: Path) -> Set[ClangTidyWarning]: def generate_report( warnings: Set[ClangTidyWarning], output_path: Path, - job_name: Optional[str] = None, ): by_check: Dict[str, List[ClangTidyWarning]] = defaultdict(list) by_file: Dict[str, List[ClangTidyWarning]] = defaultdict(list) @@ -78,14 +77,14 @@ def generate_report( by_file[w.file].append(w) with output_path.open("w", encoding="utf-8") as md: - title = "### " - if job_name: - title += f"{job_name}" - + title = "#### " md.write( - f"{title} `clang-tidy` job \t[**{len(warnings)} warnings**]\n\n" + f"{title} `clang-tidy` job reported {len(warnings)} warnings\n\n" ) + if not warnings: + return + def write_section( title, data, @@ -170,16 +169,10 @@ def main(): default="clang_tidy_report.md", help="Output report path", ) - parser.add_argument( - "-j", - "--job_name", - type=str, - help="Job name to include in the report title", - ) args = parser.parse_args() warnings = parse_log(args.build_log) - generate_report(warnings, args.output, args.job_name) + generate_report(warnings, args.output) sys.stdout.write(f"{OutputKeys.TOTAL_WARNINGS.value}={len(warnings)}\n") if args.output.exists(): diff --git a/ci/do_ci.sh b/ci/do_ci.sh index 2943eab00f..eaea9e9643 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -106,6 +106,12 @@ if [ -n "$CMAKE_TOOLCHAIN_FILE" ]; then CMAKE_OPTIONS+=("-DCMAKE_TOOLCHAIN_FILE=$CMAKE_TOOLCHAIN_FILE") fi +if [ -n "$OTELCPP_CMAKE_CACHE_FILE" ]; then + OTELCPP_CMAKE_CACHE_FILE_PATH="${SRC_DIR}/test_common/cmake/${OTELCPP_CMAKE_CACHE_FILE}" +else + OTELCPP_CMAKE_CACHE_FILE_PATH="${SRC_DIR}/test_common/cmake/all-options-abiv1-preview.cmake" +fi + echo "CMAKE_OPTIONS:" "${CMAKE_OPTIONS[@]}" export CTEST_OUTPUT_ON_FAILURE=1 @@ -339,27 +345,26 @@ elif [[ "$1" == "cmake.legacy.test" ]]; then make test exit 0 elif [[ "$1" == "cmake.clang_tidy.test" ]]; then - # Note - if the --header-filter or --exclude-header-filter are modified please also modify the clang-tidy github workflow file (.github/workflows/clang-tidy.yaml) to match - cd "${BUILD_DIR}" - rm -rf * + rm -rf "${BUILD_DIR}" + mkdir -p "${BUILD_DIR}" clang-tidy --version LOG_FILE="${BUILD_DIR}/opentelemetry-cpp-clang-tidy.log" - cmake -S ${SRC_DIR} \ + cmake "${CMAKE_OPTIONS[@]}" \ + -S ${SRC_DIR} \ -B ${BUILD_DIR} \ - -C ${SRC_DIR}/test_common/cmake/all-options-abiv2-preview.cmake \ - "${CMAKE_OPTIONS[@]}" \ + -C ${OTELCPP_CMAKE_CACHE_FILE_PATH} \ -DWITH_OPENTRACING=OFF \ -DCMAKE_CXX_FLAGS="-Wno-deprecated-declarations" \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DCMAKE_CXX_CLANG_TIDY="clang-tidy;--header-filter=.*/opentelemetry-cpp/.*;--exclude-header-filter=.*(internal/absl|third_party|third-party|/usr/|/opt/|.*\.pb\.h|.*\.pb\.cc)/.*;--quiet" - make -j $(nproc) 2>&1 | tee "$LOG_FILE" - make test - SCRIPT_OUTPUT=$(python3 ${SRC_DIR}/ci/create_clang_tidy_report.py \ - --build_log "$LOG_FILE" \ - --output clang_tidy_report.md) - export $SCRIPT_OUTPUT - echo "total warnings = $TOTAL_WARNINGS" - echo "clang-tidy report generated at $REPORT_PATH" + -DCMAKE_CXX_CLANG_TIDY="clang-tidy;--header-filter=.*/opentelemetry-cpp/.*;--exclude-header-filter=.*(internal/absl|third_party|third-party|build.*|/usr|/opt)/.*|.*\.pb\.h;--quiet" + cmake --build "${BUILD_DIR}" -- -j $(nproc) 2>&1 | tee "$LOG_FILE" + if [ ! -s "$LOG_FILE" ]; then + echo "Error: Build log was not created at $LOG_FILE" + exit 1 + fi + echo "Build log written to: $LOG_FILE" + echo "To generate a clang-tidy report, use the following command:" + echo " python3 ./ci/create_clang_tidy_report.py --build_log $LOG_FILE" exit 0 elif [[ "$1" == "cmake.legacy.exporter.otprotocol.test" ]]; then cd "${BUILD_DIR}" From be9b574845f0c39edee4a57d9c19deb235bbf619 Mon Sep 17 00:00:00 2001 From: Douglas Barker Date: Mon, 15 Dec 2025 00:42:40 +0000 Subject: [PATCH 6/6] set warning limits --- .github/workflows/clang-tidy.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/clang-tidy.yaml b/.github/workflows/clang-tidy.yaml index b444a313aa..127387ec7e 100644 --- a/.github/workflows/clang-tidy.yaml +++ b/.github/workflows/clang-tidy.yaml @@ -17,9 +17,9 @@ jobs: matrix: include: - cmake_options: all-options-abiv1-preview - warning_limit: 581 + warning_limit: 595 - cmake_options: all-options-abiv2-preview - warning_limit: 583 + warning_limit: 597 env: CC: /usr/bin/clang-18 CXX: /usr/bin/clang++-18