feat: Add support for executing the report-converter tool

This commit is contained in:
Whisperity
2022-03-26 11:09:05 +01:00
parent 14d6da98f7
commit 61bccd7593
5 changed files with 199 additions and 18 deletions

View File

@@ -61,7 +61,6 @@ jobs:
name: "Simple analysis: ${{ matrix.logfile && 'logfile' || 'no logfile' }}, ${{ matrix.build-command && 'build-command' || 'no build-command' }}, ${{ matrix.analyze-output && 'analyze-output' || 'no analyze-output'}}"
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- run: test/fix_compile_json_paths.sh
@@ -105,6 +104,29 @@ jobs:
- name: "Reject test if previous step did not produce CTU finding"
run: cat ${{ steps.codechecker.outputs.result-log }} | grep "Dereference of null pointer"
report-converter:
name: "Report converter: PyLint"
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: "Install PyLint"
run: |
sudo apt-get install -y pylint
- name: "Perform static analysis explicitly with PyLint"
run: |
pylint test/report-converter/testpylint.py \
-f json \
--exit-zero \
> ./pylint_reports.json
- uses: ./
id: codechecker
with:
report-converter: true
original-analyser: 'pylint'
original-analysis-output: './pylint_reports.json'
- name: "Reject test if previous step did not produce findings"
run: cat ${{ steps.codechecker.outputs.result-log }} | grep "Explicit return in __init__"
reports-errors:
name: "Parse: Findings are reported"
runs-on: ubuntu-20.04
@@ -219,7 +241,7 @@ jobs:
runs-on: ubuntu-20.04
if: ${{ github.event_name == 'push' }}
env:
CODECHECKER_VERSION: '6.18.1'
CODECHECKER_VERSION: '6.19.1'
steps:
- uses: actions/checkout@v2
- run: test/fix_compile_json_paths.sh
@@ -240,11 +262,11 @@ jobs:
name: "Diff: New findings are discovered and reported"
runs-on: ubuntu-20.04
env:
CODECHECKER_VERSION: '6.18.1'
CODECHECKER_VERSION: '6.19.1'
# This time, we do not need authentication, so test with the official Docker subsystem.
services:
codechecker-server:
image: 'codechecker/codechecker-web:6.18.1'
image: 'codechecker/codechecker-web:6.19.1'
ports:
- 8001:8001/tcp
steps:

View File

