Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CI: add a regression test for output of clang-scan-build #29184

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 206 additions & 0 deletions .github/workflows/test_clang_scan_build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
name: test clang-scan-build

on:
push:
paths-ignore:
# remove non SITL HAL
- 'libraries/AP_HAL_ChibiOS/**'
- 'libraries/AP_HAL_ESP32/**'
- 'libraries/AP_HAL_Linux/**'
- 'libraries/AP_HAL_QURT/**'
# remove non SITL directories
- 'Tools/AP_Bootloader/**'
- 'Tools/AP_Periph/**'
- 'Tools/bootloaders/**'
- 'Tools/CHDK-Script/**'
- 'Tools/CodeStyle/**'
- 'Tools/completion/**'
- 'Tools/CPUInfo/**'
- 'Tools/debug/**'
- 'Tools/environment_install/**'
- 'Tools/FilterTestTool/**'
- 'Tools/Frame_params/**'
- 'Tools/geotag/**'
- 'Tools/GIT_Test/**'
- 'Tools/gittools/**'
- 'Tools/Hello/**'
- 'Tools/IO_Firmware/**'
- 'Tools/Linux_HAL_Essentials/**'
- 'Tools/Pozyx/**'
- 'Tools/PrintVersion.py'
- 'Tools/Replay/**'
- 'Tools/simulink/**'
- 'Tools/UDP_Proxy/**'
- 'Tools/vagrant/**'
- 'Tools/Vicon/**'
# Discard python file from Tools/scripts as not used
- 'Tools/scripts/build_sizes/**'
- 'Tools/scripts/build_tests/**'
- 'Tools/scripts/CAN/**'
- 'Tools/scripts/signing/**'
# Remove autotest
- 'Tools/autotest/antennatracker.py'
- 'Tools/autotest/arducopter.py'
- 'Tools/autotest/arduplane.py'
- 'Tools/autotest/ardusub.py'
- 'Tools/autotest/helicopter.py'
- 'Tools/autotest/rover.py'
- 'Tools/autotest/location.txt'
- 'Tools/autotest/quadplane.py'
- 'Tools/autotest/swarminit.txt'
# Remove markdown files as irrelevant
- '**.md'
# Remove dotfile at root directory
- './.dir-locals.el'
- './.dockerignore'
- './.editorconfig'
- './.flake8'
- './.gitattributes'
- './.github'
- './.gitignore'
- './.pre-commit-config.yaml'
- './.pydevproject'
- './.valgrind-suppressions'
- './.valgrindrc'
- 'Dockerfile'
- 'Vagrantfile'
- 'Makefile'
# Remove some directories check
- '.vscode/**'
- '.github/ISSUE_TEMPLATE/**'
# Remove change on other workflows
- '.github/workflows/test_environment.yml'


pull_request:
paths-ignore:
# remove non SITL HAL
- 'libraries/AP_HAL_QURT/**'
- 'libraries/AP_HAL_Linux/**'
- 'libraries/AP_HAL_ChibiOS/**'
- 'libraries/AP_HAL_ESP32/**'
# remove non SITL directories
- 'Tools/AP_Bootloader/**'
- 'Tools/AP_Periph/**'
- 'Tools/bootloaders/**'
- 'Tools/CHDK-Script/**'
- 'Tools/CodeStyle/**'
- 'Tools/completion/**'
- 'Tools/CPUInfo/**'
- 'Tools/debug/**'
- 'Tools/environment_install/**'
- 'Tools/FilterTestTool/**'
- 'Tools/Frame_params/**'
- 'Tools/geotag/**'
- 'Tools/GIT_Test/**'
- 'Tools/gittools/**'
- 'Tools/Hello/**'
- 'Tools/IO_Firmware/**'
- 'Tools/Linux_HAL_Essentials/**'
- 'Tools/LogAnalyzer/**'
- 'Tools/Pozyx/**'
- 'Tools/PrintVersion.py'
- 'Tools/Replay/**'
- 'Tools/simulink/**'
- 'Tools/UDP_Proxy/**'
- 'Tools/vagrant/**'
- 'Tools/Vicon/**'
# Discard python file from Tools/scripts as not used
- 'Tools/scripts/build_sizes/**'
- 'Tools/scripts/build_tests/**'
- 'Tools/scripts/CAN/**'
- 'Tools/scripts/signing/**'
# Remove other vehicles autotest
- 'Tools/autotest/antennatracker.py'
- 'Tools/autotest/arducopter.py'
- 'Tools/autotest/arduplane.py'
- 'Tools/autotest/ardusub.py'
- 'Tools/autotest/helicopter.py'
- 'Tools/autotest/location.txt'
- 'Tools/autotest/quadplane.py'
- 'Tools/autotest/rover.py'
- 'Tools/autotest/swarminit.txt'
# Remove markdown files as irrelevant
- '**.md'
# Remove dotfile at root directory
- './.dir-locals.el'
- './.dockerignore'
- './.editorconfig'
- './.flake8'
- './.gitattributes'
- './.github'
- './.gitignore'
- './.pre-commit-config.yaml'
- './.pydevproject'
- './.valgrind-suppressions'
- './.valgrindrc'
- 'Dockerfile'
- 'Vagrantfile'
- 'Makefile'
# Remove some directories check
- '.vscode/**'
- '.github/ISSUE_TEMPLATE/**'
# Remove change on other workflows
- '.github/workflows/test_environment.yml'

