mirror of
https://github.com/whisperity/CodeChecker-Action.git
synced 2026-02-09 22:57:45 +00:00
Wire in the analyze command
This commit is contained in:
38
.github/workflows/test.yml
vendored
38
.github/workflows/test.yml
vendored
@@ -10,8 +10,8 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
# Fetch tests do not produce results, but test the functionality of the
|
# Fetch tests do not produce results, but test the functionality of the
|
||||||
# "grab LLVM" and "grab and build CodeChecker" features.
|
# "grab LLVM" and "grab and build CodeChecker" features.
|
||||||
fetch_ubuntu_2004_latestllvm:
|
fetch_ubuntu-2004_latest-llvm:
|
||||||
name: "Fetch test: Ubuntu Linux 20.04 (latest LLVM)"
|
name: "Fetch: Ubuntu Linux 20.04 (latest LLVM)"
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
@@ -20,8 +20,8 @@ jobs:
|
|||||||
version: "master"
|
version: "master"
|
||||||
llvm-version: "latest"
|
llvm-version: "latest"
|
||||||
logfile: "test/empty/compile_commands.json"
|
logfile: "test/empty/compile_commands.json"
|
||||||
fetch_ubuntu_1804_12llvm:
|
fetch_ubuntu-1804_12-llvm:
|
||||||
name: "Fetch test: Ubuntu Linux 18.04 (LLVM 12.y)"
|
name: "Fetch: Ubuntu Linux 18.04 (LLVM 12.y)"
|
||||||
runs-on: ubuntu-18.04
|
runs-on: ubuntu-18.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
@@ -32,22 +32,46 @@ jobs:
|
|||||||
logfile: "test/empty/compile_commands.json"
|
logfile: "test/empty/compile_commands.json"
|
||||||
|
|
||||||
# Test simple build and analysis configuration.
|
# Test simple build and analysis configuration.
|
||||||
simple_analysis_test:
|
simple-analysis-tests:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
logfile: ['', 'test/simple/compile_commands.json']
|
logfile: ['', 'test/simple/compile_commands.json']
|
||||||
build-command: ['', 'cd test/simple; g++ -c main.cpp -o main.o']
|
build-command: ['', 'cd test/simple; g++ -c main.cpp -o main.o']
|
||||||
|
analyze-output: ['', 'my-output-dir']
|
||||||
|
|
||||||
name: "Simple analysis: (${{ matrix.logfile && 'logfile' || 'no-logfile' }} ${{ matrix.build-command && 'build-command' || 'no-build-command' }})"
|
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
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
# Allow continuing the build, this step is "expected failure".
|
# Allow continuing the build, we check "expected failure" for misconfiguration.
|
||||||
continue-on-error: ${{ (matrix.logfile != '') == (matrix.build-command != '') }}
|
continue-on-error: ${{ (matrix.logfile != '') == (matrix.build-command != '') }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
- run: test/fix_compile_json_paths.sh
|
||||||
- uses: ./
|
- uses: ./
|
||||||
with:
|
with:
|
||||||
logfile: ${{ matrix.logfile }}
|
logfile: ${{ matrix.logfile }}
|
||||||
build-command: ${{ matrix.build-command }}
|
build-command: ${{ matrix.build-command }}
|
||||||
|
analyze-output: ${{ matrix.analyze-output }}
|
||||||
|
|
||||||
|
analysis-cfg:
|
||||||
|
name: "Analysis: Custom configuration"
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: test/fix_compile_json_paths.sh
|
||||||
|
- uses: ./
|
||||||
|
with:
|
||||||
|
config: 'test/codechecker.verbose.json'
|
||||||
|
logfile: 'test/simple/compile_commands.json'
|
||||||
|
analysis-ctu:
|
||||||
|
name: "Analysis: CTU shortcut"
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: test/fix_compile_json_paths.sh
|
||||||
|
- uses: ./
|
||||||
|
with:
|
||||||
|
logfile: 'test/ctu/compile_commands.json'
|
||||||
|
ctu: true
|
||||||
|
|||||||
32
README.md
32
README.md
@@ -11,6 +11,8 @@ Objective-C) using the [Clang](http://clang.llvm.org/) infrastructure and
|
|||||||
This single action composite script encompasses the following steps:
|
This single action composite script encompasses the following steps:
|
||||||
|
|
||||||
1. Obtain a package of the LLVM Clang suite's analysers, and CodeChecker.
|
1. Obtain a package of the LLVM Clang suite's analysers, and CodeChecker.
|
||||||
|
2. _(Optional)_ Log the build commands to prepare for analysis.
|
||||||
|
3. Execute the analysis.
|
||||||
|
|
||||||
ℹ️ **Note:** Static analysis can be a time-consuming process.
|
ℹ️ **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.
|
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.
|
||||||
@@ -26,11 +28,11 @@ The two versions are mutually exclusive — you either can give a compilatio
|
|||||||
### Project can generate a [JSON Compilation Database](http://clang.llvm.org/docs/JSONCompilationDatabase.html) and build cleanly (no generated code)
|
### Project can generate a [JSON Compilation Database](http://clang.llvm.org/docs/JSONCompilationDatabase.html) and build cleanly (no generated code)
|
||||||
|
|
||||||
Some projects are trivial enough in their build configuration that no additional steps need to be taken after executing `configure.sh`, `cmake`, or similar tools.
|
Some projects are trivial enough in their build configuration that no additional steps need to be taken after executing `configure.sh`, `cmake`, or similar tools.
|
||||||
If you are able to generate a *compilation database* from your build system **without** running the build itself, you can save some time, and go to the analysis immediately.
|
If you are able to generate a _compilation database_ from your build system **without** running the build itself, you can save some time, and go to the analysis immediately.
|
||||||
|
|
||||||
You can specify the generated compilation database in the `logfile` variable
|
You can specify the generated compilation database in the `logfile` variable
|
||||||
|
|
||||||
~~~{.yml}
|
```yaml
|
||||||
runs:
|
runs:
|
||||||
steps:
|
steps:
|
||||||
# Check YOUR project out!
|
# Check YOUR project out!
|
||||||
@@ -48,18 +50,18 @@ runs:
|
|||||||
- uses: whisperity/codechecker-analysis-action
|
- uses: whisperity/codechecker-analysis-action
|
||||||
with:
|
with:
|
||||||
logfile: ${{ github.workspace }}/Build/compile_commands.json
|
logfile: ${{ github.workspace }}/Build/compile_commands.json
|
||||||
~~~
|
```
|
||||||
|
|
||||||
### Projects that need to self-creating a *JSON Compilation Database* or require generated code
|
### Projects that need to self-creating a *JSON Compilation Database* or require generated code
|
||||||
|
|
||||||
Other kinds of projects might rely heavily on *generated code*.
|
Other kinds of projects might rely heavily on _generated code_.
|
||||||
When looking at the source code of these projects **without** a build having been executed beforehand, they do not compile — as such, analysis cannot be executed either.
|
When looking at the source code of these projects **without** a build having been executed beforehand, they do not compile — as such, analysis cannot be executed either.
|
||||||
|
|
||||||
In this case, you will need to instruct CodeChecker to log a build (and spend time doing the build) just before analysis.
|
In this case, you will need to instruct CodeChecker to log a build (and spend time doing the build) just before analysis.
|
||||||
|
|
||||||
You can specify the build to execute in the `build-command` variable.
|
You can specify the build to execute in the `build-command` variable.
|
||||||
|
|
||||||
~~~{.yml}
|
```yaml
|
||||||
runs:
|
runs:
|
||||||
steps:
|
steps:
|
||||||
# Check YOUR project out!
|
# Check YOUR project out!
|
||||||
@@ -77,7 +79,7 @@ runs:
|
|||||||
- uses: whisperity/codechecker-analysis-action
|
- uses: whisperity/codechecker-analysis-action
|
||||||
with:
|
with:
|
||||||
build-command: "cd ${{ github.workspace }}/Build; cmake --build ."
|
build-command: "cd ${{ github.workspace }}/Build; cmake --build ."
|
||||||
~~~
|
```
|
||||||
|
|
||||||
|
|
||||||
## Action configuration
|
## Action configuration
|
||||||
@@ -103,4 +105,22 @@ runs:
|
|||||||
| `logfile` | | The location of the JSON Compilation Database which describes how the project is built. This flag is used if the build system can pre-generate the file for us. |
|
| `logfile` | | The location of the JSON Compilation Database which describes how the project is built. This flag is used if the build system can pre-generate the file for us. |
|
||||||
| `build-command` | | The build command to execute. CodeChecker is capable of executing and logging the build for itself. This flag is used if the build-system can not generate the information by itself, or the project relies on other generated code. |
|
| `build-command` | | The build command to execute. CodeChecker is capable of executing and logging the build for itself. This flag is used if the build-system can not generate the information by itself, or the project relies on other generated code. |
|
||||||
|
|
||||||
|
### Analysis configuration
|
||||||
|
|
||||||
|
🔖 Read more about [`CodeChecker analyze`](http://codechecker.readthedocs.io/en/latest/analyzer/user_guide/#analyze) in the official documentation.
|
||||||
|
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|------------------|------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| `analyze-output` | (auto-generated) | The directory where the **raw** analysis output should be stored. |
|
||||||
|
| `ctu` | `false` | Enable [Cross Translation Unit analysis](http://clang.llvm.org/docs/analyzer/user-docs/CrossTranslationUnit.html) in the _Clang Static Analyzer_. ⚠️ **CAUTION!** _CTU_ analysis might take a very long time, and CTU is officially regarded as experimental. |
|
||||||
|
|
||||||
|
|
||||||
|
## Action *`outputs`* to use in further steps
|
||||||
|
|
||||||
|
The action exposes the following outputs which may be used in a workflow's steps succeeding the analysis.
|
||||||
|
|
||||||
|
| Variable | Value | Description |
|
||||||
|
|------------------|-------------------------------------------|----------------------------------------------------------------------|
|
||||||
|
| `logfile` | Auto-generated, or `logfile` input | The JSON Compilation Database of the analysis that was executed. |
|
||||||
|
| `analyze-output` | Auto-generated, or `analyze-output` input | The directory where the **raw** analysis output files are available. |
|
||||||
|
|||||||
39
action.yml
39
action.yml
@@ -30,6 +30,24 @@ inputs:
|
|||||||
description: 'The build command to execute and log for the creation of a JSON Compilation Database. Mutually exclusive with "logfile".'
|
description: 'The build command to execute and log for the creation of a JSON Compilation Database. Mutually exclusive with "logfile".'
|
||||||
required: false
|
required: false
|
||||||
|
|
||||||
|
analyze-output:
|
||||||
|
description: 'The output directory where the raw analysis output should be stored. If left the default empty, the path will be generated automatically.'
|
||||||
|
default: ''
|
||||||
|
required: false
|
||||||
|
ctu:
|
||||||
|
description: 'Whether to enable Cross Translation Unit (CTU) analysis in the Clang Static Analyzer.'
|
||||||
|
default: 'false'
|
||||||
|
required: true
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
logfile:
|
||||||
|
description: 'The location of the JSON Compilation Database that was used for the analysis.'
|
||||||
|
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 }}
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
steps:
|
steps:
|
||||||
@@ -59,7 +77,7 @@ runs:
|
|||||||
- name: "Build and Package CodeChecker"
|
- name: "Build and Package CodeChecker"
|
||||||
id: codechecker
|
id: codechecker
|
||||||
env:
|
env:
|
||||||
CODECHECKER_WILL_USE_WEB_API: false # TODO: Add support for this later.
|
CODECHECKER_WILL_USE_WEB_API: "false" # TODO: Add support for this later.
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
set -ex
|
set -ex
|
||||||
@@ -89,13 +107,30 @@ runs:
|
|||||||
echo "::set-output name=GITSEVEN::$(./build/CodeChecker/bin/CodeChecker analyzer-version | grep 'Git commit' | cut -d'|' -f 2 | cut -c 2-8)"
|
echo "::set-output name=GITSEVEN::$(./build/CodeChecker/bin/CodeChecker analyzer-version | grep 'Git commit' | cut -d'|' -f 2 | cut -c 2-8)"
|
||||||
|
|
||||||
popd
|
popd
|
||||||
|
|
||||||
- name: "Prepare JSON Compilation Database"
|
- name: "Prepare JSON Compilation Database"
|
||||||
|
id: log
|
||||||
env:
|
env:
|
||||||
|
ACTION_NAME: ${{ github.action }}
|
||||||
CODECHECKER_PATH: ${{ steps.codechecker.outputs.PATH }}
|
CODECHECKER_PATH: ${{ steps.codechecker.outputs.PATH }}
|
||||||
|
|
||||||
IN_LOGFILE: ${{ inputs.logfile }}
|
IN_LOGFILE: ${{ inputs.logfile }}
|
||||||
IN_COMMAND: ${{ inputs.build-command }}
|
IN_COMMAND: ${{ inputs.build-command }}
|
||||||
|
|
||||||
OUT_FILE: ${{ github.workspace }}/codechecker_compilation_database.json
|
OUT_FILE: ${{ github.workspace }}/${{ github.action }}_codechecker_compilation_database.json
|
||||||
shell: bash
|
shell: bash
|
||||||
run: ${{ github.action_path }}/src/get-or-create-build-json.sh
|
run: ${{ github.action_path }}/src/get-or-create-build-json.sh
|
||||||
|
|
||||||
|
- name: "Execute static analysis"
|
||||||
|
id: analyze
|
||||||
|
env:
|
||||||
|
ACTION_NAME: ${{ github.action }}
|
||||||
|
CODECHECKER_PATH: ${{ steps.codechecker.outputs.PATH }}
|
||||||
|
COMPILATION_DATABASE: ${{ steps.log.outputs.COMPILATION_DATABASE }}
|
||||||
|
|
||||||
|
IN_CONFIGFILE: ${{ inputs.config }}
|
||||||
|
IN_CTU: ${{ inputs.ctu }}
|
||||||
|
IN_FLAGS: ${{ inputs.analyze-options }}
|
||||||
|
IN_OUTPUT_DIR: ${{ inputs.analyze-output }}
|
||||||
|
shell: bash
|
||||||
|
run: ${{ github.action_path }}/src/execute-analysis.sh
|
||||||
|
|||||||
41
src/execute-analysis.sh
Executable file
41
src/execute-analysis.sh
Executable file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
if [[ -z "$COMPILATION_DATABASE" ]]; then
|
||||||
|
echo "::error title=Internal error::environment variable 'COMPILATION_DATABASE' missing!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
OUTPUT_DIR="$IN_OUTPUT_DIR"
|
||||||
|
if [[ -z "$OUTPUT_DIR" ]]; then
|
||||||
|
OUTPUT_DIR=~/"$ACTION_NAME"_Results
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -pv "$(dirname $"OUTPUT_DIR")"
|
||||||
|
|
||||||
|
if [[ ! -z "$IN_CONFIGFILE" ]]; then
|
||||||
|
CONFIG_FLAG_1="--config"
|
||||||
|
CONFIG_FLAG_2=$IN_CONFIGFILE
|
||||||
|
echo "Using configuration file \"$IN_CONFIGFILE\"!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
CTU_FLAG=$([[ "$IN_CTU" == "true" ]] && echo "--ctu --ctu-ast-mode load-from-pch" || echo "")
|
||||||
|
if [[ "$IN_CTU" == "true" ]]; then
|
||||||
|
CTU_FLAG="--ctu --ctu-ast-mode load-from-pch"
|
||||||
|
echo "::notice title=Cross Translation Unit analyis::CTU has been enabled, the analysis might take a long time!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Note: Ignoring the result of the analyze command in CTU mode, as we do not
|
||||||
|
# wish to break the build on a CTU failure.
|
||||||
|
|
||||||
|
"$CODECHECKER_PATH"/CodeChecker analyze \
|
||||||
|
"$COMPILATION_DATABASE" \
|
||||||
|
--output "$OUTPUT_DIR" \
|
||||||
|
--jobs $(nproc) \
|
||||||
|
$CONFIG_FLAG_1 $CONFIG_FLAG_2 \
|
||||||
|
$CTU_FLAGS \
|
||||||
|
|| [[ "$IN_CTU" == "true" ]]
|
||||||
|
EXIT_CODE=$?
|
||||||
|
|
||||||
|
echo "::set-output name=OUTPUT_DIR::$OUTPUT_DIR"
|
||||||
|
exit $EXIT_CODE
|
||||||
@@ -6,19 +6,24 @@ if [[ ! -z "$IN_LOGFILE" && ! -z "$IN_COMMAND" ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
mkdir -pv $(dirname "$OUT_FILE")
|
||||||
|
|
||||||
|
EXIT_CODE=0
|
||||||
|
|
||||||
if [[ ! -z "$IN_LOGFILE" ]]; then
|
if [[ ! -z "$IN_LOGFILE" ]]; then
|
||||||
# Pretty trivial.
|
# Pretty trivial.
|
||||||
cp -v "$IN_LOGFILE" "$OUT_FILE"
|
cp -v "$IN_LOGFILE" "$OUT_FILE"
|
||||||
exit $?
|
EXIT_CODE=$?
|
||||||
fi
|
elif [[ ! -z "$IN_COMMAND" ]]; then
|
||||||
|
|
||||||
if [[ ! -z "$IN_COMMAND" ]]; then
|
|
||||||
"$CODECHECKER_PATH"/CodeChecker log \
|
"$CODECHECKER_PATH"/CodeChecker log \
|
||||||
--build "$IN_COMMAND" \
|
--build "$IN_COMMAND" \
|
||||||
--output "$OUT_FILE"
|
--output "$OUT_FILE"
|
||||||
exit $?
|
EXIT_CODE=$?
|
||||||
|
else
|
||||||
|
echo "::error title=Configuration error::neither 'logfile' nor 'build-command' specified!"
|
||||||
|
echo "[]" > "$OUT_FILE"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "::error title=Configuration error::neither 'logfile' nor 'build-command' specified!"
|
echo "::set-output name=COMPILATION_DATABASE::$OUT_FILE"
|
||||||
echo "[]" > "$OUT_FILE"
|
exit $EXIT_CODE
|
||||||
exit 1
|
|
||||||
|
|||||||
5
test/codechecker.verbose.json
Normal file
5
test/codechecker.verbose.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"analyze": [
|
||||||
|
"--verbose=debug"
|
||||||
|
]
|
||||||
|
}
|
||||||
12
test/ctu/compile_commands.json
Normal file
12
test/ctu/compile_commands.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"directory": "__DIRECTORY__",
|
||||||
|
"command": "g++ -c main.cpp -o main.o",
|
||||||
|
"file": "main.cpp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"directory": "__DIRECTORY__",
|
||||||
|
"command": "g++ -c lib.cpp -o lib.o",
|
||||||
|
"file": "lib.cpp"
|
||||||
|
}
|
||||||
|
]
|
||||||
3
test/ctu/lib.cpp
Normal file
3
test/ctu/lib.cpp
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
int zero() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
5
test/ctu/main.cpp
Normal file
5
test/ctu/main.cpp
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
int zero();
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
return argc / zero();
|
||||||
|
}
|
||||||
8
test/fix_compile_json_paths.sh
Executable file
8
test/fix_compile_json_paths.sh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
for CCDB in $(find . -name "compile_commands.json"); do
|
||||||
|
pushd $(dirname "$CCDB")
|
||||||
|
sed -i "s,__DIRECTORY__,$(pwd),g" "compile_commands.json"
|
||||||
|
popd
|
||||||
|
done
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"directory": ".",
|
"directory": "__DIRECTORY__",
|
||||||
"command": "g++ -c main.cpp -o main.o",
|
"command": "g++ -c main.cpp -o main.o",
|
||||||
"file": "main.cpp"
|
"file": "main.cpp"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user