Add clang-format, clang-tidy, ASan/UBSan CI lanes
Format and tidy enforce only on lines changed in PRs (diff-only via git-clang-format and clang-tidy-diff.py) — existing files keep their current style until edited. Mass reformat deferred; .git-blame-ignore-revs stub is in place for whenever that happens. Sanitizer lane builds with -fsanitize=address,undefined and runs the unit suite. continue-on-error: true initially so we can triage findings without blocking PRs. UB categories pervasive in the Hash9 C cascade (alignment, signed-integer-overflow, vptr) are suppressed pending file-by-file fixes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,49 @@
|
|||||||
|
# Triangles code style.
|
||||||
|
# Conservative: do not reflow long lines, do not reorganize includes.
|
||||||
|
# This config is enforced *only on changed lines* via `git clang-format` in CI,
|
||||||
|
# so it shapes new/edited code without touching legacy files until they're touched.
|
||||||
|
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
Language: Cpp
|
||||||
|
Standard: c++17
|
||||||
|
|
||||||
|
IndentWidth: 4
|
||||||
|
TabWidth: 4
|
||||||
|
UseTab: Never
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
|
||||||
|
ColumnLimit: 0 # Don't reflow long lines — too disruptive for legacy code.
|
||||||
|
ReflowComments: false
|
||||||
|
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
AllowShortFunctionsOnASingleLine: Inline
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
|
||||||
|
PointerAlignment: Left
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
|
||||||
|
NamespaceIndentation: None
|
||||||
|
FixNamespaceComments: true
|
||||||
|
|
||||||
|
# Includes: don't shuffle — header order in this codebase is load-bearing
|
||||||
|
# (e.g. main.cpp's mix of project + system headers carries platform meaning).
|
||||||
|
SortIncludes: false
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
MaxEmptyLinesToKeep: 2
|
||||||
|
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignTrailingComments: true
|
||||||
|
|
||||||
|
# Don't auto-add braces to single-statement bodies — too invasive.
|
||||||
|
InsertBraces: false
|
||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
# Triangles clang-tidy config.
|
||||||
|
#
|
||||||
|
# Goal: catch real bugs in new/edited code without drowning in noise from
|
||||||
|
# legacy patterns. Enforced *diff-only* in CI (changed lines on PRs).
|
||||||
|
#
|
||||||
|
# Conservative starter set. Graduate checks to WarningsAsErrors only after
|
||||||
|
# the codebase is clean for that check.
|
||||||
|
|
||||||
|
Checks: >
|
||||||
|
-*,
|
||||||
|
bugprone-*,
|
||||||
|
performance-*,
|
||||||
|
readability-misleading-indentation,
|
||||||
|
readability-redundant-control-flow,
|
||||||
|
readability-redundant-smartptr-get,
|
||||||
|
readability-redundant-string-cstr,
|
||||||
|
readability-redundant-string-init,
|
||||||
|
readability-string-compare,
|
||||||
|
modernize-use-nullptr,
|
||||||
|
modernize-use-override,
|
||||||
|
modernize-deprecated-headers,
|
||||||
|
cppcoreguidelines-init-variables,
|
||||||
|
cppcoreguidelines-pro-type-member-init,
|
||||||
|
-bugprone-easily-swappable-parameters,
|
||||||
|
-bugprone-implicit-widening-of-multiplication-result,
|
||||||
|
-bugprone-narrowing-conversions,
|
||||||
|
-bugprone-branch-clone,
|
||||||
|
-bugprone-signed-char-misuse,
|
||||||
|
-bugprone-reserved-identifier,
|
||||||
|
-bugprone-unchecked-optional-access,
|
||||||
|
-performance-no-int-to-ptr,
|
||||||
|
-performance-avoid-endl
|
||||||
|
|
||||||
|
# Warn-only initially. Once a check is clean repo-wide we can promote it here.
|
||||||
|
WarningsAsErrors: ''
|
||||||
|
|
||||||
|
# Run on project sources; skip vendored/generated code.
|
||||||
|
HeaderFilterRegex: '^.*src/(?!json/nlohmann_json|leveldb|lz4|tor/tor-src).*\.h$'
|
||||||
|
|
||||||
|
FormatStyle: file
|
||||||
|
|
||||||
|
CheckOptions:
|
||||||
|
- key: readability-identifier-naming.IgnoreMainLikeFunctions
|
||||||
|
value: '1'
|
||||||
|
- key: cppcoreguidelines-init-variables.IncludeStyle
|
||||||
|
value: 'google'
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# Revisions listed here are skipped by `git blame` when --ignore-revs-file
|
||||||
|
# is configured. GitHub honors this file automatically.
|
||||||
|
#
|
||||||
|
# Add the SHA of any large mechanical reformat / rename / mass-style commit
|
||||||
|
# below, with a one-line comment.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# abc1234567890abcdef # repo-wide clang-format (no behavior change)
|
||||||
|
#
|
||||||
|
# To enable locally:
|
||||||
|
# git config blame.ignoreRevsFile .git-blame-ignore-revs
|
||||||
@@ -37,6 +37,50 @@ jobs:
|
|||||||
- name: Run unit tests
|
- name: Run unit tests
|
||||||
run: cd build && ctest --output-on-failure || true
|
run: cd build && ctest --output-on-failure || true
|
||||||
|
|
||||||
|
test-linux-sanitizers:
|
||||||
|
# ASan + UBSan build of the daemon + unit tests. Allowed to fail until
|
||||||
|
# findings are triaged — see .github/workflows/lint.yml comment block.
|
||||||
|
# Once the test suite is clean under sanitizers, drop continue-on-error.
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
continue-on-error: true
|
||||||
|
env:
|
||||||
|
# ASan: leak detection off by default (BDB and OpenSSL produce noise on shutdown).
|
||||||
|
# Re-enable once we've quieted the legitimate suspects.
|
||||||
|
ASAN_OPTIONS: "detect_leaks=0:halt_on_error=1:abort_on_error=1:print_stacktrace=1:strict_string_checks=1:detect_stack_use_after_return=1"
|
||||||
|
# UBSan: print full stack traces on first error and exit non-zero.
|
||||||
|
UBSAN_OPTIONS: "halt_on_error=1:abort_on_error=1:print_stacktrace=1"
|
||||||
|
# Suppress UB categories that are pervasive in the Hash9 C cascade
|
||||||
|
# and BDB until they're fixed file-by-file.
|
||||||
|
SAN_FLAGS: "-fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize-recover=undefined -fno-sanitize=alignment,signed-integer-overflow,vptr"
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y build-essential cmake ninja-build \
|
||||||
|
libboost-all-dev libssl-dev libdb++-dev libleveldb-dev \
|
||||||
|
libevent-dev libminiupnpc-dev zlib1g-dev
|
||||||
|
|
||||||
|
- name: Configure with sanitizers
|
||||||
|
run: |
|
||||||
|
cmake -B build-san -G Ninja \
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug \
|
||||||
|
-DCMAKE_C_FLAGS="$SAN_FLAGS" \
|
||||||
|
-DCMAKE_CXX_FLAGS="$SAN_FLAGS" \
|
||||||
|
-DCMAKE_EXE_LINKER_FLAGS="$SAN_FLAGS" \
|
||||||
|
-DCMAKE_SHARED_LINKER_FLAGS="$SAN_FLAGS" \
|
||||||
|
-DBUILD_QT=OFF \
|
||||||
|
-DBUILD_DAEMON=ON \
|
||||||
|
-DBUILD_TESTS=ON \
|
||||||
|
-DUSE_UPNP=OFF
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: cmake --build build-san -j$(nproc)
|
||||||
|
|
||||||
|
- name: Run unit tests under sanitizers
|
||||||
|
run: cd build-san && ctest --output-on-failure
|
||||||
|
|
||||||
build-windows-qt:
|
build-windows-qt:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
defaults:
|
defaults:
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
name: Lint
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [master]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
# Diff-only enforcement: clang-format and clang-tidy run only on lines changed
|
||||||
|
# in the PR. Existing files keep their current style until they're edited.
|
||||||
|
# See .clang-format and .clang-tidy for the rule sets.
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
clang-format-diff:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
# Need merge-base with target branch to compute the diff.
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Install clang-format
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y clang-format-15
|
||||||
|
sudo ln -sf /usr/bin/clang-format-15 /usr/local/bin/clang-format
|
||||||
|
|
||||||
|
- name: Check format on changed lines
|
||||||
|
run: |
|
||||||
|
BASE_SHA=$(git merge-base origin/${{ github.base_ref }} HEAD)
|
||||||
|
echo "Comparing against merge-base: $BASE_SHA"
|
||||||
|
|
||||||
|
# git-clang-format prints a diff if any changed line violates style.
|
||||||
|
# --diff exits non-zero when reformatting would change something.
|
||||||
|
OUTPUT=$(git clang-format --diff "$BASE_SHA" -- '*.cpp' '*.h' '*.hpp' '*.cc' || true)
|
||||||
|
|
||||||
|
if [ -z "$OUTPUT" ] || [ "$OUTPUT" = "no modified files to format" ] || [ "$OUTPUT" = "clang-format did not modify any files" ]; then
|
||||||
|
echo "clang-format: clean"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "::error::clang-format wants to change the following on lines you touched."
|
||||||
|
echo "Run \`git clang-format $BASE_SHA\` locally and commit the result."
|
||||||
|
echo "$OUTPUT"
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
clang-tidy-diff:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Install dependencies + clang-tidy
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y build-essential cmake ninja-build clang-tidy-15 \
|
||||||
|
libboost-all-dev libssl-dev libdb++-dev libleveldb-dev \
|
||||||
|
libevent-dev libminiupnpc-dev zlib1g-dev
|
||||||
|
sudo ln -sf /usr/bin/clang-tidy-15 /usr/local/bin/clang-tidy
|
||||||
|
|
||||||
|
- name: Configure (export compile_commands.json)
|
||||||
|
run: |
|
||||||
|
cmake -B build -G Ninja \
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug \
|
||||||
|
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||||
|
-DBUILD_QT=OFF \
|
||||||
|
-DBUILD_DAEMON=ON \
|
||||||
|
-DBUILD_TESTS=ON \
|
||||||
|
-DUSE_UPNP=OFF
|
||||||
|
|
||||||
|
- name: Generate build artifacts that headers depend on
|
||||||
|
# build.h, qt UI headers, etc. — clang-tidy needs them to parse sources.
|
||||||
|
run: cmake --build build --target generate_build_info
|
||||||
|
|
||||||
|
- name: Run clang-tidy on changed lines
|
||||||
|
run: |
|
||||||
|
BASE_SHA=$(git merge-base origin/${{ github.base_ref }} HEAD)
|
||||||
|
echo "Comparing against merge-base: $BASE_SHA"
|
||||||
|
|
||||||
|
# clang-tidy-diff.py ships with clang-tidy; runs tidy only on changed lines.
|
||||||
|
DIFF_SCRIPT=$(dpkg -L clang-tidy-15 | grep clang-tidy-diff.py | head -1)
|
||||||
|
if [ -z "$DIFF_SCRIPT" ]; then
|
||||||
|
DIFF_SCRIPT=/usr/share/clang/clang-tidy-diff.py
|
||||||
|
fi
|
||||||
|
echo "Using: $DIFF_SCRIPT"
|
||||||
|
|
||||||
|
# -p1 strips the leading "a/"/"b/" from git diff paths.
|
||||||
|
# -path=build points clang-tidy at compile_commands.json.
|
||||||
|
# -iregex restricts to project sources (not vendored).
|
||||||
|
git diff -U0 "$BASE_SHA" -- 'src/*.cpp' 'src/*.h' \
|
||||||
|
':(exclude)src/json/nlohmann_json.hpp' \
|
||||||
|
':(exclude)src/leveldb/*' \
|
||||||
|
':(exclude)src/lz4/*' \
|
||||||
|
':(exclude)src/tor/tor-src/*' \
|
||||||
|
| python3 "$DIFF_SCRIPT" -p1 -path build \
|
||||||
|
-iregex '.*\.(cpp|cc|h|hpp)$' \
|
||||||
|
-j$(nproc) || EXIT=$?
|
||||||
|
|
||||||
|
# Warn-only initially. Flip this to `exit ${EXIT:-0}` once we're clean.
|
||||||
|
exit 0
|
||||||
Reference in New Issue
Block a user