Skip to content

Commit 61bccd7

Browse files
committed
feat: Add support for executing the report-converter tool
1 parent 14d6da9 commit 61bccd7

File tree

5 files changed

+199
-18
lines changed

5 files changed

+199
-18
lines changed

.github/workflows/test.yml

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ jobs:
6161
name: "Simple analysis: ${{ matrix.logfile && 'logfile' || 'no logfile' }}, ${{ matrix.build-command && 'build-command' || 'no build-command' }}, ${{ matrix.analyze-output && 'analyze-output' || 'no analyze-output'}}"
6262
runs-on: ubuntu-20.04
6363

64-
6564
steps:
6665
- uses: actions/checkout@v2
6766
- run: test/fix_compile_json_paths.sh
@@ -105,6 +104,29 @@ jobs:
105104
- name: "Reject test if previous step did not produce CTU finding"
106105
run: cat ${{ steps.codechecker.outputs.result-log }} | grep "Dereference of null pointer"
107106

107+
report-converter:
108+
name: "Report converter: PyLint"
109+
runs-on: ubuntu-20.04
110+
steps:
111+
- uses: actions/checkout@v2
112+
- name: "Install PyLint"
113+
run: |
114+
sudo apt-get install -y pylint
115+
- name: "Perform static analysis explicitly with PyLint"
116+
run: |
117+
pylint test/report-converter/testpylint.py \
118+
-f json \
119+
--exit-zero \
120+
> ./pylint_reports.json
121+
- uses: ./
122+
id: codechecker
123+
with:
124+
report-converter: true
125+
original-analyser: 'pylint'
126+
original-analysis-output: './pylint_reports.json'
127+
- name: "Reject test if previous step did not produce findings"
128+
run: cat ${{ steps.codechecker.outputs.result-log }} | grep "Explicit return in __init__"
129+
108130
reports-errors:
109131
name: "Parse: Findings are reported"
110132
runs-on: ubuntu-20.04
@@ -219,7 +241,7 @@ jobs:
219241
runs-on: ubuntu-20.04
220242
if: ${{ github.event_name == 'push' }}
221243
env:
222-
CODECHECKER_VERSION: '6.18.1'
244+
CODECHECKER_VERSION: '6.19.1'
223245
steps:
224246
- uses: actions/checkout@v2
225247
- run: test/fix_compile_json_paths.sh
@@ -240,11 +262,11 @@ jobs:
240262
name: "Diff: New findings are discovered and reported"
241263
runs-on: ubuntu-20.04
242264
env:
243-
CODECHECKER_VERSION: '6.18.1'
265+
CODECHECKER_VERSION: '6.19.1'
244266
# This time, we do not need authentication, so test with the official Docker subsystem.
245267
services:
246268
codechecker-server:
247-
image: 'codechecker/codechecker-web:6.18.1'
269+
image: 'codechecker/codechecker-web:6.19.1'
248270
ports:
249271
- 8001:8001/tcp
250272
steps:

README.md

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# [CodeChecker](http://github.com/Ericsson/CodeChecker/) C++ Static Analysis action
22

