mirror of
https://github.com/SCST-project/scst.git
synced 2026-07-19 14:32:30 +00:00
736651c630
Run run-regression-tests in analyzer-only mode for push and pull request events. Report findings as warnings and upload logs for review.
307 lines
9.2 KiB
YAML
307 lines
9.2 KiB
YAML
name: Static analysis
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- master
|
|
pull_request:
|
|
branches:
|
|
- master
|
|
workflow_dispatch:
|
|
inputs:
|
|
kernel_version:
|
|
description: Kernel version to pass to scripts/run-regression-tests.
|
|
required: false
|
|
default: '7.0'
|
|
type: string
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
|
|
concurrency:
|
|
group: ${{github.workflow}}-${{github.event.pull_request.number || github.ref}}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
sparse_smatch:
|
|
name: sparse and smatch
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 120
|
|
env:
|
|
KERNEL_VERSION: ${{github.event.inputs.kernel_version || '7.0'}}
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v5
|
|
|
|
- name: Select kernel version
|
|
id: kernel
|
|
run: |
|
|
artifact_kernel="$(printf '%s' "${KERNEL_VERSION}" |
|
|
tr -c 'A-Za-z0-9._-' '-')"
|
|
|
|
echo "artifact-name=static-analysis-${artifact_kernel}" \
|
|
>> "${GITHUB_OUTPUT}"
|
|
echo "Kernel version: ${KERNEL_VERSION}" >> "${GITHUB_STEP_SUMMARY}"
|
|
|
|
- name: Cache kernel sources
|
|
uses: actions/cache@v5
|
|
with:
|
|
path: ~/.cache/scst-kernels
|
|
key: scst-kernels-${{runner.os}}-${{env.KERNEL_VERSION}}
|
|
restore-keys: |
|
|
scst-kernels-${{runner.os}}-
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y \
|
|
bc \
|
|
bison \
|
|
build-essential \
|
|
flex \
|
|
libelf-dev \
|
|
libsqlite3-dev \
|
|
libssl-dev \
|
|
sparse \
|
|
wget \
|
|
xz-utils
|
|
|
|
- name: Install smatch
|
|
run: |
|
|
git clone --depth=1 https://github.com/error27/smatch.git
|
|
make -j"$(nproc)" -C smatch
|
|
sudo BINDIR=/bin SHAREDIR=/home/runner/share make -C smatch install
|
|
|
|
- name: Run sparse and smatch
|
|
run: |
|
|
set -u
|
|
|
|
workdir="${RUNNER_TEMP}/scst-static-analysis"
|
|
artifactdir="${RUNNER_TEMP}/scst-static-analysis-artifacts"
|
|
raw_log="${workdir}/run-regression-tests.log"
|
|
log="${artifactdir}/run-regression-tests.log"
|
|
path_list="${artifactdir}/scst-analysis-paths.txt"
|
|
|
|
append_summary() {
|
|
printf '%s\n' "$@" >> "${GITHUB_STEP_SUMMARY}"
|
|
}
|
|
|
|
print_progress_log() {
|
|
awk '
|
|
/^[[:space:]]*[0-9]+ errors? \/ [0-9]+ warnings?\.$/ {
|
|
next
|
|
}
|
|
|
|
/ info:| warning:| warn:| error:/ {
|
|
next
|
|
}
|
|
|
|
/^make\[[0-9]+\]: (Entering|Leaving) directory/ {
|
|
next
|
|
}
|
|
|
|
/^[[:space:]]*(CC|CHECK|LD|MODPOST)[[:space:]\[]/ {
|
|
next
|
|
}
|
|
|
|
/^[[:space:]]*WARNING:/ {
|
|
next
|
|
}
|
|
|
|
{
|
|
print
|
|
}
|
|
'
|
|
}
|
|
|
|
build_scst_path_list() {
|
|
{
|
|
printf '%s\n' \
|
|
'drivers/scst/' \
|
|
'include/scst/' \
|
|
'dev_handlers/' \
|
|
'fcst/' \
|
|
'iscsi-scst/' \
|
|
'srpt/' \
|
|
'scst_local/'
|
|
|
|
while IFS= read -r -d '' patch; do
|
|
# shellcheck disable=SC2016
|
|
awk '
|
|
function emit_path(path, alias) {
|
|
if (path == "" || path == "/dev/null")
|
|
return
|
|
|
|
print path
|
|
if (path !~ /[.][ch]$/)
|
|
return
|
|
|
|
alias = path
|
|
sub(/^drivers\/scst\//, "", alias)
|
|
if (alias != path)
|
|
print alias
|
|
|
|
alias = path
|
|
sub(/^include\/scst\//, "", alias)
|
|
if (alias != path)
|
|
print alias
|
|
|
|
alias = path
|
|
sub(/^drivers\/scsi\/qla2xxx\//, "", alias)
|
|
if (alias != path)
|
|
print alias
|
|
|
|
alias = path
|
|
sub(/^.*\//, "", alias)
|
|
if (alias != path)
|
|
print alias
|
|
}
|
|
|
|
/^\+\+\+ / {
|
|
path = $2
|
|
sub(/^b\//, "", path)
|
|
sub(/^linux-[^/]+\//, "", path)
|
|
emit_path(path)
|
|
}
|
|
' "${patch}"
|
|
done < <(
|
|
find "${workdir}" -path "${workdir}/patchdir-*/*" \
|
|
-type f -print0
|
|
)
|
|
} | sed '/^$/d' | sort -u > "${path_list}"
|
|
}
|
|
|
|
filter_scst_findings() {
|
|
awk '
|
|
FILENAME == ARGV[1] {
|
|
paths[++n] = $0
|
|
next
|
|
}
|
|
|
|
function normalize(line) {
|
|
gsub(/ error:/, " warning:", line)
|
|
gsub(/ warn:/, " warning:", line)
|
|
return line
|
|
}
|
|
|
|
function is_scst_line(line, i) {
|
|
for (i = 1; i <= n; i++)
|
|
if (index(line, paths[i]) > 0)
|
|
return 1
|
|
return 0
|
|
}
|
|
|
|
/^[[:space:]]*[0-9]+ errors? \/ [0-9]+ warnings?\.$/ {
|
|
next
|
|
}
|
|
|
|
/ warning:| warn:| error:/ {
|
|
if (is_scst_line($0))
|
|
print normalize($0)
|
|
next
|
|
}
|
|
' "${path_list}" -
|
|
}
|
|
|
|
count_findings() {
|
|
grep -E -c ' warning:| warn:| error:' "$1" || true
|
|
}
|
|
|
|
rm -rf "${workdir}" "${artifactdir}"
|
|
mkdir -p "${workdir}" "${artifactdir}" "${HOME}/.cache/scst-kernels"
|
|
|
|
set +e
|
|
./scripts/run-regression-tests \
|
|
-l \
|
|
-q \
|
|
-c "${HOME}/.cache/scst-kernels" \
|
|
-d "${workdir}" \
|
|
"${KERNEL_VERSION}-nc-nb" 2>&1 \
|
|
| tee "${raw_log}" \
|
|
| print_progress_log \
|
|
| tee "${log}"
|
|
status="${PIPESTATUS[0]}"
|
|
set -e
|
|
|
|
build_scst_path_list
|
|
|
|
append_summary "" "### sparse and smatch" ""
|
|
|
|
if [ "${status}" -ne 0 ]; then
|
|
printf '::warning title=Static analysis::%s\n' \
|
|
"run-regression-tests exited with status ${status}"
|
|
append_summary \
|
|
"run-regression-tests exited with status ${status}." \
|
|
""
|
|
fi
|
|
|
|
found_outputs=false
|
|
for output in "${workdir}"/sparse-*-output.txt "${workdir}"/smatch-*-output.txt; do
|
|
[ -e "${output}" ] || continue
|
|
|
|
found_outputs=true
|
|
title="$(basename "${output}")"
|
|
analyzer="${title%%-*}"
|
|
filtered_all="${workdir}/${title%.txt}-scst-all.txt"
|
|
filtered="${artifactdir}/${title%.txt}-scst-only.txt"
|
|
filter_scst_findings < "${output}" > "${filtered_all}"
|
|
awk '!seen[$0]++' "${filtered_all}" > "${filtered}"
|
|
findings="$(awk 'END { print NR }' "${filtered}")"
|
|
scst_findings="$(awk 'END { print NR }' "${filtered_all}")"
|
|
total_findings="$(count_findings "${output}")"
|
|
duplicate_findings=$((scst_findings - findings))
|
|
suppressed_findings=$((total_findings - scst_findings))
|
|
|
|
printf '%s: %s SCST warnings (%s external, %s duplicates hidden)\n' \
|
|
"${analyzer}" \
|
|
"${findings}" \
|
|
"${suppressed_findings}" \
|
|
"${duplicate_findings}"
|
|
append_summary "- ${analyzer}: ${findings} warnings (${title})"
|
|
hidden_summary=" ${suppressed_findings} external and"
|
|
hidden_summary+=" ${duplicate_findings} duplicate warnings hidden."
|
|
append_summary "${hidden_summary}"
|
|
if [ "${findings}" -gt 0 ]; then
|
|
printf '===== %s SCST warnings =====\n' "${analyzer}"
|
|
head -100 "${filtered}"
|
|
printf '::warning title=%s::%s SCST warnings from %s; see logs.\n' \
|
|
"${analyzer}" "${findings}" "${analyzer}"
|
|
fi
|
|
done
|
|
|
|
if [ "${found_outputs}" = false ]; then
|
|
echo "::warning title=Static analysis::No sparse or smatch output files were produced."
|
|
append_summary "No sparse or smatch output files were produced."
|
|
fi
|
|
|
|
append_summary \
|
|
"" \
|
|
"<details><summary>First findings</summary>" \
|
|
"" \
|
|
'```text'
|
|
for output in "${artifactdir}"/sparse-*-scst-only.txt \
|
|
"${artifactdir}"/smatch-*-scst-only.txt; do
|
|
[ -e "${output}" ] || continue
|
|
|
|
{
|
|
printf '===== %s =====\n' "$(basename "${output}")"
|
|
head -100 "${output}"
|
|
} >> "${GITHUB_STEP_SUMMARY}"
|
|
done
|
|
append_summary '```' "</details>"
|
|
|
|
exit 0
|
|
|
|
- name: Upload analysis logs
|
|
if: always()
|
|
uses: actions/upload-artifact@v6
|
|
with:
|
|
name: ${{steps.kernel.outputs.artifact-name}}
|
|
path: ${{runner.temp}}/scst-static-analysis-artifacts
|
|
if-no-files-found: warn
|
|
retention-days: 14
|