@@ -1,10 +1,10 @@
# [CodeChecker](http://github.com/Ericsson/CodeChecker/) C++ Static Analysis action
GitHub Action to execute static analysis over C-family projects (C, C++,
Objective-C) using the [Clang](http://clang.llvm.org/) infrastructure and
[CodeChecker](http://github.com/Ericsson/CodeChecker/) as its driver.
GitHub Action to execute static analysis over using [CodeChecker](http://github.com/Ericsson/CodeChecker/) as its driver.
For C-family projects (C, C++, Objective-C, CUDA, etc.), CodeChecker supports driving the static analysis programs of [Clang](http://clang.llvm.org).
Several other static analysers' output can be integrated into CodeChecker through the [report converter](http://codechecker.readthedocs.io/en/latest/tools/report-converter/).
## Overview
## Overview (for C-family projects)
⚠️ **CAUTION! This action has been written with commands that target Ubuntu-based distributions!**
@@ -238,6 +238,60 @@ runs:
exit 1
```
## Overview (for other analyses through the _report-converter_)
⚠️ **CAUTION! This action has been written with commands that target Ubuntu-based distributions!**
This single action composite script encompasses the following steps:
1. Obtain a package of CodeChecker.
3. Use the `report-converter` to convert other analysers' reports to CodeChecker's format.
4. Show the analysis results in the CI log, and create HTML reports that can be uploaded as an artefact. (Uploading is to be done by the user!)
5. _(Optional)_ Check for the current commit introducing new bug reports against a known state. (Good for pull requests!)
6. _(Optional)_ Upload the results to a running _CodeChecker server_. (Good for the main project!)
**Note:** Static analysis can be a time-consuming process.
It's recommended that the static analysis step is not sequential with the rest of a CI execution, but either runs as its own job in a workflow, or a completely distinct workflow altogether.
Please refer to the documentation of the analyser of your choice for this.
CodeChecker does **NOT** support driving the analysis through external tools, but if a successful analysis had been done, it can convert and store the results.
```yaml
job:
steps:
# Check YOUR project out!
- name: "Check out repository"
uses: actions/checkout@v2
# Perform the analysis. Details vary between analysers!
# Example for "PyLint" added below!
- name: "Analyse with PyLint"
run: |
sudo apt-get -y install pylint
pylint -f json --exit-zero myproject > pylint_reports.json
# Run the conversion
- uses: whisperity/codechecker-analysis-action@v1
id: codechecker
with:
report-converter: true
original-analyser: "pylint"
original-analysis-output: "pylint_reports.json"
# Upload the results (after conversion by CodeChecker) to the CI.
- uses: actions/upload-artifact@v2
with:
name: "CodeChecker Bug Reports"
path: ${{ steps.codechecker.outputs.result-html-dir }}
```
### Uploading results and acting as a CI gate
The _report-converter_ tool converts the output of various analysers to the common format used by CodeChecker.
Once the conversion is done, the rest of the action's features can execute in the same fashion as for C/C++ projects.
Please refer to earlier parts of the documentation for the configuration of these features.
## Action configuration
| Variable | Default | Description |
@@ -276,6 +330,16 @@ runs:
🔖 Read more about [`CodeChecker parse`](http://codechecker.readthedocs.io/en/latest/analyzer/user_guide/#parse) in the official documentation.
### Report conversion configuration
🔖 Read more about the [`report-converter`](http://codechecker.readthedocs.io/en/latest/tools/report-converter/) in the official documentation.
| Variable | Default | Description |
|----------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------|
| `report-converter` | `false` | If set to `true`, the job will execute _report conversion_ from other analysers instead of driving the static analysis by itself. |
| `original-analyser` | | The "type" of the analysis that **had been performed** earlier. Passed as mandatory input to the `report-converter` executable. |
| `original-analysis-output` | | The file or directory where the results of the third-party analyser are available. Passed as mandatory input to the `report-converter` executable. |
### Diff configuration
🔖 Read more about [`CodeChecker cmd diff`](http://codechecker.readthedocs.io/en/latest/analyzer/web_guide/#cmd-diff) in the official documentation.
@@ -310,7 +374,7 @@ The action exposes the following outputs which may be used in a workflow's steps
| Variable | Value | Description |
|--------------------|-------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|
| `analyze-output` | Auto-generated, or `analyze-output` input | The directory where the **raw** analysis output files are available. |
| `analyze-output` | Auto-generated, or `analyze-output` input | The directory where the **raw** analysis output files (either created by the analysers, or by the converter) are available. |
| `logfile` | Auto-generated, or `logfile` input | The JSON Compilation Database of the analysis that was executed. |
| `diff-html-dir` | Auto-generated. | The directory where the **user-friendly HTML** bug reports were generated to about the **new** findings (if `diff` was enabled). |
| `diff-result-log` | Auto-generated. | `CodeChecker cmd diff`'s output log file which contains the **new** findings dumped into it. |

View File

@@ -47,6 +47,17 @@ inputs:
required: true
default: 'true'
report-converter:
description: 'Whether to perform report conversion from analyses executed by third-party analysers instead of driving the analysis via CodeChecker directly.'
required: true
default: 'false'
original-analyser:
description: 'The type of the third-party analyser which performed the analysis. Passed to the report converter executable, as a mandatory input parameter.'
required: false
original-analysis-output:
description: 'The location of the analysis data emitted by the third-party analyser. Passed to the report converter executable, as a mandatory input parameter.'
required: false
diff:
description: 'Whether to enable calculating the different of the current analysis results against a run stored on a CodeChecker server. If enabled, other flags, such as "diff-url" must also be set.'
required: true
@@ -89,8 +100,8 @@ outputs:
value: ${{ steps.log.outputs.COMPILATION_DATABASE }}
analyze-output:
description: 'The output directory where the raw analysis output was stored to.'
value: ${{ steps.analyze.outputs.OUTPUT_DIR }}
description: 'The output directory where the raw analysis or converted output was stored to.'
value: ${{ steps.analyze-or-report.outputs.OUTPUT_DIR }}
warnings:
description: 'Whether the static analyser(s) reported any findings.'
@@ -135,7 +146,7 @@ runs:
- name: "Install LLVM (${{ inputs.llvm-version }})"
id: llvm
if: ${{ inputs.llvm-version != 'ignore' }}
if: ${{ inputs.llvm-version != 'ignore' && inputs.report-converter != 'true' }}
env:
IN_LLVM_VERSION: ${{ inputs.llvm-version }}
shell: bash
@@ -159,6 +170,7 @@ runs:
- name: "Prepare JSON Compilation Database"
id: log
if: ${{ inputs.report-converter != 'true' }}
env:
ACTION_NAME: ${{ github.action }}
CODECHECKER_PATH: ${{ steps.codechecker.outputs.PATH }}
@@ -170,8 +182,9 @@ runs:
shell: bash
run: ${{ github.action_path }}/src/get-or-create-build-json.sh
- name: "Execute static analysis"
- name: "Execute static analysis for C/C++"
id: analyze
if: ${{ inputs.report-converter != 'true' }}
env:
CODECHECKER_PATH: ${{ steps.codechecker.outputs.PATH }}
COMPILATION_DATABASE: ${{ steps.log.outputs.COMPILATION_DATABASE }}
@@ -179,18 +192,48 @@ runs:
IN_CONFIGFILE: ${{ inputs.config }}
IN_CTU: ${{ inputs.ctu }}
IN_FLAGS: ${{ inputs.analyze-options }}
IN_IGNORE_CRASHES: ${{ inputs.ignore-analyze-crashes }}
IN_OUTPUT_DIR: ${{ inputs.analyze-output }}
shell: bash
run: ${{ github.action_path }}/src/execute-analysis.sh
- name: "Parse and convert results"
- name: "Perform report-converter"
id: report-convert
if: ${{ inputs.report-converter == 'true' }}
env:
CODECHECKER_PATH: ${{ steps.codechecker.outputs.PATH }}
GITHUB_ACTION_NAME: ${{ github.action }}
IN_ORIGINAL_ANALYSER: ${{ inputs.original-analyser }}
IN_ORIGINAL_ANALYSIS_OUTPUT: ${{ inputs.original-analysis-output }}
IN_IGNORE_CRASHES: ${{ inputs.ignore-analyze-crashes }}
IN_OUTPUT_DIR: ${{ inputs.analyze-output }}
shell: bash
run: ${{ github.action_path }}/src/report-converter.sh
# This step is needed because it is forbidden to reuse the 'id' of a step,
# even if the two steps taking the same 'id' are mutually exclusive.
- name: "(Internal: set output variables for steps after analyze/convert)"
id: analyze-or-report
shell: bash
run: |
if [[ ! -z "$CODECHECKER_ACTION_DEBUG" ]]; then
set -x
fi
if [[ "${{ inputs.report-converter }}" != "true" ]]
then
echo "::set-output name=OUTPUT_DIR::${{ steps.analyze.outputs.OUTPUT_DIR }}"
else
echo "::set-output name=OUTPUT_DIR::${{ steps.report-convert.outputs.OUTPUT_DIR }}"
fi
- name: "Parse and convert results to HTML"
id: parse
env:
PROJECT_PATH: ${{ github.workspace }}
CODECHECKER_PATH: ${{ steps.codechecker.outputs.PATH }}
RAW_RESULT_DIR: ${{ steps.analyze.outputs.OUTPUT_DIR }}
RAW_RESULT_DIR: ${{ steps.analyze-or-report.outputs.OUTPUT_DIR }}
IN_CONFIGFILE: ${{ inputs.config }}
shell: bash
@@ -220,7 +263,7 @@ runs:
PROJECT_PATH: ${{ github.workspace }}
CODECHECKER_PATH: ${{ steps.codechecker.outputs.PATH }}
CODECHECKER_DIFF_RUN_NAME: ${{ steps.diff-pre.outputs.RUN_NAME }}
RAW_RESULT_DIR: ${{ steps.analyze.outputs.OUTPUT_DIR }}
RAW_RESULT_DIR: ${{ steps.analyze-or-report.outputs.OUTPUT_DIR }}
IN_CONFIGFILE: ${{ inputs.config }}
IN_DIFF_URL: ${{ inputs.diff-url }}
@@ -251,7 +294,7 @@ runs:
CODECHECKER_PATH: ${{ steps.codechecker.outputs.PATH }}
CODECHECKER_STORE_RUN_NAME: ${{ steps.store-pre.outputs.RUN_NAME }}
CODECHECKER_STORE_RUN_TAG: ${{ steps.store-pre.outputs.RUN_TAG }}
RAW_RESULT_DIR: ${{ steps.analyze.outputs.OUTPUT_DIR }}
RAW_RESULT_DIR: ${{ steps.analyze-or-report.outputs.OUTPUT_DIR }}
IN_CONFIGFILE: ${{ inputs.config }}
IN_STORE_URL: ${{ inputs.store-url }}

48
src/report-converter.sh Executable file
View File

@@ -0,0 +1,48 @@
#!/bin/bash
if [[ ! -z "$CODECHECKER_ACTION_DEBUG" ]]; then
set -x
fi
echo "::group::Preparing for conversion"
if [[ -z "$IN_ORIGINAL_ANALYSER" ]]; then
echo "::error title=Internal error::environment variable 'IN_ORIGINAL_ANALYSER' missing!"
exit 1
fi
if [[ -z "$IN_ORIGINAL_ANALYSIS_OUTPUT" ]]; then
echo "::error title=Internal error::environment variable 'IN_ORIGINAL_ANALYSIS_OUTPUT' missing!"
exit 1
fi
OUTPUT_DIR="$IN_OUTPUT_DIR"
if [[ -z "$OUTPUT_DIR" ]]; then
OUTPUT_DIR=~/"$GITHUB_ACTION_NAME"_Results
fi
mkdir -pv "$(dirname $"OUTPUT_DIR")"
# Report-Converter does not support a config file. :(
# if [[ ! -z "$IN_CONFIGFILE" ]]; then
# CONFIG_FLAG_1="--config"
# CONFIG_FLAG_2=$IN_CONFIGFILE
# echo "Using configuration file \"$IN_CONFIGFILE\"!"
# fi
echo "::endgroup::"
echo "::group::Performing conversion"
"$CODECHECKER_PATH"/report-converter \
"$IN_ORIGINAL_ANALYSIS_OUTPUT" \
--type "$IN_ORIGINAL_ANALYSER" \
--output "$OUTPUT_DIR" \
--export plist
EXIT_CODE=$?
echo "::endgroup::"
if [[ $EXIT_CODE -ne 0 && "$IN_IGNORE_CRASHES" == "true" ]]; then
# In general it is a good idea not to destroy the entire job just because a
# few translation units failed. Crashes are, unfortunately, usual.
echo "::warning title=Report Converter crashed on some inputs::Some of the analysis results failed to convert due to internal error."
EXIT_CODE=0
fi
echo "::set-output name=OUTPUT_DIR::$OUTPUT_DIR"
exit $EXIT_CODE

View File

@@ -0,0 +1,4 @@
class ReturnInInitE0101:
def __init__(self, value):
# Should trigger "return-in-init"
return value