3-
GitHub Action to execute static analysis over C-family projects (C, C++,
4-
Objective-C) using the [Clang](http://clang.llvm.org/) infrastructure and
5-
[CodeChecker](http://github.com/Ericsson/CodeChecker/) as its driver.
3+
GitHub Action to execute static analysis over using [CodeChecker](http://github.com/Ericsson/CodeChecker/) as its driver.
4+
For C-family projects (C, C++, Objective-C, CUDA, etc.), CodeChecker supports driving the static analysis programs of [Clang](http://clang.llvm.org).
5+
Several other static analysers' output can be integrated into CodeChecker through the [report converter](http://codechecker.readthedocs.io/en/latest/tools/report-converter/).
66

7-
## Overview
7+
## Overview (for C-family projects)
88

99
⚠️ **CAUTION! This action has been written with commands that target Ubuntu-based distributions!**
1010

@@ -238,6 +238,60 @@ runs:
238238
exit 1
239239
```
240240

241+
## Overview (for other analyses through the _report-converter_)
242+
243+
⚠️ **CAUTION! This action has been written with commands that target Ubuntu-based distributions!**
244+
245+
This single action composite script encompasses the following steps:
246+
247+
1. Obtain a package of CodeChecker.
248+
3. Use the `report-converter` to convert other analysers' reports to CodeChecker's format.
249+
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!)
250+
5. _(Optional)_ Check for the current commit introducing new bug reports against a known state. (Good for pull requests!)
251+
6. _(Optional)_ Upload the results to a running _CodeChecker server_. (Good for the main project!)
252+
253+
254+
ℹ️ **Note:** Static analysis can be a time-consuming process.
255+
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.
256+
257+
Please refer to the documentation of the analyser of your choice for this.
258+
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.
259+
260+
```yaml
261+
job:
262+
steps:
263+
# Check YOUR project out!
264+
- name: "Check out repository"
265+
uses: actions/checkout@v2
266+
267+
# Perform the analysis. Details vary between analysers!
268+
# Example for "PyLint" added below!
269+
- name: "Analyse with PyLint"
270+
run: |
271+
sudo apt-get -y install pylint
272+
pylint -f json --exit-zero myproject > pylint_reports.json
273+
274+
# Run the conversion
275+
- uses: whisperity/codechecker-analysis-action@v1
276+
id: codechecker
277+
with:
278+
report-converter: true
279+
original-analyser: "pylint"
280+
original-analysis-output: "pylint_reports.json"
281+
282+
# Upload the results (after conversion by CodeChecker) to the CI.
283+
- uses: actions/upload-artifact@v2
284+
with:
285+
name: "CodeChecker Bug Reports"
286+
path: ${{ steps.codechecker.outputs.result-html-dir }}
287+
```
288+
289+
### Uploading results and acting as a CI gate
290+
291+
The _report-converter_ tool converts the output of various analysers to the common format used by CodeChecker.
292+
Once the conversion is done, the rest of the action's features can execute in the same fashion as for C/C++ projects.
293+
Please refer to earlier parts of the documentation for the configuration of these features.
294+
241295
## Action configuration
242296

243297
| Variable | Default | Description |
@@ -276,6 +330,16 @@ runs:
276330

277331
🔖 Read more about [`CodeChecker parse`](http://codechecker.readthedocs.io/en/latest/analyzer/user_guide/#parse) in the official documentation.
278332

333+
### Report conversion configuration
334+
335+
🔖 Read more about the [`report-converter`](http://codechecker.readthedocs.io/en/latest/tools/report-converter/) in the official documentation.
336+
337+
| Variable | Default | Description |
338+
|----------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------|
339+
| `report-converter` | `false` | If set to `true`, the job will execute _report conversion_ from other analysers instead of driving the static analysis by itself. |
340+
| `original-analyser` | | The "type" of the analysis that **had been performed** earlier. Passed as mandatory input to the `report-converter` executable. |
341+
| `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. |
342+
279343
### Diff configuration
280344

281345
🔖 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
310374

311375
| Variable | Value | Description |
312376
|--------------------|-------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|
313-
| `analyze-output` | Auto-generated, or `analyze-output` input | The directory where the **raw** analysis output files are available. |
377+
| `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. |
314378
| `logfile` | Auto-generated, or `logfile` input | The JSON Compilation Database of the analysis that was executed. |
315379
| `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). |
316380
| `diff-result-log` | Auto-generated. | `CodeChecker cmd diff`'s output log file which contains the **new** findings dumped into it. |

action.yml

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,17 @@ inputs:
4747
required: true
4848
default: 'true'
4949

50+
report-converter:
51+
description: 'Whether to perform report conversion from analyses executed by third-party analysers instead of driving the analysis via CodeChecker directly.'
52+
required: true
53+
default: 'false'
54+
original-analyser:
55+
description: 'The type of the third-party analyser which performed the analysis. Passed to the report converter executable, as a mandatory input parameter.'
56+
required: false
57+
original-analysis-output:
58+
description: 'The location of the analysis data emitted by the third-party analyser. Passed to the report converter executable, as a mandatory input parameter.'
59+
required: false
60+
5061
diff:
5162
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.'
5263
required: true
@@ -89,8 +100,8 @@ outputs:
89100
value: ${{ steps.log.outputs.COMPILATION_DATABASE }}
90101

91102
analyze-output:
92-
description: 'The output directory where the raw analysis output was stored to.'
93-
value: ${{ steps.analyze.outputs.OUTPUT_DIR }}
103+
description: 'The output directory where the raw analysis or converted output was stored to.'
104+
value: ${{ steps.analyze-or-report.outputs.OUTPUT_DIR }}
94105

95106
warnings:
96107
description: 'Whether the static analyser(s) reported any findings.'
@@ -135,7 +146,7 @@ runs:
135146

136147
- name: "Install LLVM (${{ inputs.llvm-version }})"
137148
id: llvm
138-
if: ${{ inputs.llvm-version != 'ignore' }}
149+
if: ${{ inputs.llvm-version != 'ignore' && inputs.report-converter != 'true' }}
139150
env:
140151
IN_LLVM_VERSION: ${{ inputs.llvm-version }}
141152
shell: bash
@@ -159,6 +170,7 @@ runs:
159170
160171
- name: "Prepare JSON Compilation Database"
161172
id: log
173+
if: ${{ inputs.report-converter != 'true' }}
162174
env:
163175
ACTION_NAME: ${{ github.action }}
164176
CODECHECKER_PATH: ${{ steps.codechecker.outputs.PATH }}
@@ -170,27 +182,58 @@ runs:
170182
shell: bash
171183
run: ${{ github.action_path }}/src/get-or-create-build-json.sh
172184

173-
- name: "Execute static analysis"
185+
- name: "Execute static analysis for C/C++"
174186
id: analyze
187+
if: ${{ inputs.report-converter != 'true' }}
175188
env:
176189
CODECHECKER_PATH: ${{ steps.codechecker.outputs.PATH }}
177190
COMPILATION_DATABASE: ${{ steps.log.outputs.COMPILATION_DATABASE }}
178191
GITHUB_ACTION_NAME: ${{ github.action }}
179192

180193
IN_CONFIGFILE: ${{ inputs.config }}
181194
IN_CTU: ${{ inputs.ctu }}
182-
IN_FLAGS: ${{ inputs.analyze-options }}
183195
IN_IGNORE_CRASHES: ${{ inputs.ignore-analyze-crashes }}
184196
IN_OUTPUT_DIR: ${{ inputs.analyze-output }}
185197
shell: bash
186198
run: ${{ github.action_path }}/src/execute-analysis.sh
187199

188-
- name: "Parse and convert results"
200+
- name: "Perform report-converter"
201+
id: report-convert
202+
if: ${{ inputs.report-converter == 'true' }}
203+
env:
204+
CODECHECKER_PATH: ${{ steps.codechecker.outputs.PATH }}
205+
GITHUB_ACTION_NAME: ${{ github.action }}
206+
207+
IN_ORIGINAL_ANALYSER: ${{ inputs.original-analyser }}
208+
IN_ORIGINAL_ANALYSIS_OUTPUT: ${{ inputs.original-analysis-output }}
209+
IN_IGNORE_CRASHES: ${{ inputs.ignore-analyze-crashes }}
210+
IN_OUTPUT_DIR: ${{ inputs.analyze-output }}
211+
shell: bash
212+
run: ${{ github.action_path }}/src/report-converter.sh
213+
214+
# This step is needed because it is forbidden to reuse the 'id' of a step,
215+
# even if the two steps taking the same 'id' are mutually exclusive.
216+
- name: "(Internal: set output variables for steps after analyze/convert)"
217+
id: analyze-or-report
218+
shell: bash
219+
run: |
220+
if [[ ! -z "$CODECHECKER_ACTION_DEBUG" ]]; then
221+
set -x
222+
fi
223+
224+
if [[ "${{ inputs.report-converter }}" != "true" ]]
225+
then
226+
echo "::set-output name=OUTPUT_DIR::${{ steps.analyze.outputs.OUTPUT_DIR }}"
227+
else
228+
echo "::set-output name=OUTPUT_DIR::${{ steps.report-convert.outputs.OUTPUT_DIR }}"
229+
fi
230+
231+
- name: "Parse and convert results to HTML"
189232
id: parse
190233
env:
191234
PROJECT_PATH: ${{ github.workspace }}
192235
CODECHECKER_PATH: ${{ steps.codechecker.outputs.PATH }}
193-
RAW_RESULT_DIR: ${{ steps.analyze.outputs.OUTPUT_DIR }}
236+
RAW_RESULT_DIR: ${{ steps.analyze-or-report.outputs.OUTPUT_DIR }}
194237

195238
IN_CONFIGFILE: ${{ inputs.config }}
196239
shell: bash
@@ -220,7 +263,7 @@ runs:
220263
PROJECT_PATH: ${{ github.workspace }}
221264
CODECHECKER_PATH: ${{ steps.codechecker.outputs.PATH }}
222265
CODECHECKER_DIFF_RUN_NAME: ${{ steps.diff-pre.outputs.RUN_NAME }}
223-
RAW_RESULT_DIR: ${{ steps.analyze.outputs.OUTPUT_DIR }}
266+
RAW_RESULT_DIR: ${{ steps.analyze-or-report.outputs.OUTPUT_DIR }}
224267

225268
IN_CONFIGFILE: ${{ inputs.config }}
226269
IN_DIFF_URL: ${{ inputs.diff-url }}
@@ -251,7 +294,7 @@ runs:
251294
CODECHECKER_PATH: ${{ steps.codechecker.outputs.PATH }}
252295
CODECHECKER_STORE_RUN_NAME: ${{ steps.store-pre.outputs.RUN_NAME }}
253296
CODECHECKER_STORE_RUN_TAG: ${{ steps.store-pre.outputs.RUN_TAG }}
254-
RAW_RESULT_DIR: ${{ steps.analyze.outputs.OUTPUT_DIR }}
297+
RAW_RESULT_DIR: ${{ steps.analyze-or-report.outputs.OUTPUT_DIR }}
255298

256299
IN_CONFIGFILE: ${{ inputs.config }}
257300
IN_STORE_URL: ${{ inputs.store-url }}

src/report-converter.sh

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/bin/bash
2+
if [[ ! -z "$CODECHECKER_ACTION_DEBUG" ]]; then
3+
set -x
4+
fi
5+
6+
echo "::group::Preparing for conversion"
7+
if [[ -z "$IN_ORIGINAL_ANALYSER" ]]; then
8+
echo "::error title=Internal error::environment variable 'IN_ORIGINAL_ANALYSER' missing!"
9+
exit 1
10+
fi
11+
if [[ -z "$IN_ORIGINAL_ANALYSIS_OUTPUT" ]]; then
12+
echo "::error title=Internal error::environment variable 'IN_ORIGINAL_ANALYSIS_OUTPUT' missing!"
13+
exit 1
14+
fi
15+
16+
OUTPUT_DIR="$IN_OUTPUT_DIR"
17+
if [[ -z "$OUTPUT_DIR" ]]; then
18+
OUTPUT_DIR=~/"$GITHUB_ACTION_NAME"_Results
19+
fi
20+
21+
mkdir -pv "$(dirname $"OUTPUT_DIR")"
22+
23+
# Report-Converter does not support a config file. :(
24+
# if [[ ! -z "$IN_CONFIGFILE" ]]; then
25+
# CONFIG_FLAG_1="--config"
26+
# CONFIG_FLAG_2=$IN_CONFIGFILE
27+
# echo "Using configuration file \"$IN_CONFIGFILE\"!"
28+
# fi
29+
echo "::endgroup::"
30+
31+
echo "::group::Performing conversion"
32+
"$CODECHECKER_PATH"/report-converter \
33+
"$IN_ORIGINAL_ANALYSIS_OUTPUT" \
34+
--type "$IN_ORIGINAL_ANALYSER" \
35+
--output "$OUTPUT_DIR" \
36+
--export plist
37+
EXIT_CODE=$?
38+
echo "::endgroup::"
39+
40+
if [[ $EXIT_CODE -ne 0 && "$IN_IGNORE_CRASHES" == "true" ]]; then
41+
# In general it is a good idea not to destroy the entire job just because a
42+
# few translation units failed. Crashes are, unfortunately, usual.
43+
echo "::warning title=Report Converter crashed on some inputs::Some of the analysis results failed to convert due to internal error."
44+
EXIT_CODE=0
45+
fi
46+
47+
echo "::set-output name=OUTPUT_DIR::$OUTPUT_DIR"
48+
exit $EXIT_CODE
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class ReturnInInitE0101:
2+
def __init__(self, value):
3+
# Should trigger "return-in-init"
4+
return value

0 commit comments

Comments
 (0)