feat: Expose and wire in the store command

This commit is contained in:
Whisperity
2021-11-29 16:22:28 +01:00
parent 6d2fc77005
commit 3c9baf21be
7 changed files with 285 additions and 13 deletions

View File

@@ -121,3 +121,75 @@ jobs:
with: with:
name: "Parse HTML test results" name: "Parse HTML test results"
path: ${{ steps.codechecker.outputs.result-html-dir }} path: ${{ steps.codechecker.outputs.result-html-dir }}
store:
name: "Store: Authenticated local store of single result"
runs-on: ubuntu-20.04
env:
CODECHECKER_VERSION: '6.18.0'
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: "Set up CodeChecker server"
run: |
set -x
sudo apt-get -y update
sudo apt-get -y install --no-install-recommends \
netcat \
wget
mkdir -pv ~/codechecker-server-data
chmod 1777 ~/codechecker-server-data
cp test/codechecker.server.json ~/codechecker-server-data/server_config.json
test/prepare-docker-server.sh
echo "::group::CodeChecker server configuration"
cd ~/codechecker-server-data
chown 950:950 server_config.json && chmod 0600 server_config.json
chown 950:950 root.user && chmod 0600 root.user
ls -alh
cat docker-compose.yml
cat root.user
cat server_config.json
echo "::endgroup::"
docker-compose up -d
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"
docker ps -a
echo "::group::CodeChecker server initial log output"
docker logs codechecker-server
echo "::endgroup::"
- run: test/fix_compile_json_paths.sh
- uses: ./
id: codechecker
continue-on-error: true
with:
version: "v${{ env.CODECHECKER_VERSION }}"
logfile: 'test/simple/compile_commands.json'
store: true
store-url: 'http://0.0.0.0:8001/Default'
store-username: 'root'
store-password: 'root'
- name: "Test if server logged store action"
id: test
continue-on-error: true
run: docker logs codechecker-server | grep "stored results"
- name: "Teardown CodeChecker server"
run: |
set -x
echo "::group::CodeChecker server log output"
docker logs codechecker-server
echo "::endgroup::"
cd ~/codechecker-server-data
docker-compose down
docker ps -a
- name: "Fail the build if the test execution failed"
if: ${{ steps.test.outcome == 'failure' || steps.codechecker.outcome == 'failure' }}
run: exit 1

View File

@@ -1,4 +1,4 @@
# [CodeChecker](http://github.com/Ericsson/CodeChecker/) C++ static analysis action # [CodeChecker](http://github.com/Ericsson/CodeChecker/) C++ Static Analysis action
GitHub Action to execute static analysis over C-family projects (C, C++, GitHub Action to execute static analysis over C-family projects (C, C++,
Objective-C) using the [Clang](http://clang.llvm.org/) infrastructure and Objective-C) using the [Clang](http://clang.llvm.org/) infrastructure and
@@ -26,7 +26,7 @@ Hence, it's recommended to configure your project in a **`Debug`** configuration
Add the job into your CI as follows. Add the job into your CI as follows.
The two versions are mutually exclusive — you either can give a compilation database, or you instruct CodeChecker to create one. The two versions are mutually exclusive — you either can give a compilation database, or you instruct CodeChecker to create one.
### Project can generate a [JSON Compilation Database](http://clang.llvm.org/docs/JSONCompilationDatabase.html) and build cleanly (no generated code) ### Projects that 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.
@@ -138,18 +138,32 @@ runs:
| Variable | Default | Description | | Variable | Default | Description |
|-------------------------|---------|-----------------------------------------------------------------------------------| |-------------------------|---------|---------------------------------------------------------------------------------------------------|
| `fail-build-if-reports` | `false` | If set to `true`, the build will be set to broken if the static analysers report. | | `fail-build-if-reports` | `false` | If set to `true`, the build will be set to broken if the static analysers reports _any_ findings. |
### Store settings
🔖 Read more about [`CodeChecker store`](http://codechecker.readthedocs.io/en/latest/web/user_guide/#store) in the official documentation.
| 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-url` | | The URL of the CodeChecker product to store to, **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 `store` was set to `true`. |
| `store-username` | | If the server requires authentication to access, specify the username which the upload should log in with. |
| `store-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. |
| `store-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. Runs can be stored incrementally, in which case CodeChecker is able to annotate that reports got fixed. |
## Action *`outputs`* to use in further steps ## 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. 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. | | `result-html-dir` | Auto-generated. | The directory where the **user-friendly HTML** bug reports were generated to. |
| `result-log` | Auto-generated. | `CodeChecker parse`'s output log file which contains the findings dumped into it. | | `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. |
| `warnings` | `true` or `false` | Whether the static analysers reported any findings. | | `warnings` | `true` or `false` | Whether the static analysers reported any findings. |

View File

@@ -44,6 +44,24 @@ inputs:
default: 'false' default: 'false'
required: true required: true
store:
description: 'Whether to enable storing the results to a CodeChecker server. If enabled, other flags, such as `store-url` must also be set.'
default: 'false'
required: true
store-url:
description: 'The CodeChecker product URL (usually in the format of http://example.com/ProductName) where the store should connect to. Mandatory if `store` is true.'
required: false
store-username:
description: 'If the server requires authentication, the username to authenticate with.'
required: false
store-password:
description: 'The password (or generated private access token) corresponding to the user.'
required: false
store-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.'
default: '__DEFAULT__'
required: true
outputs: outputs:
logfile: logfile:
description: 'The location of the JSON Compilation Database that was used for the analysis.' description: 'The location of the JSON Compilation Database that was used for the analysis.'
@@ -63,6 +81,10 @@ 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 }}
store-run-name:
description: 'The name of the analysis run that the results were uploaded to.'
value: ${{ steps.store-pre.outputs.RUN_NAME }}
runs: runs:
using: "composite" using: "composite"
steps: steps:
@@ -92,7 +114,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: ${{ inputs.store == 'true' }}
shell: bash shell: bash
run: | run: |
set -ex set -ex
@@ -169,3 +191,34 @@ runs:
run: | run: |
echo "Static analysis reported warnings, and user requested build breaking." echo "Static analysis reported warnings, and user requested build breaking."
exit 1 exit 1
- name: "Generate the configuration for uploading results"
id: store-pre
if: ${{ inputs.store == 'true' }}
env:
IN_STORE_URL: ${{ inputs.store-url }}
IN_STORE_USERNAME: ${{ inputs.store-username }}
IN_STORE_PASSWORD: ${{ inputs.store-password }}
IN_STORE_RUN_NAME: ${{ inputs.store-run-name }}
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_REF_NAME: ${{ github.ref_name }}
GITHUB_REF_TYPE: ${{ github.ref_type }}
GITHUB_SHA: ${{ github.sha }}
shell: bash
run: ${{ github.action_path }}/src/store-pre.sh
- name: "Store analysis results to server"
id: store
if: ${{ steps.store-pre.outputs.STORE_CONFIGURED == 'true' }}
env:
PROJECT_PATH: ${{ github.workspace }}
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 }}
IN_CONFIGFILE: ${{ inputs.config }}
IN_STORE_URL: ${{ inputs.store-url }}
shell: bash
run: ${{ github.action_path }}/src/store.sh