workflow_dispatch:

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

jobs:
build:
runs-on: ubuntu-22.04
container:
image: ardupilot/ardupilot-dev-base:v0.1.3
options: --privileged --cap-add=SYS_PTRACE --security-opt apparmor=unconfined --security-opt seccomp=unconfined
strategy:
fail-fast: false # don't cancel if a job from the matrix fails (get archives!)
steps:
# git checkout the PR
- uses: actions/checkout@v4
with:
submodules: 'recursive'
# Put ccache into github cache for faster build
- name: Prepare ccache timestamp
id: ccache_cache_timestamp
run: |
NOW=$(date -u +"%F-%T")
echo "timestamp=${NOW}" >> $GITHUB_OUTPUT
- name: ccache cache files
uses: actions/cache@v4
with:
path: ~/.ccache
key: ${{github.workflow}}-ccache-clang-scan-build-${{steps.ccache_cache_timestamp.outputs.timestamp}}
restore-keys: ${{github.workflow}}-ccache-clang-scan-build- # restore ccache from either previous build on this branch or on master
- name: setup ccache
run: |
. .github/workflows/ccache.env
- name: run clang-scan-build
shell: bash
run: |
git config --global --add safe.directory ${GITHUB_WORKSPACE}
sudo apt update
sudo apt-get -y install clang-tools
ls /usr/bin/clang-scan*
mkdir -p $HOME/bin
ln -s /usr/bin/scan-build-py-18 $HOME/bin/scan-build
export PATH="$HOME/bin:/github/home/.local/bin:$PATH"
mkdir -p /__w/ardupilot/ardupilot/tmp
CI_BUILD_TARGET="clang_scan_build" Tools/scripts/build_ci.sh >$HOME/scan-build-stdout.txt

ccache -s
ccache -z

# this renames the scan-build output directory to a fixed
# name so we can archive it
./Tools/autotest/process_scan_build_output.py $HOME/scan-build-stdout.txt

- name: Archive artifacts
uses: actions/upload-artifact@v4
with:
name: clang-scan-build
path: /__w/ardupilot/ardupilot/tmp/scan-build
retention-days: 7

72 changes: 72 additions & 0 deletions Tools/autotest/process_scan_build_output.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env python3

'''
Tool to process stdout from clang_scan_build, and manipulate files for archiving

AP_FLAKE8_CLEAN
'''

import os
import pathlib
import re
import sys


class ProcessScanBuildOutput():
def __init__(self, stdout_filepath):
self.stdout_filepath = stdout_filepath

def progress(self, msg):
print(f"psbo: {msg}")

def run(self):
t = pathlib.Path(self.stdout_filepath).read_text()
m_scan_build_dir = None
m_bug_count = None
for line in t.split("\n"):
# extract scan-build-dir
m = re.match(r".*Run 'scan-view (.+)'", line)
if m is not None:
m_scan_build_dir = m
# extract count of bugs
m = re.match(r".*?(\d+) bugs found", line)
if m is not None:
m_bug_count = m
if m_scan_build_dir is None:
raise ValueError("Did not find scan-build output directory in output")
if m_bug_count is None:
raise ValueError("Did not find bug count in output")
scan_build_dir = m_scan_build_dir.group(1)
bug_count = int(m_bug_count.group(1))

dest = "/__w/ardupilot/ardupilot/scan-build"
self.progress(f"Renaming {scan_build_dir} to {dest}")
os.rename(scan_build_dir, dest)

new_stdout_filepath = os.path.join(dest, self.stdout_filepath)
self.progress(f"Renaming {self.stdout_filepath} to {new_stdout_filepath}")
os.rename(self.stdout_filepath, new_stdout_filepath)

self.progress(f"Extracted Bug count is {bug_count}")

if bug_count != self.expected_bug_count():
self.progress(f"Bug count incorrect (want={self.expected_bug_count()} got={bug_count})")
if bug_count < self.expected_bug_count():
self.progress("You have fixed bugs, please modify Tools/autotest/process_scan_build_output.py to reduce expected count") # noqa: E501
else:
self.progress("clang-scan-build has found problems being introduced; see artifacts")
sys.exit(1)

def expected_bug_count(self):
return 80


if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description='tool to post-process output from clang-scan-build in CI')
parser.add_argument('clang_scan_build_stdout', default=None, help='file containing stdout from clang-scan-build process')

args = parser.parse_args()

p = ProcessScanBuildOutput(args.clang_scan_build_stdout)
p.run()
9 changes: 9 additions & 0 deletions Tools/scripts/build_ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,15 @@ for t in $CI_BUILD_TARGET; do
continue
fi

if [ "$t" == "clang_scan_build" ]; then
install_mavproxy
install_pymavlink
unset BUILDROOT
echo "Running SITL clang-scan-build test"
./Tools/autotest/autotest.py clang-scan-build
continue
fi

if [ "$t" == "validate_board_list" ]; then
echo "Validating board list"
./Tools/autotest/validate_board_list.py
Expand Down
Loading