Skip to content

Commit 1607273

Browse files
committed
CI: add a regression test for output of clang-scan-build
ratchet so we reduce these over time
1 parent fb4e5ce commit 1607273

File tree

3 files changed

+287
-0
lines changed

3 files changed

+287
-0
lines changed
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
name: test clang-scan-build
2+
3+
on:
4+
push:
5+
paths-ignore:
6+
# remove non SITL HAL
7+
- 'libraries/AP_HAL_ChibiOS/**'
8+
- 'libraries/AP_HAL_ESP32/**'
9+
- 'libraries/AP_HAL_Linux/**'
10+
- 'libraries/AP_HAL_QURT/**'
11+
# remove non SITL directories
12+
- 'Tools/AP_Bootloader/**'
13+
- 'Tools/AP_Periph/**'
14+
- 'Tools/bootloaders/**'
15+
- 'Tools/CHDK-Script/**'
16+
- 'Tools/CodeStyle/**'
17+
- 'Tools/completion/**'
18+
- 'Tools/CPUInfo/**'
19+
- 'Tools/debug/**'
20+
- 'Tools/environment_install/**'
21+
- 'Tools/FilterTestTool/**'
22+
- 'Tools/Frame_params/**'
23+
- 'Tools/geotag/**'
24+
- 'Tools/GIT_Test/**'
25+
- 'Tools/gittools/**'
26+
- 'Tools/Hello/**'
27+
- 'Tools/IO_Firmware/**'
28+
- 'Tools/Linux_HAL_Essentials/**'
29+
- 'Tools/Pozyx/**'
30+
- 'Tools/PrintVersion.py'
31+
- 'Tools/Replay/**'
32+
- 'Tools/simulink/**'
33+
- 'Tools/UDP_Proxy/**'
34+
- 'Tools/vagrant/**'
35+
- 'Tools/Vicon/**'
36+
# Discard python file from Tools/scripts as not used
37+
- 'Tools/scripts/build_sizes/**'
38+
- 'Tools/scripts/build_tests/**'
39+
- 'Tools/scripts/CAN/**'
40+
- 'Tools/scripts/signing/**'
41+
# Remove autotest
42+
- 'Tools/autotest/antennatracker.py'
43+
- 'Tools/autotest/arducopter.py'
44+
- 'Tools/autotest/arduplane.py'
45+
- 'Tools/autotest/ardusub.py'
46+
- 'Tools/autotest/helicopter.py'
47+
- 'Tools/autotest/rover.py'
48+
- 'Tools/autotest/location.txt'
49+
- 'Tools/autotest/quadplane.py'
50+
- 'Tools/autotest/swarminit.txt'
51+
# Remove markdown files as irrelevant
52+
- '**.md'
53+
# Remove dotfile at root directory
54+
- './.dir-locals.el'
55+
- './.dockerignore'
56+
- './.editorconfig'
57+
- './.flake8'
58+
- './.gitattributes'
59+
- './.github'
60+
- './.gitignore'
61+
- './.pre-commit-config.yaml'
62+
- './.pydevproject'
63+
- './.valgrind-suppressions'
64+
- './.valgrindrc'
65+
- 'Dockerfile'
66+
- 'Vagrantfile'
67+
- 'Makefile'
68+
# Remove some directories check
69+
- '.vscode/**'
70+
- '.github/ISSUE_TEMPLATE/**'
71+
# Remove change on other workflows
72+
- '.github/workflows/test_environment.yml'
73+
74+
75+
pull_request:
76+
paths-ignore:
77+
# remove non SITL HAL
78+
- 'libraries/AP_HAL_QURT/**'
79+
- 'libraries/AP_HAL_Linux/**'
80+
- 'libraries/AP_HAL_ChibiOS/**'
81+
- 'libraries/AP_HAL_ESP32/**'
82+
# remove non SITL directories
83+
- 'Tools/AP_Bootloader/**'
84+
- 'Tools/AP_Periph/**'
85+
- 'Tools/bootloaders/**'
86+
- 'Tools/CHDK-Script/**'
87+
- 'Tools/CodeStyle/**'
88+
- 'Tools/completion/**'
89+
- 'Tools/CPUInfo/**'
90+
- 'Tools/debug/**'
91+
- 'Tools/environment_install/**'
92+
- 'Tools/FilterTestTool/**'
93+
- 'Tools/Frame_params/**'
94+
- 'Tools/geotag/**'
95+
- 'Tools/GIT_Test/**'
96+
- 'Tools/gittools/**'
97+
- 'Tools/Hello/**'
98+
- 'Tools/IO_Firmware/**'
99+
- 'Tools/Linux_HAL_Essentials/**'
100+
- 'Tools/LogAnalyzer/**'
101+
- 'Tools/Pozyx/**'
102+
- 'Tools/PrintVersion.py'
103+
- 'Tools/Replay/**'
104+
- 'Tools/simulink/**'
105+
- 'Tools/UDP_Proxy/**'
106+
- 'Tools/vagrant/**'
107+
- 'Tools/Vicon/**'
108+
# Discard python file from Tools/scripts as not used
109+
- 'Tools/scripts/build_sizes/**'
110+
- 'Tools/scripts/build_tests/**'
111+
- 'Tools/scripts/CAN/**'
112+
- 'Tools/scripts/signing/**'
113+
# Remove other vehicles autotest
114+
- 'Tools/autotest/antennatracker.py'
115+
- 'Tools/autotest/arducopter.py'
116+
- 'Tools/autotest/arduplane.py'
117+
- 'Tools/autotest/ardusub.py'
118+
- 'Tools/autotest/helicopter.py'
119+
- 'Tools/autotest/location.txt'
120+
- 'Tools/autotest/quadplane.py'
121+
- 'Tools/autotest/rover.py'
122+
- 'Tools/autotest/swarminit.txt'
123+
# Remove markdown files as irrelevant
124+
- '**.md'
125+
# Remove dotfile at root directory
126+
- './.dir-locals.el'
127+
- './.dockerignore'
128+
- './.editorconfig'
129+
- './.flake8'
130+
- './.gitattributes'
131+
- './.github'
132+
- './.gitignore'
133+
- './.pre-commit-config.yaml'
134+
- './.pydevproject'
135+
- './.valgrind-suppressions'
136+
- './.valgrindrc'
137+
- 'Dockerfile'
138+
- 'Vagrantfile'
139+
- 'Makefile'
140+
# Remove some directories check
141+
- '.vscode/**'
142+
- '.github/ISSUE_TEMPLATE/**'
143+
# Remove change on other workflows
144+
- '.github/workflows/test_environment.yml'
145+
146+
workflow_dispatch:
147+
148+
concurrency:
149+
group: ci-${{github.workflow}}-${{ github.ref }}
150+
cancel-in-progress: true
151+
152+
jobs:
153+
build:
154+
runs-on: ubuntu-22.04
155+
container:
156+
image: ardupilot/ardupilot-dev-base:v0.1.3
157+
options: --privileged --cap-add=SYS_PTRACE --security-opt apparmor=unconfined --security-opt seccomp=unconfined
158+
strategy:
159+
fail-fast: false # don't cancel if a job from the matrix fails (get archives!)
160+
steps:
161+
# git checkout the PR
162+
- uses: actions/checkout@v4
163+
with:
164+
submodules: 'recursive'
165+
# Put ccache into github cache for faster build
166+
- name: Prepare ccache timestamp
167+
id: ccache_cache_timestamp
168+
run: |
169+
NOW=$(date -u +"%F-%T")
170+
echo "timestamp=${NOW}" >> $GITHUB_OUTPUT
171+
- name: ccache cache files
172+
uses: actions/cache@v4
173+
with:
174+
path: ~/.ccache
175+
key: ${{github.workflow}}-ccache-clang-scan-build-${{steps.ccache_cache_timestamp.outputs.timestamp}}
176+
restore-keys: ${{github.workflow}}-ccache-clang-scan-build- # restore ccache from either previous build on this branch or on master
177+
- name: setup ccache
178+
run: |
179+
. .github/workflows/ccache.env
180+
- name: run clang-scan-build
181+
shell: bash
182+
run: |
183+
git config --global --add safe.directory ${GITHUB_WORKSPACE}
184+
sudo apt update
185+
sudo apt-get -y install clang-tools
186+
ls /usr/bin/clang-scan*
187+
mkdir -p $HOME/bin
188+
ln -s /usr/bin/scan-build-py-18 $HOME/bin/scan-build
189+
export PATH="$HOME/bin:/github/home/.local/bin:$PATH"
190+
mkdir -p /__w/ardupilot/ardupilot/tmp
191+
CI_BUILD_TARGET="clang_scan_build" Tools/scripts/build_ci.sh >$HOME/scan-build-stdout.txt
192+
193+
ccache -s
194+
ccache -z
195+
196+
# this renames the scan-build output directory to a fixed
197+
# name so we can archive it
198+
./Tools/autotest/process_scan_build_output.py $HOME/scan-build-stdout.txt
199+
200+
- name: Archive artifacts
201+
uses: actions/upload-artifact@v4
202+
with:
203+
name: clang-scan-build
204+
path: /__w/ardupilot/ardupilot/tmp/scan-build
205+
retention-days: 7
206+
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#!/usr/bin/env python3
2+
3+
'''
4+
Tool to process stdout from clang_scan_build, and manipulate files for archiving
5+
6+
AP_FLAKE8_CLEAN
7+
'''
8+
9+
import os
10+
import pathlib
11+
import re
12+
import sys
13+
14+
15+
class ProcessScanBuildOutput():
16+
def __init__(self, stdout_filepath):
17+
self.stdout_filepath = stdout_filepath
18+
19+
def progress(self, msg):
20+
print(f"psbo: {msg}")
21+
22+
def run(self):
23+
t = pathlib.Path(self.stdout_filepath).read_text()
24+
m_scan_build_dir = None
25+
m_bug_count = None
26+
for line in t.split("\n"):
27+
# extract scan-build-dir
28+
m = re.match(r".*Run 'scan-view (.+)'", line)
29+
if m is not None:
30+
m_scan_build_dir = m
31+
# extract count of bugs
32+
m = re.match(r".*?(\d+) bugs found", line)
33+
if m is not None:
34+
m_bug_count = m
35+
if m_scan_build_dir is None:
36+
raise ValueError("Did not find scan-build output directory in output")
37+
if m_bug_count is None:
38+
raise ValueError("Did not find bug count in output")
39+
scan_build_dir = m_scan_build_dir.group(1)
40+
bug_count = int(m_bug_count.group(1))
41+
42+
dest = "/__w/ardupilot/ardupilot/scan-build"
43+
self.progress(f"Renaming {scan_build_dir} to {dest}")
44+
os.rename(scan_build_dir, dest)
45+
46+
new_stdout_filepath = os.path.join(dest, self.stdout_filepath)
47+
self.progress(f"Renaming {self.stdout_filepath} to {new_stdout_filepath}")
48+
os.rename(self.stdout_filepath, new_stdout_filepath)
49+
50+
self.progress(f"Extracted Bug count is {bug_count}")
51+
52+
if bug_count != self.expected_bug_count():
53+
self.progress(f"Bug count incorrect (want={self.expected_bug_count()} got={bug_count})")
54+
if bug_count < self.expected_bug_count():
55+
self.progress("You have fixed bugs, please modify Tools/autotest/process_scan_build_output.py to reduce expected count") # noqa: E501
56+
else:
57+
self.progress("clang-scan-build has found problems being introduced; see artifacts")
58+
sys.exit(1)
59+
60+
def expected_bug_count(self):
61+
return 80
62+
63+
64+
if __name__ == '__main__':
65+
import argparse
66+
parser = argparse.ArgumentParser(description='tool to post-process output from clang-scan-build in CI')
67+
parser.add_argument('clang_scan_build_stdout', default=None, help='file containing stdout from clang-scan-build process')
68+
69+
args = parser.parse_args()
70+
71+
p = ProcessScanBuildOutput(args.clang_scan_build_stdout)
72+
p.run()

Tools/scripts/build_ci.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,15 @@ for t in $CI_BUILD_TARGET; do
466466
continue
467467
fi
468468

469+
if [ "$t" == "clang_scan_build" ]; then
470+
install_mavproxy
471+
install_pymavlink
472+
unset BUILDROOT
473+
echo "Running SITL clang-scan-build test"
474+
./Tools/autotest/autotest.py clang-scan-build
475+
continue
476+
fi
477+
469478
if [ "$t" == "validate_board_list" ]; then
470479
echo "Validating board list"
471480
./Tools/autotest/validate_board_list.py

0 commit comments

Comments
 (0)