Skip to content

Commit

Permalink
ci: Use CodeChecker as static analysis tool
Browse files Browse the repository at this point in the history
CodeChecker combines multiple static code analysis tools including
`clang-sa`. It also provides the possibility to check against a baseline
to report only newly introduced issues.
Moreover it is simpler to use.
It could eventually replace `clang-sa` completely in the pipeline.
  • Loading branch information
LukasWoodtli committed Dec 10, 2024
1 parent e7f4678 commit 10e8365
Show file tree
Hide file tree
Showing 9 changed files with 1,350 additions and 2 deletions.
53 changes: 53 additions & 0 deletions .github/workflows/codechecker.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: CodeChecker

on: [push, pull_request]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
codechecker_static_analyzer:
runs-on: ubuntu-24.04

steps:
- name: Checkout code including full history and submodules
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: true
fetch-depth: 0

- name: Install CodeChecker
run: |
sudo apt-get update
sudo apt-get install clang-tools-18 cmake cppcheck libcunit1-dev ninja-build
pip install --require-hashes -r tools/requirements-codechecker.txt
- name: Run CodeChecker
run: |
tools/ci/run_ci.sh --run-build --run-code-checker --code-checker diff
env:
CC: clang-18

- name: Upload CodeChecker reports
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: CodeChecker Reports
path: build-wakaama/code_checker_report/
if-no-files-found: error
if: failure()

- name: Create baseline for Upload
run: |
bash -x tools/ci/run_ci.sh --run-build --run-code-checker --code-checker baseline
env:
CC: clang-18
if: failure()

- name: Upload CodeChecker baseline (for debugging)
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: CodeChecker Baseline
path: tools/code_checker/reports.baseline
if-no-files-found: error
if: failure()
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,12 @@ Wakaama provides a simple CLI library. It can be enabled with:
- Unit testing: CUnit

On Ubuntu 24.04, used in CI, the dependencies can be installed as such:
- `apt install build-essential clang-format clang-format-18 clang-tools-18 cmake gcovr git libcunit1-dev ninja-build python3-pip`
- `apt install build-essential clang-format clang-format-18 clang-tools-18 cmake cppcheck gcovr git libcunit1-dev ninja-build python3-pip`
- `pip3 install -r tools/requirements-compliance.txt`

For macOS the development dependencies can be installed as such:

`brew install automake clang-format cmake cunit gcc gitlint gnu-getopt make ninja`
`brew install automake clang-format cmake cppcheck cunit gcc gitlint gnu-getopt make ninja`

### Code formatting
#### C
Expand Down
39 changes: 39 additions & 0 deletions doc/code_checker.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Static Code analysis with CodeChecker
=====================================

Wakaama uses ```CodeChecker`` <https://codechecker.readthedocs.io/>`__
for static code analysis.

It’s possible to run ``CodeChecker`` in two different modes: ``full``
and ``diff``

In ``full`` mode all found issues are reported. In ``diff`` mode only
new issues are shown.

The ``diff`` mode compares found issues with a ‘base line’ and shows
only newly found issues.

Running ``CodeChecker``
-----------------------

The ``CodeChecker`` is run as part of the CI GitHub Actions. But it can
be run manually:

To show new issues:

::

tools/ci/run_ci.sh --run-build --run-code-checker --code-checker diff

To show *all* issues:

::

tools/ci/run_ci.sh --run-build --run-code-checker --code-checker full

Create new ‘base line’:

::

tools/ci/run_ci.sh --run-build --run-code-checker --code-checker baseline

72 changes: 72 additions & 0 deletions tools/ci/run_ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ OPT_SONARQUBE=""
OPT_SOURCE_DIRECTORY="${REPO_ROOT_DIR}"
OPT_BUILD_DIRECTORY="build-wakaama"
OPT_TEST_COVERAGE_REPORT=""
OPT_CODE_CHECKER="full"
OPT_VERBOSE=0
OPT_WRAPPER_CMD=""
RUN_BUILD=0
Expand All @@ -41,6 +42,7 @@ RUN_GITLINT=0
RUN_GIT_BLAME_IGNORE=0
RUN_TESTS=0
RUN_DOXYGEN=0
RUN_CODE_CHECKER=0

HELP_MSG="usage: ${SCRIPT_NAME} <OPTIONS>...
Runs build and test steps in CI.
Expand Down Expand Up @@ -72,6 +74,9 @@ Options:
(WRAPPER: path to build-wrapper)
--test-coverage REPORT Enable code coverage measurement, output REPORT
(REPORT: xml html text none)
--code-checker ACTION Run the CodeChecker code analyzer to create a baseline,
do a full check or a PR check (show just difference to baseline)
(TYPE: full, diff, baseline)
-v, --verbose Verbose output
-a, --all Run all steps required for a MR
-h, --help Display this help and exit
Expand All @@ -85,6 +90,7 @@ Available steps (executed by --all):
--run-build Build all targets
--run-tests Execute tests (works only for top level project)
--run-doxygen Build the Doxygen documentation of the code
--run-code-checker Run the CodeChecker code analyzer
"