45
src/store-pre.sh Executable file
View File

@@ -0,0 +1,45 @@
#!/bin/bash
set -x
if [[ -z "$IN_STORE_URL" ]]; then
echo "::error title=Configuration error::Uploading results to a server was enabled, but the upload URL is not configured."
exit 1
fi
if [[ ! -z "$IN_STORE_USERNAME" && ! -z "$IN_STORE_PASSWORD" ]]; then
echo "Configuring credentials..."
cat <<EOF > ~/.codechecker.passwords.json
{
"client_autologin": true,
"credentials": {
"$IN_STORE_URL": "$IN_STORE_USERNAME:$IN_STORE_PASSWORD"
}
}
EOF
chmod 0600 ~/.codechecker.passwords.json
fi
if [[ ! -z "$IN_STORE_RUN_NAME" && "$IN_STORE_RUN_NAME" != "__DEFAULT__" ]]; then
echo "Using user-requested run name."
echo "::set-output name=RUN_NAME::$IN_STORE_RUN_NAME"
echo "::set-output name=RUN_TAG::"
echo "::set-output name=STORE_CONFIGURED::true"
exit 0
fi
if [[ "$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=RUN_TAG::$GITHUB_SHA"
echo "::set-output name=STORE_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=RUN_TAG::$GITHUB_REF_NAME"
echo "::set-output name=STORE_CONFIGURED::true"
exit 0
fi
echo "::notice title=Preparation for store::Failed to generate a run name. Implementation error?"
echo "::set-output name=STORE_CONFIGURED::false"

42
src/store.sh Executable file
View File

@@ -0,0 +1,42 @@
#!/bin/bash
set -x
if [[ -z "$IN_STORE_URL" ]]; then
echo "::error title=Internal error::environment variable 'IN_STORE_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_STORE_RUN_NAME" ]]; then
echo "::error title=Internal error::environment variable 'CODECHECKER_STORE_RUN_NAME' missing!"
exit 1
fi
if [[ ! -z "$IN_CONFIGFILE" ]]; then
CONFIG_FLAG_1="--config"
CONFIG_FLAG_2=$IN_CONFIGFILE
echo "Using configuration file \"$IN_CONFIGFILE\"!"
fi
if [[ ! -z "$CODECHECKER_STORE_RUN_TAG" ]]; then
RUN_TAG_FLAG_1="--tag"
RUN_TAG_FLAG_2=$CODECHECKER_STORE_RUN_TAG
fi
"$CODECHECKER_PATH"/CodeChecker \
store \
"$RAW_RESULT_DIR" \
--url "$IN_STORE_URL" \
--name "$CODECHECKER_STORE_RUN_NAME" \
--trim-path-prefix "$PROJECT_PATH" \
$RUN_TAG_FLAG_1 $RUN_TAG_FLAG_2 \
$CONFIG_FLAG_1 $CONFIG_FLAG_2

View File

@@ -0,0 +1,13 @@
{
"authentication": {
"enabled": true,
"session_lifetime": 86400,
"refresh_time": 86400,
"logins_until_cleanup": 42,
"method_dictionary": {
"enabled": true,
"auths": [],
"groups": {}
}
}
}

33
test/prepare-docker-server.sh Executable file
View File

@@ -0,0 +1,33 @@
#!/bin/bash
set -ex
if [[ -z "$CODECHECKER_VERSION" ]]; then
echo "::error title=Test configuration error::Missing environment variable 'CODECHECKER_VERSION'"
exit 1
fi
cat <<EOF > ~/codechecker-server-data/docker-compose.yml
version: '3'
services:
codechecker-server:
container_name: codechecker-server
image: "codechecker/codechecker-web:$CODECHECKER_VERSION"
ports:
- '8001:8001/tcp'
networks:
- codechecker-network
volumes:
- $HOME/codechecker-server-data:/workspace
networks:
codechecker-network:
driver: bridge
EOF
python3 - <<- EOF
import hashlib
with open("$HOME/codechecker-server-data/root.user", 'w',
encoding='utf-8', errors='ignore') as rootf:
rootf.write(f"root:{hashlib.sha256(b'root:root').hexdigest()}")
EOF