CI: clang-tidy static analysis + flash-size budget gate - #35
Merged
Conversation
Two CI tooling additions toward the 8/10 bar:
clang-tidy (.clang-tidy + .github/workflows/clang-tidy.yml)
Runs bugprone/performance/portability/misc/clang-analyzer families
with WarningsAsErrors against the five host-buildable pure-logic
units, using the test build's compile_commands.json for exact
flags. HeaderFilterRegex scopes diagnostics to BirdsEye/*.h so
doctest and system headers stay quiet (~15k third-party warnings
suppressed, 0 in our code). The one real hit — an intentional
non-null-terminated memcpy in dovex_header's fixed-layout buffer
builder — is suppressed inline with a NOLINT + reason rather than
by disabling the check everywhere.
flash-size budget gate (compile-sketch.yml)
After compiling, parses the arduino/compile-sketches report and
fails the build if flash usage exceeds 90% of the BSP-reported
maximum. Uses absolute usage (no base-branch compare needed),
handles both report schema variants (absolute as number or as
{current}), and degrades to a warning if the report can't be
parsed. The XIAO shares app flash with the SoftDevice + bootloader,
so running it dry breaks OTA — this catches runaway growth before
it bricks update capability.
Adds the clang-tidy README badge (now four) and notes both in
CLAUDE.md. No firmware behavior change.
This was referenced May 21, 2026
14 tasks
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.
PR #4 on the path to 8/10. CI tooling — no firmware behavior change.
1. clang-tidy static analysis
.clang-tidy— enables the high-signal correctness families (bugprone-*,performance-*,portability-*,misc-*,clang-analyzer-*) withWarningsAsErrors: '*'. Deliberately skips the style/opinion checks (readability-*,cppcoreguidelines-*) that fight intentional embedded idioms — C arrays, pointer math, fixed magic constants — and would drown real findings in noise.HeaderFilterRegex: 'BirdsEye/.*\.h$'scopes diagnostics to our own headers. Verified locally: ~15k warnings from doctest/system headers are suppressed, leaving 0 in our code..github/workflows/clang-tidy.yml— generates the test build'scompile_commands.json(so clang-tidy gets each.cpp's exact flags) and analyzes the five host-buildable units:haversine,gps_time,gps_validation,dovex_header,filename_validator.The only real finding was a true positive about an intentional choice:
dovex_header.cpp's buffer builder does a non-null-terminatedmemcpyinto the fixed 1024-byte region (it's\n-padded, not a C string). Suppressed inline with// NOLINT(bugprone-not-null-terminated-result)+ a reason comment, so the check stays live everywhere else rather than being globally disabled.Confirmed
clang-tidyexits 0 locally on clang-tidy 18.2. Flash-size budget gate
Added to
compile-sketch.ymlafter the compile step. Parses thearduino/compile-sketchesreport and fails the build if flash usage exceeds 90% of the BSP-reported maximum.Why absolute % and not a delta: the XIAO nRF52840's app flash is shared with the SoftDevice + bootloader, so the meaningful question is "will this still fit and leave OTA room," not "did it grow." Using absolute usage also means no base-branch checkout/compare is needed.
Robustness:
absoluteas a bare number or as{current: N})::warning::and passes if the report is missing or unparseable, so a schema change upstream can't wedge CIFLASH_BUDGET_PERCENTenv var so it's a one-line change to adjustValidated the jq/awk logic locally against synthetic reports: a 30%-usage report passes at budget 90; a 93.7% report fails at 90 and passes at 95; an empty report warns-and-skips.
Badges
Fourth README badge (
clang-tidy) joins compile-sketch, arduino-lint, unit-tests. CLAUDE.md CI line updated.Notes / scope
.inomodules aren't clang-tidy'd — they need the full Arduino toolchain and are covered bycompile-sketch. Static analysis here targets exactly the Arduino-free units, which is also where the testable logic lives.# reproduce locally cmake -S tests -B tests/build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON clang-tidy -p tests/build BirdsEye/haversine.cpp BirdsEye/gps_time.cpp \ BirdsEye/gps_validation.cpp BirdsEye/dovex_header.cpp BirdsEye/filename_validator.cppWhere we are
🤖 Generated with Claude Code
Generated by Claude Code