Repository navigation
Run clang-tidy only on changed lines in CI - #3980
Merged
Merged
Conversation
Move the clang-tidy-check logic into tools/scripts/run_clang_tidy.py so it can also run locally. Only lines added or modified by the PR are reported, and only files with a real compile command are analyzed: BUILD_ONLY adds the services whose tests or libraries changed, and CMake is configured with tests on and unity builds off.
This reverts commit 1b8549a.
Madrigal
marked this pull request as ready for review
November 5, 2026 21:05
sbiscigl
approved these changes
Nov 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue #, if available:
Description of changes:
clang-tidy-checkcurrently fails on almost every PR (about 28 of the last 34 runs), mostly for reasons that have nothing to do with the PR. Because the check is always red, real issues get merged unnoticed. This PR makes it report only problems on lines the PR adds or modifies, and only on files it can actually compile.Why it fails today
clang-tidyon every changed file in full, so olderperformance-*warnings anywhere in a touched file fail the job.-DBUILD_ONLY="s3" -DENABLE_TESTING=OFF. Test files and services other than s3 then have no compile command, so clang-tidy guesses flags and fails on missing includes (aws/testing/AwsCppSdkGTestSuite.h,gtest/gtest.hnot found). No line filter can suppress those compiler errors.ub_core.cpp, so those files have no compile command of their own.origin/<head branch>, which doesn't exist for PRs from forks.Real issues that were merged
Since the check was added in #3753, 11 merged PRs introduced 29
performance-*errors on lines they added. The check was red on those PRs too, but that was indistinguishable from the usual noise. Some examples:performance-move-const-arg,performance-unnecessary-value-params3-transfer:DownloadRequest.cpp,UploadRequest.cpp,S3TransferManager.cppperformance-unnecessary-copy-initializationClientProtocolTest.cpp:40,CodecTest.cpp(5)performance-move-const-arg(std::moveon a trivially-copyableDateTime)smithy/client/schema/Document.cpp:154,:253performance-unnecessary-value-paramBucketAndObjectOperationTest.cpp:1575(s3-crt integration tests)performance-unnecessary-value-paramcore/source/client/RetryStrategy.cpp:113The others are #3844, #3919, #3916, #3895, #3884 and #3849. The new check flags all 29 errors. Fixing the existing ones is out of scope here; the point is that new ones will now be visible.
What changes
The logic moves out of the workflow into
tools/scripts/run_clang_tidy.py, which also runs locally. The workflow now just checks out, installs dependencies, and calls the script. The script:BUILD_ONLY:s3, plus any service whose tests or high-level library the PR touches, plus that service's test dependencies. It reads these from the existing lists incmake/sdksCommon.cmake(SDK_TEST_PROJECT_LIST,TEST_DEPENDENCY_LIST). For example, Fix S3 CRT async request lifetime #3945 configuress3;s3-crt, so its s3-crt test is analyzed instead of skipped..cppfile (as in TM Header Update #3844).clang-tidywith-line-filterset to the PR's added or modified lines, so only diagnostics on those lines are reported. The script builds the line filter from the diff itself instead of using LLVM'sclang-tidy-diff.py, so theclang-tidybinary is the only dependency. Whether and whereclang-tidy-diff.pyis installed differs between apt, Homebrew and pip packages..clang-tidyis unchanged and still decides what's an error (WarningsAsErrors: 'performance-*'). Making more checks blocking later is a one-line.clang-tidychange.CONTRIBUTING.mdgets a "Checking Your Changes Locally" section with the steps below, plus a PR checklist item.Security
pull_request, withcontents: readand no secrets, same as before. A separate security review found no new risk above Low.::stop-commands::), so it can't inject workflow commands. File lists are prefixed so a crafted file name can't start a command line. Only real diagnostics inside the repo become annotations.How this was tested
All runs were local (macOS, clang-tidy 21.1.6), on full source trees extracted from git, using the same CMake configure the workflow runs.
clang-tidyon each whole checked file with the same compile flags, and kept only errors on lines the PR added. The script's results matched exactly in 54 of 55 runs, with nothing missed and nothing extra. In TM Header Update #3844 the script reported two more errors than the cross-check. They're in new headers, and clang-tidy attaches them to destructor definitions on.cpplines the PR added. That's correct behavior; the cross-check only looked at errors located in the.cppitself.bugprone-narrowing-conversionsfix. The warnings show up on the changed lines and don't block, as.clang-tidyspecifies.performance-*errors remain in both, matching the merged state.Aws::Stringparameter toDateTimeCommon.cppproducedperformance-unnecessary-value-paramand a non-zero exit.::add-mask::/::warninglines, spoofederror:lines in code snippets, and an out-of-repo path. Only the real diagnostic was annotated, and everything else stayed inside the paused region.clang-tidy-diff.py. After switching to building-line-filteritself, Fix S3 CRT async request lifetime #3945, TM Header Update #3844, Single File Upload/Download #3866, Make CognitoCachingCredentialsProviderTest work with both JSON and RPC v2 CBOR #3958, JSON number parsing bug fix #3921 and Validate event stream header name and value lengths when encoding #3962 report exactly the same errors as before.pip install clang-tidy(23.1.4) and the script run with no flags on Fix S3 CRT async request lifetime #3945. It found the same error, and no system-header errors on macOS.CONTRIBUTING.md: in a git checkout of this branch on macOS, where the only thing installed beyond the existinggit/cmake/python3waspip install clang-tidy,python3 tools/scripts/run_clang_tidy.pyran end to end in about a minute. With a temporary by-valueAws::Stringparameter added toDateTimeCommon.cpp, it reportedperformance-unnecessary-value-paramon that line and exited 1.Running locally
From the repo root, with submodules checked out:
Needs
git,cmakeandclang-tidy. On macOS the script passes the SDK path (xcrun --show-sdk-path) to clang-tidy itself, so no extra flags are needed. CI installs whateverclang-tidytheubuntu-latestimage provides, so a local version can differ slightly in which diagnostics it reports.Known limitations
workflow_dispatchruns are now a no-op.Check all that applies:
Check which platforms you have built SDK on to verify the correctness of this PR.
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.