Add GitHub action which runs static analysis
Now that all of the various issues that static analysis uncovered have been fixed (#2431, #2432, #2433, #2436, #2437, #2446), I've added a GitHub action which will run static analysis for every PR going forward. When static analysis detects issues with your code, the GitHub action provides a link to download its findings in a form tailored for human consumption. Take a look at [this demonstration of what it looks like when static analysis issues are found](https://github.com/Svetlitski/jemalloc/actions/runs/5010245602) on my fork for an example (make sure to follow the instructions in the error message to download and inspect the results).
This commit is contained in:
parent
bb0333e745
commit
05385191d4
68
.github/workflows/static_analysis.yaml
vendored
Normal file
68
.github/workflows/static_analysis.yaml
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
name: 'Static Analysis'
|
||||||
|
on: [pull_request]
|
||||||
|
jobs:
|
||||||
|
static-analysis:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
# We build libunwind ourselves because sadly the version
|
||||||
|
# provided by Ubuntu via apt-get is much too old.
|
||||||
|
- name: Check out libunwind
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
repository: libunwind/libunwind
|
||||||
|
path: libunwind
|
||||||
|
ref: 'v1.6.2'
|
||||||
|
github-server-url: 'https://github.com'
|
||||||
|
- name: Install libunwind
|
||||||
|
run: |
|
||||||
|
cd libunwind
|
||||||
|
autoreconf -i
|
||||||
|
./configure --prefix=/usr
|
||||||
|
make -s -j $(nproc) V=0
|
||||||
|
sudo make -s install V=0
|
||||||
|
cd ..
|
||||||
|
rm -rf libunwind
|
||||||
|
- name: Check out repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
# We download LLVM directly from the latest stable release
|
||||||
|
# on GitHub, because this tends to be much newer than the
|
||||||
|
# version available via apt-get in Ubuntu.
|
||||||
|
- name: Download LLVM
|
||||||
|
uses: dsaltares/fetch-gh-release-asset@master
|
||||||
|
with:
|
||||||
|
repo: 'llvm/llvm-project'
|
||||||
|
version: 'latest'
|
||||||
|
file: 'clang[+]llvm-.*x86_64-linux-gnu.*'
|
||||||
|
regex: true
|
||||||
|
target: 'llvm_assets/'
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Install prerequisites
|
||||||
|
id: install_prerequisites
|
||||||
|
run: |
|
||||||
|
tar -C llvm_assets -xaf llvm_assets/*.tar* &
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y jq bear python3-pip
|
||||||
|
pip install codechecker
|
||||||
|
echo "Extracting LLVM from tar" 1>&2
|
||||||
|
wait
|
||||||
|
echo "LLVM_BIN_DIR=$(echo llvm_assets/clang*/bin)" >> "$GITHUB_OUTPUT"
|
||||||
|
- name: Run static analysis
|
||||||
|
id: run_static_analysis
|
||||||
|
run: >
|
||||||
|
PATH="${{ steps.install_prerequisites.outputs.LLVM_BIN_DIR }}:$PATH"
|
||||||
|
LDFLAGS='-L/usr/lib'
|
||||||
|
scripts/run_static_analysis.sh static_analysis_results "$GITHUB_OUTPUT"
|
||||||
|
- name: Upload static analysis results
|
||||||
|
if: ${{ steps.run_static_analysis.outputs.HAS_STATIC_ANALYSIS_RESULTS }} == '1'
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: static_analysis_results
|
||||||
|
path: static_analysis_results
|
||||||
|
- name: Check static analysis results
|
||||||
|
run: |
|
||||||
|
if [[ "${{ steps.run_static_analysis.outputs.HAS_STATIC_ANALYSIS_RESULTS }}" == '1' ]]
|
||||||
|
then
|
||||||
|
echo "::error::Static analysis found issues with your code. Download the 'static_analysis_results' artifact from this workflow and view the 'index.html' file contained within it in a web browser locally for detailed results."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -45,6 +45,10 @@
|
|||||||
/src/*.[od]
|
/src/*.[od]
|
||||||
/src/*.sym
|
/src/*.sym
|
||||||
|
|
||||||
|
compile_commands.json
|
||||||
|
/static_analysis_raw_results
|
||||||
|
/static_analysis_results
|
||||||
|
|
||||||
/run_tests.out/
|
/run_tests.out/
|
||||||
|
|
||||||
/test/test.sh
|
/test/test.sh
|
||||||
|
52
scripts/run_static_analysis.sh
Executable file
52
scripts/run_static_analysis.sh
Executable file
@ -0,0 +1,52 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
git clean -Xfd
|
||||||
|
|
||||||
|
export CC='clang'
|
||||||
|
export CXX='clang++'
|
||||||
|
compile_time_malloc_conf='background_thread:true,'\
|
||||||
|
'metadata_thp:auto,'\
|
||||||
|
'abort_conf:true,'\
|
||||||
|
'muzzy_decay_ms:0,'\
|
||||||
|
'zero_realloc:free,'\
|
||||||
|
'prof_unbias:false,'\
|
||||||
|
'prof_time_resolution:high'
|
||||||
|
|
||||||
|
./autogen.sh \
|
||||||
|
--with-private-namespace=jemalloc_ \
|
||||||
|
--disable-cache-oblivious \
|
||||||
|
--enable-prof \
|
||||||
|
--enable-prof-libunwind \
|
||||||
|
--with-malloc-conf="$compile_time_malloc_conf" \
|
||||||
|
--enable-readlinkat \
|
||||||
|
--enable-opt-safety-checks \
|
||||||
|
--enable-uaf-detection \
|
||||||
|
--enable-force-getenv \
|
||||||
|
--enable-debug # Enabling debug for static analysis is important,
|
||||||
|
# otherwise you'll get tons of warnings for things
|
||||||
|
# that are already covered by `assert`s.
|
||||||
|
|
||||||
|
bear -- make -s -j $(nproc)
|
||||||
|
# We end up with lots of duplicate entries in the compilation database, one for
|
||||||
|
# each output file type (e.g. .o, .d, .sym, etc.). There must be exactly one
|
||||||
|
# entry for each file in the compilation database in order for
|
||||||
|
# cross-translation-unit analysis to work, so we deduplicate the database here.
|
||||||
|
jq '[.[] | select(.output | test("/[^./]*\\.o$"))]' compile_commands.json > compile_commands.json.tmp
|
||||||
|
mv compile_commands.json.tmp compile_commands.json
|
||||||
|
|
||||||
|
CC_ANALYZERS_FROM_PATH=1 CodeChecker analyze compile_commands.json --jobs $(nproc) \
|
||||||
|
--ctu --compile-uniqueing strict --output static_analysis_raw_results \
|
||||||
|
--analyzers clang-tidy clangsa
|
||||||
|
|
||||||
|
html_output_dir="${1:-static_analysis_results}"
|
||||||
|
result=${2:-/dev/null}
|
||||||
|
# We're echoing a value because we want to indicate whether or not any errors
|
||||||
|
# were found, but we always want the script to have a successful exit code so
|
||||||
|
# that we actually reach the step in the GitHub action where we upload the results.
|
||||||
|
if CodeChecker parse --export html --output "$html_output_dir" static_analysis_raw_results
|
||||||
|
then
|
||||||
|
echo "HAS_STATIC_ANALYSIS_RESULTS=0" >> "$result"
|
||||||
|
else
|
||||||
|
echo "HAS_STATIC_ANALYSIS_RESULTS=1" >> "$result"
|
||||||
|
fi
|
Loading…
Reference in New Issue
Block a user