name: 'CodeChecker Static Analysis' author: 'Whisperity' description: 'Execute C/C++ static analysis of LLVM/Clang (Clang Static Analyzer and Clang-Tidy) driven via CodeChecker.' branding: icon: 'tool' color: 'blue' inputs: repository: description: 'The CodeChecker repository to check out and build from.' required: true default: 'Ericsson/CodeChecker' version: description: 'The version of the CodeChecker suite to obtain and execute. Might be a Git commit SHA, a branch name, or a tag.' required: true default: 'master' llvm-version: description: 'The major version of LLVM to install and use. LLVM is installed from PPA. If "latest", automatically gather the latest version. If "ignore", do not install anything. (Not recommended)' required: true default: 'latest' config: description: 'The CodeChecker configuration JSON that contains for each CodeChecker action (analyze, parse, ...) the list of flags that should be appended to the invocation of the command.' required: false logfile: description: 'The location of the JSON Compilation Database for the project. This file describes how the project is compiled, and thus how it should be analysed. Mutually exclusive with "build-command".' required: false build-command: description: 'The build command to execute and log for the creation of a JSON Compilation Database. Mutually exclusive with "logfile".' 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 fail-build-if-reports: description: 'Whether to fail the build if static analysis warnings are emitted.' 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 }} warnings: description: 'Whether the static analyser(s) reported any findings.' value: ${{ steps.parse.outputs.HAS_FINDINGS }} result-log: description: 'The file where the output of CodeChecker parse is written to verbatim.' value: ${{ steps.parse.outputs.OUTPUT_LOG }} result-html-dir: description: 'The output directory where the user-friendly HTML reports were stored to.' value: ${{ steps.parse.outputs.HTML_DIR }} runs: using: "composite" steps: - name: "Check out repository ${{ inputs.repository }}" uses: actions/checkout@v2 with: repository: ${{ inputs.repository }} path: CodeChecker ref: ${{ inputs.version }} - name: "Install dependencies of CodeChecker" shell: bash run: | sudo apt-get -qy update ${{ github.action_path }}/src/apt-dependencies.sh - name: "Install LLVM version" id: llvm if: ${{ inputs.llvm-version != 'ignore' }} env: CONFIGURED_LLVM_VERSION: ${{ inputs.llvm-version }} shell: bash run: | ${{ github.action_path }}/src/get-llvm.sh echo "::set-output name=REAL_VERSION::$(clang --version | head -n 1 | cut -d' ' -f4-)" - name: "Build and Package CodeChecker" id: codechecker env: CODECHECKER_WILL_USE_WEB_API: "false" # TODO: Add support for this later. shell: bash run: | set -ex if [[ "$CODECHECKER_WILL_USE_WEB_API" == "false" ]]; then # If the job is only running analysis, do not spend time with building the API stuff! echo "Building only 'analyzer' module..." pushd CodeChecker/analyzer else echo "Building full CodeChecker package..." pushd CodeChecker fi make venv source venv/bin/activate BUILD_UI_DIST=NO make standalone_package deactivate ./build/CodeChecker/bin/CodeChecker analyzer-version if [[ "$CODECHECKER_WILL_USE_WEB_API" == "true" ]]; then ./build/CodeChecker/bin/CodeChecker web-version else echo "CodeChecker 'web' package not built." fi echo "::set-output name=PATH::$(readlink -f ./build/CodeChecker/bin)" echo "::set-output name=VERSION::$(./build/CodeChecker/bin/CodeChecker analyzer-version | grep 'Base package' | cut -d'|' -f 2 | tr -d ' ')" echo "::set-output name=GITSEVEN::$(./build/CodeChecker/bin/CodeChecker analyzer-version | grep 'Git commit' | cut -d'|' -f 2 | cut -c 2-8)" popd - name: "Prepare JSON Compilation Database" id: log env: ACTION_NAME: ${{ github.action }} CODECHECKER_PATH: ${{ steps.codechecker.outputs.PATH }} IN_LOGFILE: ${{ inputs.logfile }} IN_COMMAND: ${{ inputs.build-command }} OUT_FILE: ${{ github.workspace }}/${{ github.action }}_codechecker_compilation_database.json shell: bash 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 - name: "Parse and convert results" id: parse env: PROJECT_PATH: ${{ github.workspace }} CODECHECKER_PATH: ${{ steps.codechecker.outputs.PATH }} RAW_RESULT_DIR: ${{ steps.analyze.outputs.OUTPUT_DIR }} IN_CONFIGFILE: ${{ inputs.config }} IN_FAIL_IF_REPORTS: ${{ inputs.fail-build-if-reports }} IN_OUTPUT_DIR: ${{ inputs.analyze-output }} shell: bash run: ${{ github.action_path }}/src/parse-results.sh - name: "Fail the build if requested and warnings detected" if: ${{ steps.parse.outputs.HAS_FINDINGS == 'true' && inputs.fail-build-if-reports == 'true' }} shell: bash run: | echo "Static analysis reported warnings, and user requested build breaking." exit 1