Merge pull request #5 from dreamer/po/ci-improvements-1
Enforce limit on issues found in static analysis
This commit is contained in:
commit
57aaed6399
3 changed files with 99 additions and 12 deletions
8
.github/workflows/static.yml
vendored
8
.github/workflows/static.yml
vendored
|
@ -12,7 +12,7 @@ jobs:
|
|||
- name: "Install packages"
|
||||
run: sudo apt-get install libsdl1.2-dev libsdl-net1.2-dev libsdl-sound1.2-dev python3-setuptools
|
||||
- name: "Install scan-build (Python version)"
|
||||
run: sudo pip3 install scan-build
|
||||
run: sudo pip3 install scan-build beautifulsoup4 html5lib
|
||||
- name: Build
|
||||
run: |
|
||||
# build steps
|
||||
|
@ -27,3 +27,9 @@ jobs:
|
|||
with:
|
||||
name: report
|
||||
path: report
|
||||
- name: Summarize report
|
||||
run: |
|
||||
# summary
|
||||
echo "Full report is included in build Artifacts"
|
||||
echo
|
||||
./scripts/count-bugs.py report/*/index.html
|
||||
|
|
74
scripts/count-bugs.py
Executable file
74
scripts/count-bugs.py
Executable file
|
@ -0,0 +1,74 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
# Copyright (c) 2019 Patryk Obara <patryk.obara@gmail.com>
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# This script prints a summary snippet of information out of reports created
|
||||
# by scan-build or analyze-build for Clang's static code analysis.
|
||||
#
|
||||
# Usage: ./count-warnings.py path/to/report/index.html
|
||||
#
|
||||
# This script depends on BeautifulSoup module, if you're distribution is
|
||||
# missing it, you can use pipenv to install it for virtualenv spanning only
|
||||
# this repo: pipenv install beautifulsoup4 html5lib
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
# pylint: disable=missing-docstring
|
||||
|
||||
import sys
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
# Maximum allowed number of issues; if report will include more bugs,
|
||||
# then script will return with status 1. Simply change this line if you
|
||||
# want to set a different limit.
|
||||
#
|
||||
MAX_ISSUES = 113
|
||||
|
||||
|
||||
def summary_values(summary_table):
|
||||
if not summary_table:
|
||||
return
|
||||
for row in summary_table.find_all('tr'):
|
||||
description = row.find('td', 'SUMM_DESC')
|
||||
value = row.find('td', 'Q')
|
||||
if description is None or value is None:
|
||||
continue
|
||||
yield description.get_text(), int(value.get_text())
|
||||
|
||||
|
||||
def read_soup(index_html):
|
||||
with open(index_html) as index:
|
||||
soup = BeautifulSoup(index, 'html5lib')
|
||||
tables = soup.find_all('table')
|
||||
summary = tables[1]
|
||||
return {bug: count for bug, count in summary_values(summary)}
|
||||
|
||||
|
||||
def find_longest_name_length(names):
|
||||
return max(len(x) for x in names)
|
||||
|
||||
|
||||
def print_summary(issues):
|
||||
summary = list(issues.items())
|
||||
size = find_longest_name_length(issues.keys()) + 1
|
||||
for warning, count in sorted(summary, key=lambda x: -x[1]):
|
||||
print(' {text:{field_size}s}: {count}'.format(
|
||||
text=warning, count=count, field_size=size))
|
||||
print()
|
||||
|
||||
|
||||
def main():
|
||||
bug_types = read_soup(sys.argv[1])
|
||||
total = bug_types.pop('All Bugs')
|
||||
if bug_types:
|
||||
print("Bugs grouped by type:\n")
|
||||
print_summary(bug_types)
|
||||
print('Total: {} bugs (out of {} allowed)\n'.format(total, MAX_ISSUES))
|
||||
if total > MAX_ISSUES:
|
||||
print('Error: upper limit of allowed bugs is', MAX_ISSUES)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
29
scripts/count-warnings.py
Normal file → Executable file
29
scripts/count-warnings.py
Normal file → Executable file
|
@ -1,8 +1,9 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
# Copyright (c) 2019 Patryk Obara
|
||||
# Copyright (c) 2019 Patryk Obara <patryk.obara@gmail.com>
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# This script counts and all warnings and prints a summary.
|
||||
# This script counts all compiler warnings and prints a summary.
|
||||
#
|
||||
# Usage: ./count-warnings.py build.log
|
||||
# Usage: cat "*.log" | ./count-warnings.py -
|
||||
|
@ -18,11 +19,11 @@ import os
|
|||
import re
|
||||
import sys
|
||||
|
||||
# Maximum allowed number of warnings; if build will include more warnings,
|
||||
# Maximum allowed number of issues; if build will include more warnings,
|
||||
# then script will return with status 1. Simply change this line if you
|
||||
# want to set a different limit.
|
||||
#
|
||||
MAX_WARNINGS = 357
|
||||
MAX_ISSUES = 357
|
||||
|
||||
# For recognizing warnings in GCC format in stderr:
|
||||
#
|
||||
|
@ -63,11 +64,16 @@ def get_input_lines(name):
|
|||
return logs.readlines()
|
||||
|
||||
|
||||
def print_summary(warning_types):
|
||||
print("Warnings grouped by type:\n")
|
||||
summary = list(warning_types.items())
|
||||
def find_longest_name_length(names):
|
||||
return max(len(x) for x in names)
|
||||
|
||||
|
||||
def print_summary(issues):
|
||||
summary = list(issues.items())
|
||||
size = find_longest_name_length(issues.keys()) + 1
|
||||
for warning, count in sorted(summary, key=lambda x: -x[1]):
|
||||
print(' {:28s}: {}'.format(warning, count))
|
||||
print(' {text:{field_size}s}: {count}'.format(
|
||||
text=warning, count=count, field_size=size))
|
||||
print()
|
||||
|
||||
|
||||
|
@ -77,10 +83,11 @@ def main():
|
|||
for line in get_input_lines(sys.argv[1]):
|
||||
total += count_warning(line, warning_types)
|
||||
if warning_types:
|
||||
print("Warnings grouped by type:\n")
|
||||
print_summary(warning_types)
|
||||
print('Total: {} warnings\n'.format(total))
|
||||
if total > MAX_WARNINGS:
|
||||
print('Error: upper limit of warnings is', MAX_WARNINGS)
|
||||
print('Total: {} warnings (out of {} allowed)\n'.format(total, MAX_ISSUES))
|
||||
if total > MAX_ISSUES:
|
||||
print('Error: upper limit of allowed warnings is', MAX_ISSUES)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue