mirror of
https://github.com/whisperity/CodeChecker-Action.git
synced 2026-02-09 22:57:45 +00:00
feat: Allow executing cmd diff against a stored run and report if there are new findings
This commit is contained in:
76
.github/workflows/test.yml
vendored
76
.github/workflows/test.yml
vendored
@@ -43,6 +43,7 @@ jobs:
|
|||||||
install-custom: ${{ matrix.install-custom }}
|
install-custom: ${{ matrix.install-custom }}
|
||||||
version: ${{ matrix.version }}
|
version: ${{ matrix.version }}
|
||||||
llvm-version: ${{ matrix.llvm-version }}
|
llvm-version: ${{ matrix.llvm-version }}
|
||||||
|
|
||||||
logfile: "test/empty/compile_commands.json"
|
logfile: "test/empty/compile_commands.json"
|
||||||
|
|
||||||
simple-analysis-tests:
|
simple-analysis-tests:
|
||||||
@@ -83,6 +84,7 @@ jobs:
|
|||||||
- uses: ./
|
- uses: ./
|
||||||
with:
|
with:
|
||||||
config: 'test/codechecker.verbose.json'
|
config: 'test/codechecker.verbose.json'
|
||||||
|
|
||||||
logfile: 'test/simple/compile_commands.json'
|
logfile: 'test/simple/compile_commands.json'
|
||||||
analyze-ctu:
|
analyze-ctu:
|
||||||
name: "Analyze: CTU shortcut"
|
name: "Analyze: CTU shortcut"
|
||||||
@@ -94,6 +96,7 @@ jobs:
|
|||||||
id: codechecker
|
id: codechecker
|
||||||
with:
|
with:
|
||||||
logfile: 'test/ctu/compile_commands.json'
|
logfile: 'test/ctu/compile_commands.json'
|
||||||
|
|
||||||
ctu: true
|
ctu: true
|
||||||
- name: "Reject test if previous step did not produce CTU finding"
|
- name: "Reject test if previous step did not produce CTU finding"
|
||||||
run: cat ${{ steps.codechecker.outputs.result-log }} | grep "Dereference of null pointer"
|
run: cat ${{ steps.codechecker.outputs.result-log }} | grep "Dereference of null pointer"
|
||||||
@@ -108,11 +111,12 @@ jobs:
|
|||||||
id: codechecker
|
id: codechecker
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
logfile: 'test/simple/compile_commands.json'
|
|
||||||
# FIXME: 6.18 release on PyPI is broken when it comes to the "parse"
|
# FIXME: 6.18 release on PyPI is broken when it comes to the "parse"
|
||||||
# command. See Ericsson/CodeChecker#3515.
|
# command. See Ericsson/CodeChecker#3515.
|
||||||
install-custom: true
|
install-custom: true
|
||||||
version: "v6.18.0"
|
version: "v6.18.0"
|
||||||
|
|
||||||
|
logfile: 'test/simple/compile_commands.json'
|
||||||
- name: "Reject test if output isn't as expected"
|
- name: "Reject test if output isn't as expected"
|
||||||
if: ${{ steps.codechecker.outputs.warnings != 'true' }}
|
if: ${{ steps.codechecker.outputs.warnings != 'true' }}
|
||||||
run: |
|
run: |
|
||||||
@@ -128,11 +132,12 @@ jobs:
|
|||||||
- uses: ./
|
- uses: ./
|
||||||
id: codechecker
|
id: codechecker
|
||||||
with:
|
with:
|
||||||
logfile: 'test/simple/compile_commands.json'
|
|
||||||
# FIXME: 6.18 release on PyPI is broken when it comes to the "parse"
|
# FIXME: 6.18 release on PyPI is broken when it comes to the "parse"
|
||||||
# command. See Ericsson/CodeChecker#3515.
|
# command. See Ericsson/CodeChecker#3515.
|
||||||
install-custom: true
|
install-custom: true
|
||||||
version: "v6.18.0"
|
version: "v6.18.0"
|
||||||
|
|
||||||
|
logfile: 'test/simple/compile_commands.json'
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: "Parse HTML test results"
|
name: "Parse HTML test results"
|
||||||
@@ -187,7 +192,9 @@ jobs:
|
|||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
version: "${{ env.CODECHECKER_VERSION }}"
|
version: "${{ env.CODECHECKER_VERSION }}"
|
||||||
|
|
||||||
logfile: 'test/simple/compile_commands.json'
|
logfile: 'test/simple/compile_commands.json'
|
||||||
|
|
||||||
store: true
|
store: true
|
||||||
store-url: 'http://0.0.0.0:8001/Default'
|
store-url: 'http://0.0.0.0:8001/Default'
|
||||||
store-username: 'root'
|
store-username: 'root'
|
||||||
@@ -210,3 +217,68 @@ jobs:
|
|||||||
- name: "Fail the build if the test execution failed"
|
- name: "Fail the build if the test execution failed"
|
||||||
if: ${{ steps.test.outcome == 'failure' || steps.codechecker.outcome == 'failure' || steps.codechecker.outputs.store-successful != 'true' }}
|
if: ${{ steps.test.outcome == 'failure' || steps.codechecker.outcome == 'failure' || steps.codechecker.outputs.store-successful != 'true' }}
|
||||||
run: exit 1
|
run: exit 1
|
||||||
|
|
||||||
|
diff:
|
||||||
|
name: "Diff: New findings are discovered and reported"
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
env:
|
||||||
|
CODECHECKER_VERSION: '6.18.0'
|
||||||
|
# This time, we do not need authentication, so test with the official Docker subsystem.
|
||||||
|
services:
|
||||||
|
codechecker-server:
|
||||||
|
image: 'codechecker/codechecker-web:6.18.0'
|
||||||
|
ports:
|
||||||
|
- 8001:8001/tcp
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
# Need to do this manually because the server for this test has to have
|
||||||
|
# authentication on, with a known username and password.
|
||||||
|
- name: "Wait for CodeChecker server service to go live"
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
|
||||||
|
sudo apt-get -y update
|
||||||
|
sudo apt-get -y install --no-install-recommends \
|
||||||
|
netcat \
|
||||||
|
wget
|
||||||
|
|
||||||
|
wget -qO- http://raw.githubusercontent.com/eficode/wait-for/v2.1.3/wait-for | sh -s -- --timeout=30 http://0.0.0.0:8001/ -- echo "CodeChecker up"
|
||||||
|
- run: test/fix_compile_json_paths.sh
|
||||||
|
- name: "Do the first analysis that stores a result"
|
||||||
|
uses: ./
|
||||||
|
id: codechecker-store
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
# FIXME: 6.18 release on PyPI is broken when it comes to the "parse"
|
||||||
|
# command. See Ericsson/CodeChecker#3515.
|
||||||
|
install-custom: true
|
||||||
|
version: "v${{ env.CODECHECKER_VERSION }}"
|
||||||
|
|
||||||
|
logfile: 'test/simple/compile_commands.json'
|
||||||
|
|
||||||
|
store: true
|
||||||
|
store-url: 'http://0.0.0.0:8001/Default'
|
||||||
|
store-run-name: 'test-run'
|
||||||
|
- name: "Do the second analysis that finds a new result"
|
||||||
|
uses: ./
|
||||||
|
id: codechecker-diff
|
||||||
|
with:
|
||||||
|
# FIXME: 6.18 release on PyPI is broken when it comes to the "parse"
|
||||||
|
# command. See Ericsson/CodeChecker#3515.
|
||||||
|
install-custom: true
|
||||||
|
version: "v${{ env.CODECHECKER_VERSION }}"
|
||||||
|
|
||||||
|
logfile: 'test/simple2/compile_commands.json'
|
||||||
|
|
||||||
|
diff: true
|
||||||
|
diff-url: 'http://0.0.0.0:8001/Default'
|
||||||
|
diff-run-name: 'test-run'
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
if: ${{ steps.codechecker-diff.outputs.warnings-in-diff == 'true' }}
|
||||||
|
with:
|
||||||
|
name: "Diff HTML test results"
|
||||||
|
path: ${{ steps.codechecker-diff.outputs.diff-html-dir }}
|
||||||
|
if-no-files-found: error
|
||||||
|
- name: "Fail the build if the test execution failed"
|
||||||
|
if: ${{ steps.codechecker-store.outcome == 'failure' || steps.codechecker-diff.outcome == 'failure' || steps.codechecker-store.outputs.store-successful != 'true' || steps.codechecker-diff.outputs.warnings-in-diff != 'true' }}
|
||||||
|
run: exit 1
|
||||||
|
|||||||
100
README.md
100
README.md
@@ -14,7 +14,8 @@ This single action composite script encompasses the following steps:
|
|||||||
2. _(Optional)_ Log the build commands to prepare for analysis.
|
2. _(Optional)_ Log the build commands to prepare for analysis.
|
||||||
3. Execute the analysis.
|
3. Execute the analysis.
|
||||||
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!)
|
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)_ Upload the results to a running _CodeChecker server_.
|
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.
|
ℹ️ **Note:** Static analysis can be a time-consuming process.
|
||||||
@@ -146,6 +147,11 @@ If your project hosts a CodeChecker server somewhere, the job can be configured
|
|||||||
to automatically create or update a run.
|
to automatically create or update a run.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
# It is recommended that storing only happens for PUSH events, and preferably
|
||||||
|
# only for long-term branches.
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
steps:
|
steps:
|
||||||
# Check YOUR project out!
|
# Check YOUR project out!
|
||||||
@@ -168,6 +174,7 @@ runs:
|
|||||||
store-url: 'http://example.com:8001/MyProject'
|
store-url: 'http://example.com:8001/MyProject'
|
||||||
store-username: ${{ secrets.CODECHECKER_STORE_USER }}
|
store-username: ${{ secrets.CODECHECKER_STORE_USER }}
|
||||||
store-password: ${{ secrets.CODECHECKER_STORE_PASSWORD }}
|
store-password: ${{ secrets.CODECHECKER_STORE_PASSWORD }}
|
||||||
|
# store-run-name: "custom run name to store against"
|
||||||
|
|
||||||
# Upload the results to the CI.
|
# Upload the results to the CI.
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v2
|
||||||
@@ -176,7 +183,58 @@ runs:
|
|||||||
path: ${{ steps.codechecker.outputs.result-html-dir }}
|
path: ${{ steps.codechecker.outputs.result-html-dir }}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Acting as a CI gate on pull requests
|
||||||
|
|
||||||
|
CodeChecker is capable of calculating the difference between two analyses.
|
||||||
|
If an analysis of the stable version of the project is stored (see above) to a server, a job for pull requests can be configured that automatically rejects a pull request if it tries to introduce _new_ analysis findings.
|
||||||
|
|
||||||
|
To get the reports in a human-consumable form, they must be uploaded somewhere first, before the failure step fails the entire job!
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
runs:
|
||||||
|
steps:
|
||||||
|
# Check the pull request out! (In pull_request jobs, the checkout action
|
||||||
|
# automatically downloads the "after-merge" state of the pull request if
|
||||||
|
# there are no conflicts.)
|
||||||
|
- name: "Check out repository"
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
# Prepare a build
|
||||||
|
- name: "Prepare build"
|
||||||
|
run: |
|
||||||
|
mkdir -pv Build
|
||||||
|
cd Build
|
||||||
|
cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=OFF
|
||||||
|
|
||||||
|
# Run the analysis
|
||||||
|
- uses: whisperity/codechecker-analysis-action
|
||||||
|
id: codechecker
|
||||||
|
with:
|
||||||
|
build-command: "cd ${{ github.workspace }}/Build; cmake --build ."
|
||||||
|
diff: true
|
||||||
|
diff-url: 'http://example.com:8001/MyProject'
|
||||||
|
diff-username: ${{ secrets.CODECHECKER_DIFF_USER }}
|
||||||
|
diff-password: ${{ secrets.CODECHECKER_DIFF_PASSWORD }}
|
||||||
|
# diff-run-name: "custom run name to diff against"
|
||||||
|
|
||||||
|
# Upload the potential new findings results to the CI.
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
if: ${{ steps.codechecker.outputs.warnings-in-diff == 'true' }}
|
||||||
|
with:
|
||||||
|
name: "New introduced results Bug Reports"
|
||||||
|
path: ${{ steps.codechecker.outputs.diff-html-dir }}
|
||||||
|
|
||||||
|
- name: "Fail the job if new findings are introduced"
|
||||||
|
if: ${{ steps.codechecker.outputs.warnings-in-diff == 'true' }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "::error title=New static analysis warnings::Analysed commit would introduce new static analysis warnings and potential bugs to the project"
|
||||||
|
# Fail the build, after results were collected and uploaded.
|
||||||
|
exit 1
|
||||||
|
```
|
||||||
|
|
||||||
## Action configuration
|
## Action configuration
|
||||||
|
|
||||||
@@ -215,10 +273,26 @@ runs:
|
|||||||
|
|
||||||
🔖 Read more about [`CodeChecker parse`](http://codechecker.readthedocs.io/en/latest/analyzer/user_guide/#parse) in the official documentation.
|
🔖 Read more about [`CodeChecker parse`](http://codechecker.readthedocs.io/en/latest/analyzer/user_guide/#parse) in the official documentation.
|
||||||
|
|
||||||
### Store settings
|
### Diff configuration
|
||||||
|
|
||||||
|
🔖 Read more about [`CodeChecker cmd diff`](http://codechecker.readthedocs.io/en/latest/analyzer/user_guide/#cmd-diff) in the official documentation.
|
||||||
|
|
||||||
|
🔓 Checking the analysis results against the contents of a server requires the `PRODUCT_VIEW` permission, if the server is requiring authentication.
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|-----------------|---------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| `diff` | `false` | If set to `true`, the job will compute a diff of the current analysis results against the results stored on a remote server. |
|
||||||
|
| `diff-url` | | The URL of the CodeChecker product to check and diff against, **including** the [endpoint](http://codechecker.readthedocs.io/en/latest/web/user_guide/#product_url-format). Usually in the format of `http://example.com/ProductName`. Specifying this variable is **required** if `diff` was set to `true`. |
|
||||||
|
| `diff-username` | | If the server requires authentication to access, specify the username which the check should log in with. |
|
||||||
|
| `diff-password` | | The password or [generated access token](http://codechecker.readthedocs.io/en/latest/web/authentication/#personal-access-token) corresponding to the user. 🔐 **Note:** It is recommended that this is configured as a repository secret, and given as such: `${{ secrets.CODECHECKER_PASSWORD }}` when configuring the action. |
|
||||||
|
| `diff-run-name` | (auto-generated, in the format `user/repo: branchname`) | CodeChecker analysis executions are collected into _runs_. A run usually correlates to one configuration of the analysis. |
|
||||||
|
|
||||||
|
### Store configuration
|
||||||
|
|
||||||
🔖 Read more about [`CodeChecker store`](http://codechecker.readthedocs.io/en/latest/web/user_guide/#store) in the official documentation.
|
🔖 Read more about [`CodeChecker store`](http://codechecker.readthedocs.io/en/latest/web/user_guide/#store) in the official documentation.
|
||||||
|
|
||||||
|
🔓 Storing runs to a server requires the `PRODUCT_STORE` permission, if the server is requiring authentication.
|
||||||
|
|
||||||
| Variable | Default | Description |
|
| Variable | Default | Description |
|
||||||
|------------------|---------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|------------------|---------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| `store` | `false` | If set to `true`, the script will upload the findings to a CodeChecker server. Usually, other flags need to be configured too! |
|
| `store` | `false` | If set to `true`, the script will upload the findings to a CodeChecker server. Usually, other flags need to be configured too! |
|
||||||
@@ -231,12 +305,16 @@ runs:
|
|||||||
|
|
||||||
The action exposes the following outputs which may be used in a workflow's steps succeeding the analysis.
|
The action exposes the following outputs which may be used in a workflow's steps succeeding the analysis.
|
||||||
|
|
||||||
| Variable | Value | Description |
|
| 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 are available. |
|
||||||
| `logfile` | Auto-generated, or `logfile` input | The JSON Compilation Database of the analysis that was executed. |
|
| `logfile` | Auto-generated, or `logfile` input | The JSON Compilation Database of the analysis that was executed. |
|
||||||
| `result-html-dir` | Auto-generated. | The directory where the **user-friendly HTML** bug reports were generated to. |
|
| `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). |
|
||||||
| `result-log` | Auto-generated. | `CodeChecker parse`'s output log file which contains the findings dumped into it. |
|
| `diff-run-name` | Auto-generated, or `diff-run-name` input | The name of the analysis run (if `diff` was enabled) against which the reports were compared. |
|
||||||
| `store-run-name` | Auto-generated, or `store-run-name` input | The name of the analysis run (if `store` was enabled) to which the results were uploaded to. |
|
| `diff-result-log` | Auto-generated. | `CodeChecker cmd diff`'s output log file which contains the **new** findings dumped into it. |
|
||||||
| `store-successful` | `true` or `false` | Whether storing the results succeeded. Useful for optionally breaking the build later to detect networking failures. |
|
| `result-html-dir` | Auto-generated. | The directory where the **user-friendly HTML** bug reports were generated to. |
|
||||||
| `warnings` | `true` or `false` | Whether the static analysers reported any findings. |
|
| `result-log` | Auto-generated. | `CodeChecker parse`'s output log file which contains the findings dumped into it. |
|
||||||
|
| `store-run-name` | Auto-generated, or `store-run-name` input | The name of the analysis run (if `store` was enabled) to which the results were uploaded to. |
|
||||||
|
| `store-successful` | `true` or `false` | Whether storing the results succeeded. Useful for optionally breaking the build later to detect networking failures. |
|
||||||
|
| `warnings` | `true` or `false` | Whether the static analysers reported any findings. |
|
||||||
|
| `warnings-in-diff` | `true` or `false` | If `diff` was enabled, whether there were **new** findings in the current analysis when compared against the contents of the server. |
|
||||||
|
|||||||
67
action.yml
67
action.yml
@@ -43,6 +43,24 @@ inputs:
|
|||||||
required: true
|
required: true
|
||||||
default: 'false'
|
default: '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
|
||||||
|
default: 'false'
|
||||||
|
diff-url:
|
||||||
|
description: 'The CodeChecker product URL (usually in the format of http://example.com/ProductName) where the diff should connect to. Mandatory if "diff" is true.'
|
||||||
|
required: false
|
||||||
|
diff-username:
|
||||||
|
description: 'If the server requires authentication, the username to authenticate with.'
|
||||||
|
required: false
|
||||||
|
diff-password:
|
||||||
|
description: 'The password (or generated private access token) corresponding to the user.'
|
||||||
|
required: false
|
||||||
|
diff-run-name:
|
||||||
|
description: 'An identifying name of the analysis run. A run usually correlates to a set of configuration, e.g. analysis mode, branch, etc. If left default, the name is automatically generated from the current repository and branch name.'
|
||||||
|
required: true
|
||||||
|
default: '__DEFAULT__'
|
||||||
|
|
||||||
store:
|
store:
|
||||||
description: 'Whether to enable storing the results to a CodeChecker server. If enabled, other flags, such as "store-url" must also be set.'
|
description: 'Whether to enable storing the results to a CodeChecker server. If enabled, other flags, such as "store-url" must also be set.'
|
||||||
required: true
|
required: true
|
||||||
@@ -80,6 +98,19 @@ outputs:
|
|||||||
description: 'The output directory where the user-friendly HTML reports were stored to.'
|
description: 'The output directory where the user-friendly HTML reports were stored to.'
|
||||||
value: ${{ steps.parse.outputs.HTML_DIR }}
|
value: ${{ steps.parse.outputs.HTML_DIR }}
|
||||||
|
|
||||||
|
diff-html-dir:
|
||||||
|
description: 'The output directory where the user-friendly HTML reports about the new findings (if "diff" was enabled) were stored to.'
|
||||||
|
value: ${{ steps.diff.outputs.HTML_DIR }}
|
||||||
|
diff-run-name:
|
||||||
|
description: 'The name of the analysis run against which the current reports were compared.'
|
||||||
|
value: ${{ steps.diff-pre.outputs.RUN_NAME }}
|
||||||
|
diff-result-log:
|
||||||
|
description: 'The file where the output of CodeChecker cmd diff is written to verbatim.'
|
||||||
|
value: ${{ steps.diff.outputs.OUTPUT_LOG }}
|
||||||
|
warnings-in-diff:
|
||||||
|
description: 'Whether the current analysis produced any reports that were NEW, compared to the configured analysis run on the server.'
|
||||||
|
value: ${{ steps.diff.outputs.HAS_NEW_FINDINGS }}
|
||||||
|
|
||||||
store-run-name:
|
store-run-name:
|
||||||
description: 'The name of the analysis run that the results were uploaded to.'
|
description: 'The name of the analysis run that the results were uploaded to.'
|
||||||
value: ${{ steps.store-pre.outputs.RUN_NAME }}
|
value: ${{ steps.store-pre.outputs.RUN_NAME }}
|
||||||
@@ -109,7 +140,7 @@ runs:
|
|||||||
- name: "Build and Package CodeChecker"
|
- name: "Build and Package CodeChecker"
|
||||||
id: codechecker
|
id: codechecker
|
||||||
env:
|
env:
|
||||||
CODECHECKER_WILL_USE_WEB_API: ${{ inputs.store == 'true' }}
|
CODECHECKER_WILL_USE_WEB_API: ${{ inputs.store == 'true' || inputs.diff == 'true' }}
|
||||||
|
|
||||||
IN_INSTALL_CUSTOM: ${{ inputs.install-custom }}
|
IN_INSTALL_CUSTOM: ${{ inputs.install-custom }}
|
||||||
IN_VERSION: ${{ inputs.version }}
|
IN_VERSION: ${{ inputs.version }}
|
||||||
@@ -138,9 +169,9 @@ runs:
|
|||||||
- name: "Execute static analysis"
|
- name: "Execute static analysis"
|
||||||
id: analyze
|
id: analyze
|
||||||
env:
|
env:
|
||||||
ACTION_NAME: ${{ github.action }}
|
|
||||||
CODECHECKER_PATH: ${{ steps.codechecker.outputs.PATH }}
|
CODECHECKER_PATH: ${{ steps.codechecker.outputs.PATH }}
|
||||||
COMPILATION_DATABASE: ${{ steps.log.outputs.COMPILATION_DATABASE }}
|
COMPILATION_DATABASE: ${{ steps.log.outputs.COMPILATION_DATABASE }}
|
||||||
|
GITHUB_ACTION_NAME: ${{ github.action }}
|
||||||
|
|
||||||
IN_CONFIGFILE: ${{ inputs.config }}
|
IN_CONFIGFILE: ${{ inputs.config }}
|
||||||
IN_CTU: ${{ inputs.ctu }}
|
IN_CTU: ${{ inputs.ctu }}
|
||||||
@@ -157,10 +188,40 @@ runs:
|
|||||||
RAW_RESULT_DIR: ${{ steps.analyze.outputs.OUTPUT_DIR }}
|
RAW_RESULT_DIR: ${{ steps.analyze.outputs.OUTPUT_DIR }}
|
||||||
|
|
||||||
IN_CONFIGFILE: ${{ inputs.config }}
|
IN_CONFIGFILE: ${{ inputs.config }}
|
||||||
IN_OUTPUT_DIR: ${{ inputs.analyze-output }}
|
|
||||||
shell: bash
|
shell: bash
|
||||||
run: ${{ github.action_path }}/src/parse-results.sh
|
run: ${{ github.action_path }}/src/parse-results.sh
|
||||||
|
|
||||||
|
- name: "Generate the configuration for diffing current results against previously stored"
|
||||||
|
id: diff-pre
|
||||||
|
if: ${{ inputs.diff == 'true' }}
|
||||||
|
env:
|
||||||
|
IN_DIFF_URL: ${{ inputs.diff-url }}
|
||||||
|
IN_DIFF_USERNAME: ${{ inputs.diff-username }}
|
||||||
|
IN_DIFF_PASSWORD: ${{ inputs.diff-password }}
|
||||||
|
IN_DIFF_RUN_NAME: ${{ inputs.diff-run-name }}
|
||||||
|
|
||||||
|
GITHUB_BASE_REF: ${{ github.base_ref }}
|
||||||
|
GITHUB_EVENT_NAME: ${{ github.event_name }}
|
||||||
|
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||||
|
GITHUB_REF_NAME: ${{ github.ref_name }}
|
||||||
|
GITHUB_REF_TYPE: ${{ github.ref_type }}
|
||||||
|
shell: bash
|
||||||
|
run: ${{ github.action_path }}/src/diff-pre.sh
|
||||||
|
|
||||||
|
- name: "Diff current results against previously stored run"
|
||||||
|
id: diff
|
||||||
|
if: ${{ steps.diff-pre.outputs.DIFF_CONFIGURED == 'true' }}
|
||||||
|
env:
|
||||||
|
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 }}
|
||||||
|
|
||||||
|
IN_CONFIGFILE: ${{ inputs.config }}
|
||||||
|
IN_DIFF_URL: ${{ inputs.diff-url }}
|
||||||
|
shell: bash
|
||||||
|
run: ${{ github.action_path }}/src/diff.sh
|
||||||
|
|
||||||
- name: "Generate the configuration for uploading results"
|
- name: "Generate the configuration for uploading results"
|
||||||
id: store-pre
|
id: store-pre
|
||||||
if: ${{ inputs.store == 'true' }}
|
if: ${{ inputs.store == 'true' }}
|
||||||
|
|||||||
47
src/diff-pre.sh
Executable file
47
src/diff-pre.sh
Executable file
@@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -x
|
||||||
|
|
||||||
|
if [[ -z "$IN_DIFF_URL" ]]; then
|
||||||
|
echo "::error title=Configuration error::Diffing results against a server was enabled, but the product URL is not configured."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -z "$IN_DIFF_USERNAME" && ! -z "$IN_DIFF_PASSWORD" ]]; then
|
||||||
|
echo "Configuring credentials..."
|
||||||
|
cat <<EOF > ~/.codechecker.passwords.json
|
||||||
|
{
|
||||||
|
"client_autologin": true,
|
||||||
|
"credentials": {
|
||||||
|
"$IN_DIFF_URL": "$IN_DIFF_USERNAME:$IN_DIFF_PASSWORD"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
chmod 0600 ~/.codechecker.passwords.json
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -z "$IN_DIFF_RUN_NAME" && "$IN_DIFF_RUN_NAME" != "__DEFAULT__" ]]; then
|
||||||
|
echo "Using user-requested run name."
|
||||||
|
echo "::set-output name=RUN_NAME::$IN_DIFF_RUN_NAME"
|
||||||
|
echo "::set-output name=DIFF_CONFIGURED::true"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$GITHUB_EVENT_NAME" == "pull_request" ]]; then
|
||||||
|
echo "Auto-generating run name for a PULL REQUEST's target (base)."
|
||||||
|
echo "::set-output name=RUN_NAME::$GITHUB_REPOSITORY: $GITHUB_BASE_REF"
|
||||||
|
echo "::set-output name=DIFF_CONFIGURED::true"
|
||||||
|
exit 0
|
||||||
|
elif [[ "$GITHUB_REF_TYPE" == "branch" ]]; then
|
||||||
|
echo "Auto-generating run name for a BRANCH."
|
||||||
|
echo "::set-output name=RUN_NAME::$GITHUB_REPOSITORY: $GITHUB_REF_NAME"
|
||||||
|
echo "::set-output name=DIFF_CONFIGURED::true"
|
||||||
|
exit 0
|
||||||
|
elif [[ "$GITHUB_REF_TYPE" == "tag" ]]; then
|
||||||
|
echo "Auto-generating run name for a TAG."
|
||||||
|
echo "::set-output name=RUN_NAME::$GITHUB_REPOSITORY tags"
|
||||||
|
echo "::set-output name=DIFF_CONFIGURED::true"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "::notice title=Preparation for diff::Failed to generate a run name. Implementation error?"
|
||||||
|
echo "::set-output name=DIFF_CONFIGURED::false"
|
||||||
70
src/diff.sh
Executable file
70
src/diff.sh
Executable file
@@ -0,0 +1,70 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -x
|
||||||
|
|
||||||
|
if [[ -z "$IN_DIFF_URL" ]]; then
|
||||||
|
echo "::error title=Internal error::environment variable 'IN_DIFF_URL' missing!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$PROJECT_PATH" ]]; then
|
||||||
|
echo "::error title=Internal error::environment variable 'PROJECT_PATH' missing!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$RAW_RESULT_DIR" ]]; then
|
||||||
|
echo "::error title=Internal error::environment variable 'RAW_RESULT_DIR' missing!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$CODECHECKER_DIFF_RUN_NAME" ]]; then
|
||||||
|
echo "::error title=Internal error::environment variable 'CODECHECKER_DIFF_RUN_NAME' missing!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
OUTPUT_DIR="$RAW_RESULT_DIR"_DiffHTML
|
||||||
|
OUTPUT_LOG="$(dirname "$RAW_RESULT_DIR")"/"$(basename "$RAW_RESULT_DIR")_Diff.log"
|
||||||
|
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
|
||||||
|
|
||||||
|
"$CODECHECKER_PATH"/CodeChecker \
|
||||||
|
cmd diff \
|
||||||
|
--new \
|
||||||
|
--url "$IN_DIFF_URL" \
|
||||||
|
--basename "$CODECHECKER_DIFF_RUN_NAME" \
|
||||||
|
--newname "$RAW_RESULT_DIR" \
|
||||||
|
--output html \
|
||||||
|
--export "$OUTPUT_DIR" \
|
||||||
|
$CONFIG_FLAG_1 $CONFIG_FLAG_2 \
|
||||||
|
|| true
|
||||||
|
echo "::set-output name=HTML_DIR::$OUTPUT_DIR"
|
||||||
|
|
||||||
|
"$CODECHECKER_PATH"/CodeChecker \
|
||||||
|
cmd diff \
|
||||||
|
--new \
|
||||||
|
--url "$IN_DIFF_URL" \
|
||||||
|
--basename "$CODECHECKER_DIFF_RUN_NAME" \
|
||||||
|
--newname "$RAW_RESULT_DIR" \
|
||||||
|
$CONFIG_FLAG_1 $CONFIG_FLAG_2 \
|
||||||
|
> "$OUTPUT_LOG"
|
||||||
|
EXIT_CODE=$?
|
||||||
|
|
||||||
|
cat "$OUTPUT_LOG"
|
||||||
|
echo "::set-output name=OUTPUT_LOG::$OUTPUT_LOG"
|
||||||
|
|
||||||
|
if [[ $EXIT_CODE -eq 2 ]]; then
|
||||||
|
echo "::set-output name=HAS_NEW_FINDINGS::true"
|
||||||
|
|
||||||
|
# Let the job continue. If there were new results, the script may be breaking
|
||||||
|
# the build in a later step. (After a potential upload to server.)
|
||||||
|
EXIT_CODE=0
|
||||||
|
elif [[ $EXIT_CODE -eq 0 ]]; then
|
||||||
|
echo "::set-output name=HAS_NEW_FINDINGS::false"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Exit code 1 is internal error of executing the step.
|
||||||
|
exit $EXIT_CODE
|
||||||
@@ -8,7 +8,7 @@ fi
|
|||||||
|
|
||||||
OUTPUT_DIR="$IN_OUTPUT_DIR"
|
OUTPUT_DIR="$IN_OUTPUT_DIR"
|
||||||
if [[ -z "$OUTPUT_DIR" ]]; then
|
if [[ -z "$OUTPUT_DIR" ]]; then
|
||||||
OUTPUT_DIR=~/"$ACTION_NAME"_Results
|
OUTPUT_DIR=~/"$GITHUB_ACTION_NAME"_Results
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -pv "$(dirname $"OUTPUT_DIR")"
|
mkdir -pv "$(dirname $"OUTPUT_DIR")"
|
||||||
|
|||||||
@@ -11,13 +11,9 @@ if [[ -z "$RAW_RESULT_DIR" ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
OUTPUT_DIR="$IN_OUTPUT_DIR"
|
OUTPUT_DIR="$RAW_RESULT_DIR"_HTML
|
||||||
if [[ -z "$OUTPUT_DIR" ]]; then
|
OUTPUT_LOG="$(dirname "$RAW_RESULT_DIR")"/"$(basename "$RAW_RESULT_DIR")_Diff.log"
|
||||||
OUTPUT_DIR=~/"$ACTION_NAME"_Results-HTML
|
mkdir -pv "$(dirname "$OUTPUT_DIR")"
|
||||||
fi
|
|
||||||
mkdir -pv "$(dirname $"OUTPUT_DIR")"
|
|
||||||
|
|
||||||
OUTPUT_LOG="$(dirname "$IN_OUTPUT_DIR")"/"$(basename "$IN_OUTPUT_DIR")_Parse.log"
|
|
||||||
|
|
||||||
if [[ ! -z "$IN_CONFIGFILE" ]]; then
|
if [[ ! -z "$IN_CONFIGFILE" ]]; then
|
||||||
CONFIG_FLAG_1="--config"
|
CONFIG_FLAG_1="--config"
|
||||||
@@ -38,16 +34,17 @@ echo "::set-output name=HTML_DIR::$OUTPUT_DIR"
|
|||||||
--trim-path-prefix "$PROJECT_PATH" \
|
--trim-path-prefix "$PROJECT_PATH" \
|
||||||
> "$OUTPUT_LOG"
|
> "$OUTPUT_LOG"
|
||||||
EXIT_CODE=$?
|
EXIT_CODE=$?
|
||||||
|
|
||||||
|
cat "$OUTPUT_LOG"
|
||||||
echo "::set-output name=OUTPUT_LOG::$OUTPUT_LOG"
|
echo "::set-output name=OUTPUT_LOG::$OUTPUT_LOG"
|
||||||
|
|
||||||
|
if [[ $EXIT_CODE -eq 2 ]]; then
|
||||||
if [[ $EXIT_CODE == "2" ]]; then
|
|
||||||
echo "::set-output name=HAS_FINDINGS::true"
|
echo "::set-output name=HAS_FINDINGS::true"
|
||||||
|
|
||||||
# Let the jobs continue. If there were failures, the script may be breaking
|
# Let the jobs continue. If there were findings, the script may be breaking
|
||||||
# the build in a later step. (After a potential upload to server.)
|
# the build in a later step. (After a potential upload to server.)
|
||||||
EXIT_CODE=0
|
EXIT_CODE=0
|
||||||
elif [[ $EXIT_CODE == 0 ]]; then
|
elif [[ $EXIT_CODE -eq 0 ]]; then
|
||||||
echo "::set-output name=HAS_FINDINGS::false"
|
echo "::set-output name=HAS_FINDINGS::false"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
7
test/simple2/compile_commands.json
Normal file
7
test/simple2/compile_commands.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"directory": "__DIRECTORY__",
|
||||||
|
"command": "g++ -c main.cpp -o main.o",
|
||||||
|
"file": "main.cpp"
|
||||||
|
}
|
||||||
|
]
|
||||||
3
test/simple2/main.cpp
Normal file
3
test/simple2/main.cpp
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
int main(int argc, char** argv) {
|
||||||
|
return sizeof(42);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user