function usage() {
Expand Down Expand Up @@ -229,6 +235,46 @@ function run_doxygen() {
GIT_REVISION=$(git rev-parse @) WORKING_DIR=$(pwd) DOXYGEN_OUT_DIR=build-wakaama/doxygen \
doxygen doc/doxygen/Doxyfile
}

function run_code_checker() {
readonly config_file="${REPO_ROOT_DIR}/tools/code_checker/config.json"
readonly ignore_file="${REPO_ROOT_DIR}/tools/code_checker/ignore.txt"
readonly baseline_file="${REPO_ROOT_DIR}/tools/code_checker/reports.baseline"
readonly code_checker_result_dir="build-wakaama/code_checker_result/"
readonly code_checker_report="build-wakaama/code_checker_report/"

set +e +o pipefail
CodeChecker check --logfile build-wakaama/compile_commands.json \
--config "${config_file}" \
--ignore "${ignore_file}" \
--output ${code_checker_result_dir} \
|| true # Always returns a non-zero status if issues are found
set -e -o pipefail

if [ "${OPT_CODE_CHECKER}" = "diff" ]; then
CodeChecker cmd diff -b "${baseline_file}" \
-n $code_checker_result_dir \
-o html \
--export "${code_checker_report}" \
--new
else
if [ "${OPT_CODE_CHECKER}" = "baseline" ]; then
output_format="baseline"
output_location="${baseline_file}"
else
output_format="html"
output_location="${code_checker_report}"
fi

CodeChecker parse -e "${output_format}" \
-o "${output_location}" \
--config "${config_file}" \
--ignore "${ignore_file}" \
--trim-path-prefix="${REPO_ROOT_DIR}" \
"${code_checker_result_dir}"
fi
}

# Parse Options

if [[ "$OSTYPE" == "darwin"* ]]; then
Expand Down Expand Up @@ -260,12 +306,14 @@ if ! PARSED_OPTS=$($getopt -o vah \
-l run-git-blame-ignore \
-l run-tests \
-l run-doxygen \
-l run-code-checker \
-l sanitizer: \
-l scan-build: \
-l sonarqube: \
-l source-directory: \
-l build-directory: \
-l test-coverage: \
-l code-checker: \
-l verbose \
--name "${SCRIPT_NAME}" -- "$@");
then
Expand Down Expand Up @@ -328,6 +376,12 @@ while true; do
RUN_DOXYGEN=1
shift
;;
--run-code-checker)
RUN_CODE_CHECKER=1
# Analyzing works only when code gets actually built
RUN_CLEAN=1
shift
;;
--sanitizer)
OPT_SANITIZER=$2
shift 2
Expand Down Expand Up @@ -356,6 +410,10 @@ while true; do
OPT_TEST_COVERAGE_REPORT=$2
shift 2
;;
--code-checker)
OPT_CODE_CHECKER=$2
shift 2
;;
--)
shift
break
Expand Down Expand Up @@ -411,6 +469,11 @@ if [ -n "${OPT_SCAN_BUILD}" ] && [ -n "${OPT_SONARQUBE}" ]; then
exit 1
fi

if [ "${RUN_CODE_CHECKER}" = "1" ] && [ -n "${OPT_SONARQUBE}" ]; then
echo "--sonarqube and --code-checker can not be enabled at the same time"
exit 1
fi

if [ -n "${OPT_SONARQUBE}" ]; then
OPT_TEST_COVERAGE_REPORT="${OPT_TEST_COVERAGE_REPORT:-none}"
OPT_WRAPPER_CMD="${OPT_SONARQUBE} \
Expand All @@ -431,6 +494,10 @@ if [ -n "${OPT_SCAN_BUILD}" ]; then
--exclude examples/shared/tinydtls"
fi

if [ "${RUN_CODE_CHECKER}" = "1" ]; then
CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug"
fi

# Run Steps

if [ "${RUN_GITLINT}" -eq 1 ]; then
Expand Down Expand Up @@ -464,3 +531,8 @@ fi
if [ "${RUN_DOXYGEN}" -eq 1 ]; then
run_doxygen
fi

if [ "${RUN_CODE_CHECKER}" = "1" ]; then
run_code_checker
fi

12 changes: 12 additions & 0 deletions tools/code_checker/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"analyze": [
"--disable=cplusplus",
"--disable=cppcheck-exceptDeallocThrow",
"--disable=cppcheck-exceptThrowInDestructor",
"--disable=cppcheck-leakUnsafeArgAlloc",
"--disable=cppcheck-rethrowNoCurrentException",
"--disable=cppcheck-thisSubtraction",
"--disable=cppcheck-throwInNoexceptFunction",
"--clean"
]
}
2 changes: 2 additions & 0 deletions tools/code_checker/ignore.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-*/transport/tinydtls/third_party/*
-*/tests/*
Loading

0 comments on commit 10e8365

Please sign in to comment.