CodeSonar analysis in a GitHub workflow on Linux with Docker

The following instructions are for Linux Containers using Docker. These instructions assume you are using CodeSonar 7.3 or later, where the codesonar analyze -remote-archive option is supported.

Prerequisites

These instructions assume that you have satisfied the prerequisites as described in the setup overview document.

In particular, make sure you have access to the following.

Overview

A. Prepare an example project (zlib):

For the sake of an easy, but realistic example, we will assume you want to build and analyze zlib (https://github.com/madler/zlib) version 1.2.9.

  1. On your developer workstation, clone the zlib repository from github.com.

    git clone https://github.com/madler/zlib
    
  2. Create a new GitHub repository project named "zlib" (or similar) in your GitHub server instance with the following properties:

    • Private or Internal visibility (not public).
    • Do not initialize with a README or a ".gitignore" file.
  3. Follow the instructions provided by the GitHub repository page to "push an existing repository" in order to push your local zlib repository clone to your GitHub server.

  4. Enable GitHub Advanced Security Testing (GHAS) (if available). See the Settings > Security & analysis page.

    After following the GitHub instructions, your local zlib repository should be configured so that its "origin" is on your GitHub server, and not the original GitHub.com location.

    You should now have an example zlib repository in your GitHub server. You will build and analyze this in the steps that follow.

  5. Create and push a branch called example for Git tag 'v1.2.9'.

    git branch example v1.2.9
    git push origin -u example
    git checkout example
    

    This new branch will serve as your example "main" branch. You will use it as a base branch for further branches in the steps below.

The instructions in this document were tested with zlib versions 1.2.9 and 1.2.12.

Note that zlib version 1.2.13 introduced GitHub Action workflows intended to be used on GitHub.com. Since those Action workflows will conflict with the Action workflows we want to demonstrate here, it is easiest to test with older versions of zlib such as 1.2.9.

B. Create and install an analysis data server container:

NOTE If you plan to analyze your code using a remote-managed or SaaS analysis service, then you do not need to install an analysis data server Go on to C. Create and install a build workflow runner.

Otherwise, set up an analysis data server now.

C. Create and install a build workflow runner

  1. If needed, create a CodeSonar CI hub user.

    You will need a CodeSonar hub user account that can be used for automated workflow jobs. If you previously created a hub user for an analysis data server, then you can use that account here too. Otherwise, create a new hub user account.

    The instructions will assume that the hub user name is cshub_ci.

  2. If you have not already done so, identify a suitable CI builder host machine.

    This "CI builder" machine is distinct from the "analysis data server" machine prepared previously, however it is possible to use the same machine for both analysis data server and CI builder.

    • This can be a physical machine or a virtual machine.
  3. Log in to your CI builder machine as a user with root access. Depending on your local system, you may need to use sudo with some or all of the commands in this section.

  4. If it is not already installed, use your package manager to install Docker Engine.

    See https://docs.docker.com/engine/install/#server for more information

  5. If GitHub Actions Runner is not already installed, install and register a GitHub Actions Runner.

    A GitHub runner configured for Docker must run directly on your host machine. It is possible to run a GitHub Actions runner in a container, but in that case it cannot itself start new containers. If you try to run a workflow in a container using a runner that is itself in a container, then the GitHub action will fail during the "Initialize Containers" phase, and an error will be printed:

    Error: Container feature is not supported when runner is already running inside container.

    1. Go to the Settings > Actions page for your GitHub repository.
    2. Click the Add Runner button.

      This will open a new page that provides instructions for installing the runner software and registering the runner instance.

    3. Follow the instructions to install, register, and run the runner on your CI builder machine.

  6. Log out of the CI builder machine.

See https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners for more information.

D. Create a basic workflow that can build your code

Before introducing analysis, we will define a workflow job that simply builds the code.

The workflow definition is specified in a YAML file saved in a .github/workflows/ directory in the root of your code repository. For information about the GitHub Actions workflow YAML file syntax see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions.

If you are not familiar with YAML format, you may want to read about it at https://yaml.org/spec/1.2/spec.html#Preview. Note that YAML is very sensitive to indentation.

You don't need to be logged on to your runner machine to create workflow job images.

The steps below should be carried out from your developer workstation.

  1. Create a Docker image for building your code.

    1. Create an empty directory named "zlib.build".

      The zlib.build directory can exist anywhere on disk. It could be saved in the Git repository, but we will not assume so in this example.

    2. Save the content below to a file named "Dockerfile" in the "zlib.build" directory.

      FROM ubuntu:18.04
      RUN apt-get update && apt-get install -y git gcc make
      
    3. Change to the zlib.build directory.

      cd zlib.build
      
    4. Build the image and push it to the GitHub Docker registry. The CI builder runner will be able to download images from the Docker registry.

      Script variables. You may need to adjust one or more variable settings before executing the script.

      Variable Setting
      CI_REGISTRY The address of your Docker registry: typically the host name of your GitHub server.
      CI_REGISTRY_IMAGE The fully-qualified Docker image name. This will include the name of the Docker registry where it is found (in this case, CI_REGISTRY).
      CI_IMAGE_VERSION A Docker image tag which indicates the version of the image.

      Script. Adjust variable settings as described in the table above, then execute this script to build and push the image.

      CI_REGISTRY=docker.example.com
      CI_REGISTRY_IMAGE=$CI_REGISTRY/examples/zlib
      CI_IMAGE_VERSION=latest
      
      docker login $CI_REGISTRY
      docker build -t $CI_REGISTRY_IMAGE:$CI_IMAGE_VERSION - < Dockerfile
      docker push $CI_REGISTRY_IMAGE:$CI_IMAGE_VERSION
      
  2. Configure GitHub Secrets for your Docker registry credentials.

    If your Docker registry requires a user name and password/token, store these as GitHub secrets so that your build job can retrieve and use them to pull your Docker images.

    1. Navigate to the Settings > Secrets page for your GitHub repository.
    2. Add new Secrets to store your Docker registry credentials:

      Name of Secret Secret Value
      DOCKER_USER example_registry_user_name
      DOCKER_PASS XYZ123exampleTOKEN789
  3. Change to the root directory of your local repository clone.

  4. Check out the example branch that you created earlier.

    git checkout example
    
  5. Create directory .github/workflows.

    mkdir -p .github/workflows
    
  6. Create a new workflow YAML file and save it to .github/workflows/build.yml.

  7. Insert the following content into .github/workflows/build.yml, editing as needed.

    Notice the use of the "example" branch in the on:push:branches and on:pull_request:branches items. This code assumes that you have pushed your "example" branch to your GitHub server (as described previously).

    name: Build
    on:
      push:
        branches:
          - master
          - example  # your 'example' branch
      pull_request:
        branches:
          - master
          - example  # your 'example' branch
    jobs:
      build:
        runs-on:
          - self-hosted
          - Linux
          - Docker
        container:
          # Your CI builder Docker image registry path here
          image: "docker.example.com/examples/zlib:latest"
          credentials:
            username: '${{ secrets.DOCKER_USER }}'
            password: '${{ secrets.DOCKER_PASS }}'
        timeout-minutes: 360
        steps:
          - uses: actions/checkout@v2
          - name: Configure build scripts
            run: ./configure
          - name: Compile
            run: make
    
  8. Create a repository branch named "example_build" (or whatever else you prefer) where you can save your new CI workflow definition file. Add your workflow to the branch.

    git checkout -b example_build
    git add .github/workflows/build.yml
    
  9. Commit and push your workflow file to your GitHub server.

    git commit -m "Add CI workflow configuration"
    git push -u origin example_build
    
  10. Test the workflow.

    1. Create a pull request for the branch you just pushed

      The git push command from the previous step may print a URL to help you create a pull request. You can also use the GitHub GUI directly to create a new pull request associated with your new branch. When you create a new pull request for your new branch, GitHub will notice the workflow definition file and will use it to execute the workflow jobs on your CI builder machine.

      Important: Be sure to set the example branch (created previously) as the base branch for your pull request.

    2. Verify that the workflow executed successfully.

      Use the GitHub "Pull request" web page to find the status of your repository code "check" actions. If everything works correctly, you should see that your workflow action executed and if you inspect the actions log, you should see that the code was successfully compiled.

    If the workflow did not execute successfully, fix it before going on to the next step.

    1. Merge your pull request into the 'example' base branch.

      This will merge your example_build branch into the example base branch. Merging your pull request will add the new build.yml file to your example branch.

    2. Check out the example branch again and pull the newly merged changes.

      git checkout example
      git pull origin
      

E. Install CodeSonar and integration tools in CI builder environment

At this stage, you should have a workflow that successfully compiles your code. The next task is to create a new Docker image where you can build and analyze your code using CodeSonar.

  1. Log in to your developer machine.
  2. Download and extract the CodeSonar-GitHub integration .tar.gz file.

    1. Download the CodeSonar-GitHub integration tools package (e.g. codesonar-github-integration-1.3p0.tar.gz).

    2. Change to a suitable user directory. The integration tools will be used for creating a Docker container, but will not be used directly by service processes.

    3. Extract the package.

      tar -xzf /path/to/codesonar-github-integration-1.3p0.tar.gz
      
  3. Change to the distro-image subdirectory in the extracted CodeSonar-GitHub integration files.

    Inspect the contents. There should be a Dockerfile: this can be used to create a new Docker image from your project's base image with CodeSonar added to it.

  4. Copy your CodeSonar software installation file into the distro-image directory. The name will be something like codesonar-8.0p0.20231117-x86_64-pc-linux.tar.gz (version number and datestamp will vary).

    The Dockerfile contains instructions to extract the CodeSonar programs from the CodeSonar install package and copy them into the "/opt" directory in the Docker image.

  5. [HTTPS hubs only] Download a copy of your CodeSonar hub's hub server certificate. We will use this copy to ensure that the CodeSonar command line tools in your Docker image will trust your hub.

    • If your hub uses plain HTTP protocol (and not secure HTTPS), skip this step.
    • Otherwise:

      • Download the hub server certificate from the hub Configure HTTPS page.

        See the Troubleshooting document for additional information about how to download this file.

      • Save the certificate in Base-64 ASCII text format (often called "PEM" format) as distro-image/cacert.pem.

  6. Build a new CodeSonar Docker image using distro-image/Dockerfile.

    This new CodeSonar Docker image will be based on your project's builder Docker image. It will be used to introduce CodeSonar into your workflow. This will allow CodeSonar to observe and analyze your code as it builds.

    Consult the comments in distro-image/Dockerfile for descriptions of the Docker build arguments used in this section. Many of the build arguments used here are optional and are intended to reduce the size of the Docker image. In particular, zlib contains no Java code so we omit all the components used for Java analysis. If you want Java (or .NET) analysis, then remove --buildarg JAVA_ANALYSIS=0 from the command below.

    Script variables. You may need to adjust one or more variable settings before executing the script. Note that some of the variables used here were initialized in previous steps.

    Variable Setting
    CI_REGISTRY, CI_REGISTRY_IMAGE, CI_IMAGE_VERSION Must have exactly the same values as were used to create the builder image.
    CODESONAR_PACKAGE The name of the CodeSonar installer file that you copied to distro-image

    Script. Adjust variable settings as described in the table above, then execute this script to build the image.

    CI_REGISTRY=docker.example.com
    CI_REGISTRY_IMAGE=$CI_REGISTRY/examples/zlib
    CI_IMAGE_VERSION=latest
    CODESONAR_PACKAGE=codesonar-8.0p0.20231117-x86_64-pc-linux.tar.gz
    CODESONAR_IMAGE=$CI_REGISTRY_IMAGE/codesonar
    CODESONAR_IMAGE_VERSION=latest
    CODESONAR_HUB_CACERT=cacert.pem
    
    docker build --tag $CODESONAR_IMAGE:$CODESONAR_IMAGE_VERSION \
        --build-arg BASE_IMAGE=$CI_REGISTRY_IMAGE:$CI_IMAGE_VERSION \
        --build-arg CODESONAR_PACKAGE=$CODESONAR_PACKAGE \
        --build-arg CODESONAR_HUB_CACERT=$CODESONAR_HUB_CACERT \
        --build-arg TELEMETRY=1 \
        --build-arg HUB=0 \
        --build-arg JAVA_ANALYSIS=0 \
        --build-arg PYTHON_ANALYSIS=0 \
        --build-arg JAVA_API=0 \
        --build-arg CSHARP_API=0 \
        --build-arg ECLIPSE=0 \
        --build-arg CONFIG_TOOL=0 \
        .
    
  7. Push the new CodeSonar Docker image to your container registry.

    docker login $CI_REGISTRY
    docker push $CODESONAR_IMAGE:$CODESONAR_IMAGE_VERSION
    

F. Update the workflow definition to perform CodeSonar analysis

Most of the steps that follow should be performed in your local example (zlib) repository on your developer workstation.

  1. Generate a CodeSonar hub user certificate and key.

    • If you already have a suitable hub user certificate and private key, you do not need to generate new ones. When you set up GitHub Secrets CODESONAR_HUB_USER_CERT_FILE and CODESONAR_HUB_USER_KEY_FILE later, use the contents of your existing files. Go on to the next step.

    In this example we will configure the workflow to perform certificate-based hub authentication.

    If you cannot use certificate-based authentication (for example, because your hub is not configured for HTTPS), skip this step: you will modify the authentication-related command elements in later steps.

    Certificate generation requires the CodeSonar command line tools. If you don't have CodeSonar installed on your developer workstation, install it before proceeding. Alternatively, you could start a shell in a temporary Docker container on the CodeSonar analysis image that you built in part E and use the CodeSonar command line tools there.

    1. Start a new container using your CodeSonar Docker image, and open an interactive bash shell prompt.

      CI_REGISTRY=docker.example.com
      CI_REGISTRY_IMAGE=$CI_REGISTRY/examples/zlib
      CI_IMAGE_VERSION=latest
      CODESONAR_IMAGE=$CI_REGISTRY_IMAGE/codesonar
      CODESONAR_IMAGE_VERSION=latest
      
      docker run -it "$CODESONAR_IMAGE:$CODESONAR_IMAGE_VERSION" bash

      1. Execute the following script, which includes a codesonar generate-hub-cert command.

        Script variables. You may need to adjust one or more variable settings before executing the script.

        Variable Setting
        CSONAR Your CodeSonar installation.
        CSONAR_HUB Your hub location.
        CSONAR_HUBUSER Your hub user account. Note that the command below uses this as both the username of the account that is authorizing certificate generation and the username of the account that is the subject of the certificate.

        Script. Adjust variable settings as described in the table above, then execute this script.

        CSONAR=/opt/codesonar
        CSONAR_HUB=https://codesonar.example.com:7340
        CSONAR_HUBUSER=cshub_ci
        CSONAR_HUBCERT=$CSONAR_HUBUSER.cert
        CSONAR_HUBKEY=$CSONAR_HUBUSER.key
        
        $CSONAR/codesonar/bin/codesonar generate-hub-cert \
            -foruser "$CSONAR_HUBUSER" \
            -auth password \
            -hubuser "$CSONAR_HUBUSER" \
            -out "$CSONAR_HUBCERT" \
            -outkey "$CSONAR_HUBKEY" \
            "$CSONAR_HUB"
        

    2. Provide the hub user account password when prompted.

      New files $CSONAR_HUBUSER.cert and $CSONAR_HUBUSER.key will be created, where $CSONAR_HUBUSER is the name of your hub CI user account. These files contain your certificate and private key, respectively.

      You can use the standard cat command to show the contents of the certificate and/or key files as needed.

    3. Copy these two files and save them somewhere temporarily. For example:

      1. Execute cat $CSONAR_HUBUSER.cert (where $CSONAR_HUBUSER is the name of your hub CI user account) to view the contents of the certificate file.
      2. Use your system tools to copy the text of the certificate file from the terminal and paste into a text editor on the host machine.
      3. Save the certificate text to disk.
      4. Repeat these steps to save the contents of the private key file $CSONAR_HUBUSER.key.
    4. Exit the bash shell and the container.

      exit
      

  2. Configure GitHub Secrets for your CodeSonar hub credentials.

    Add your hub user certificate and key file contents to your GitHub repository's Secrets store. This will permit your analysis job to authenticate with your CodeSonar hub without an interactive password prompt.

    If you need to authenticate with a password instead of a hub user certificate, set up a password secret instead.

    Copy the entire contents of the hub certificate and key files that you created in the previous step into separate GitHub Secret entries.

    The CodeSonar hub user associated with the CODESONAR_HUB_USER_CERT Secret must have permissions to create a new analysis for your project.

    Name of Secret Example Value Notes
    CODESONAR_HUB_USER_CERT -----BEGIN CERTIFICATE-----\nMIIEabcdefghi ... For certificate-based authentication only: the contents of the hub user certificate file that you generated above. You do not need to escape newline characters when entering the secret value in the GitHub Secret value form. The '\n' characters in the example are not intended to be copied literally.
    CODESONAR_HUB_USER_KEY -----BEGIN PRIVATE KEY-----\nMIIEjklmnopqr ... For certificate-based authentication only: the contents of the hub user certificate private key file that you generated above. You do not need to escape newline characters when entering the secret value in the CI/CD variable value form. The '\n' characters in the example are not intended to be copied literally.
  3. Download a copy of your GitHub server's HTTPS root certificate.

    In some cases, CodeSonar's Python interpreter will refuse to communicate with your GitHub server since it does not trust your GitHub server's HTTPS certificate. This may happen if your GitHub server uses a recently-issued certificate. In order to avoid a potential problem later, you can provide a copy of the certificate to CodeSonar in your workflow configuration.

    1. Download a copy of the root authority certificate for your GitHub Server's HTTPS certificate.
    2. Save this root certificate to your repository working directory in Base-64 ASCII text format (often called "PEM" format).

    See the Troubleshooting document for additional information about how to download this file. We will assume you have saved the root certificate file to the root of your local repository with the name "github.root.cacert".

  4. Configure your workflow to use CodeSonar.

    1. Create a new text file named analyze.yml and save it in your repository .github/workflows subdirectory.

      You will use this file to define a new "analyze" workflow job in order to analyze your code.

    2. Copy the example workflow file shown below into your new analyze.yml file and modify it as follows.

      • Update variables as required.

        Variable Setting
        CODESONAR The path to the codesonar binary in your CodeSonar installation.
        CSPYTHON The path to the cspython binary in your CodeSonar installation.
        GITHUB_CAFILE The path to your GitHub Server's HTTPS root authority certificate file (which you downloaded in the previous step).
        CODESONAR_HUB_URL Your hub location (protocol://host:port).
        CODESONAR_GITHUB The path to the /distro-image/codesonar-github subdirectory of your CodeSonar-GitHub integration tools installation.
        CODESONAR_REMOTE_LAUNCHDS The set of remote launch daemons to use with remote-archive or remote. If you have followed these instructions exactly, this will be "/analysis-data-server/*". For SaaS analyses, set to "/saas/*".

        Other variables in the file are set to values that have already been set up.

        • CODESONAR_HUB_USER_CERT and CODESONAR_HUB_USER_KEY are set using the certificate-related GitHub secrets that you configured above.
        • GITHUB_TOKEN is set using secrets.GITHUB_TOKEN, which is always available.
        • Various variables are set to values in the github.event.* space: these are set by default in a GitHub action. For more information, see https://docs.github.com/en/actions/learn-github-actions/variables.
      • Ensure that the runner labels after the runs-on keyword match the runner that will run your CodeSonar analysis container.

      • Update the image keyword to refer to the Docker image you created earlier.

      • For CodeSonar SaaS or other remote-managed analysis, replace

        -remote-archive "$CODESONAR_REMOTE_LAUNCHDS"
        

        with

        -remote  "$CODESONAR_REMOTE_LAUNCHDS"
        
      • To provide a different name for your analysis, modify the -name value.

      • For password-based authentication, perform the additional steps below.

      • The -property arguments are used for adding additional, searchable data to your CodeSonar analysis. They are included here since they are often helpful for searching for analyses related to specific code commits. You may want to add more -property arguments in order to retain more searchable data for the analysis.

      • Note the use of shell "parameter expansion" syntax used to "coalesce" variables to the first non-empty value. Some versions of CodeSonar do not allow -property values to be empty. The workflow example shown below uses parameter expansions to try and ensure properties are not assigned to empty values. An example parameter expansion is:

        COMMIT="${PULL_REQUEST_SHA:-$GITHUB_SHA}"
        

        This will set the variable COMMIT to $PULL_REQUEST_SHA if $PULL_REQUEST_SHA is defined and non-empty, otherwise COMMIT will be set to the value of $GITHUB_SHA, which is assumed to be defined.

      For full details of the codesonar analyze command, see the CodeSonar manual: Using CodeSonar > Building and Analyzing Projects > Command Line Build/Analysis

      Example:

      name: Analyze
      on:
        push:
          branches:
            - master
            - example    # your 'example' branch
        pull_request:
          branches:
            - master
            - example    # your 'example' branch
      jobs:
        analyze:
          runs-on:
            - self-hosted
            - Linux
            - Docker
          container:
            # CodeSonar analysis Docker image registry path here
            image: "docker.example.com/examples/zlib/codesonar:latest"
            credentials:
              username: '${{ secrets.DOCKER_USER }}'
              password: '${{ secrets.DOCKER_PASS }}'
          env:
            GITHUB_CAFILE: ".github/github.root.cacert"
            GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
            PULL_REQUEST_ID: "${{ github.event.pull_request.number }}"
            PULL_REQUEST_SHA: "${{ github.event.pull_request.head.sha }}"
            PROJECT_NAME: "${{ github.event.repository.name }}"
            CODESONAR_PROJECT: "${{ github.event.repository.name }}"
            CODESONAR_PROJECT_FILE: "${{ github.event.repository.name }}"
            # Your CodeSonar hub base URL
            CODESONAR_HUB_URL: "https://codesonar.example.com:8443"
            CODESONAR_HUB_USER_CERT: "${{ secrets.CODESONAR_HUB_USER_CERT }}"
            CODESONAR_HUB_USER_KEY: "${{ secrets.CODESONAR_HUB_USER_KEY }}"
            CODESONAR_HUB_USER_CERT_FILE: "codesonar.hub.user.cert"
            CODESONAR_HUB_USER_KEY_FILE: "codesonar.hub.user.key"
            # Your CodeSonar remote launchd group
            CODESONAR_REMOTE_LAUNCHDS: "/analysis-data-server/*"
            CODESONAR: "/opt/codesonar/codesonar/bin/codesonar"
            CSPYTHON: "/opt/codesonar/codesonar/bin/cspython"
            CODESONAR_GITHUB: "/opt/codesonar-github"
          timeout-minutes: 360
          steps:
            - uses: actions/checkout@v2
            - name: Create Hub Credential Files
              run: >
                echo "$CODESONAR_HUB_USER_CERT" > "$CODESONAR_HUB_USER_CERT_FILE"
                && echo "$CODESONAR_HUB_USER_KEY" > "$CODESONAR_HUB_USER_KEY_FILE"
            - name: Configure the build scripts
              run: ./configure
            - name: Compile and Analyze the Code
              run: >
                BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME:-$GITHUB_REF}}" ;
                TARGET="${GITHUB_BASE_REF:-${GITHUB_REF_NAME:-$GITHUB_REF}}" ;
                COMMIT="${PULL_REQUEST_SHA:-$GITHUB_SHA}" ;
                "$CODESONAR" analyze
                "$CODESONAR_PROJECT_FILE"
                -wait
                -remote-archive "$CODESONAR_REMOTE_LAUNCHDS"
                -auth certificate -hubcert "$CODESONAR_HUB_USER_CERT_FILE" -hubkey "$CODESONAR_HUB_USER_KEY_FILE"
                -project "$CODESONAR_PROJECT"
                -name "github-ci ref=$BRANCH os=$RUNNER_OS job=$GITHUB_JOB.$GITHUB_RUN_NUMBER commit=$COMMIT"
                -property branch "$BRANCH"
                -property commit "$COMMIT"
                -property target "$TARGET"
                -property os "$RUNNER_OS"
                -property ci_url "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
                -property ci_job "$GITHUB_JOB"
                -property ci_run "$GITHUB_RUN_NUMBER"
                -property ci_run_id "$GITHUB_RUN_ID"
                "$CODESONAR_HUB_URL"
                make
            - name: Pull Analysis Results from CodeSonar Hub
              run: >
                "$CODESONAR" dump_warnings.py
                -o warnings.sarif
                --hub "$CODESONAR_HUB_URL"
                -auth certificate -hubcert "$CODESONAR_HUB_USER_CERT_FILE" -hubkey "$CODESONAR_HUB_USER_KEY_FILE"
                --project-file "$CODESONAR_PROJECT_FILE"
                --sarif
                --src-root "$GITHUB_WORKSPACE"
                -t 7200
            - name: Cleanup Credential Files
              run: shred -u "$CODESONAR_HUB_USER_CERT_FILE" "$CODESONAR_HUB_USER_KEY_FILE"
            - name: Push Analysis Results to GitHub
              uses: github/codeql-action/upload-sarif@v1
              with:
                sarif_file: warnings.sarif
            - name: Push Summary Report
              if: ${{ github.event.pull_request }}
              run: >
                "$CSPYTHON" "$CODESONAR_GITHUB/sarif_summary.py"
                warnings.sarif
                "$CODESONAR_HUB_URL"
                "$CODESONAR_PROJECT_FILE"
                --title "CodeSonar Analysis (Docker)"
                | "$CSPYTHON" "$CODESONAR_GITHUB/push_github_pr_comment.py"
                --api-url "$GITHUB_API_URL"
                --cafile "$GITHUB_CAFILE"
                "$GITHUB_REPOSITORY"
                "$PULL_REQUEST_ID"
                GITHUB_TOKEN
      
  5. Create a new branch named example_analysis1 from your example branch.

    This branch will introduce your analysis workflow to GitHub, and will result in your first analysis of your Git repository.

    git checkout -b example_analysis1
    
  6. Add and commit your updated files to your Git repository and push the changes to GitHub. If you need to add the GitHub server certificate file to your repository, you should do that here too.

    For example:

    git add .github/github.root.cacert
    git add .github/workflows/analyze.yml
    git commit -m "Add CodeSonar analysis workflow"
    git push -u origin example_analysis1
    
  7. Follow GitHub instructions to create a pull request for your new branch.

    Important: When opening the new pull request, be sure to set example as the base branch.

  8. After the analysis completes, refresh the pull request Checks tab page to see the analysis results.

    • You should see a Code scanning results item which can be expanded to reveal a CodeSonar item.
  9. Click the CodeSonar item to show the analysis results.

    • The analysis page will say "1 analysis not found". This is expected.
    • Notice that the page shows a table of "Analyses". The row for the analyze.yml file will show "Not found" in the "Base branch" column.

      This is because we have not previously run an analysis on the example branch, yet GitHub wants to compare the analysis for your example_analysis1 branch against a previous analysis for the example branch. This condition always occurs when you run your first analysis on a base branch.

  10. View your pull request Conversation page.

    It will show a message with a summary of analysis results.

    • The number of warnings, grouped into high/medium/low severity rankings.
    • The most frequent warnings, by warning class.

    Analysis Report

    Fix any errors with the analysis workflow or the summary content before going on to the next step.

  11. Merge your example_analysis1 pull request.

    • This will add the new analyze.yml file to your example branch.
    • It will also cause GitHub to remember the analysis result from your pull request and use it as a "base" analysis for comparing "incremental" changes made later.

G. Incremental Analysis workflow setup

  1. Pull the new merge commit for the example branch, then create a new branch named example_analysis2 from the example branch.

    git checkout example
    git pull origin
    git checkout -b example_analysis2
    
  2. Change the code and commit it.

    Ordinarily, you would make changes to your code and commit the changes before pushing them to the GitHub server. To simulate making changes to the code for this zlib example we will merge a newer version of the zlib code into your branch. This will allow you to analyze the new version of the code and to let GitHub show you the differences.

    We will merge version v1.2.12 of the zlib code by using the v1.2.12 git tag stored in the zlib repository.

    git merge v1.2.12
    

    The merge command below should open a text editor asking you for a commit message. Accept the default message by saving and closing the text editor.

  3. Push your changes to the GitHub server.

    git push origin -u example_analysis2
    
  4. Open a pull request that targets the example branch.

    When opening the pull request for your new example_analysis2 branch, be sure to set example as the base branch.

  5. Wait for the analysis workflow to complete, then check results.

    The Code scanning results for your new pull request will highlight the differences between the first analysis and the second.

CONGRATULATIONS! You have finished setting up the workflow!

Notes

Modifications for password-based authentication

If you need to authenticate your CodeSonar commands with a password instead of with a certificate, make the following changes.

  1. Instead of configuring GitHub secrets for a hub user certificate and corresponding private key, configure a secret for your hub user account password.

    Name of Secret Example Value
    CODESONAR_HUBUSER cshub_ci
    CODESONAR_HUB_PASSWD mYpAssw0rd123
  2. When you are setting up the analyze.yml file, make the following additional changes.

    1. Replace

           CODESONAR_HUB_USER_CERT: "${{ secrets.CODESONAR_HUB_USER_CERT }}"
           CODESONAR_HUB_USER_KEY: "${{ secrets.CODESONAR_HUB_USER_KEY }}"
           CODESONAR_HUB_USER_CERT_FILE: codesonar.hub.user.cert
           CODESONAR_HUB_USER_KEY_FILE: codesonar.hub.user.key
      

      with

           CODESONAR_HUBUSER: "${{ secrets.CODESONAR_HUBUSER }}"
           CODESONAR_HUB_PASSWD: "${{ secrets.CODESONAR_HUB_PASSWD }}"
           CODESONAR_HUBPWFILE: codesonar.hub.user.passwd
      
    2. Replace

              echo "$CODESONAR_HUB_USER_CERT" > "$CODESONAR_HUB_USER_CERT_FILE"
              && echo "$CODESONAR_HUB_USER_KEY" > "$CODESONAR_HUB_USER_KEY_FILE"
      

      with

              echo "$CODESONAR_HUB_PASSWD" > "$CODESONAR_HUBPWFILE"
      
    3. Replace each occurrence of

              -auth certificate -hubcert "$CODESONAR_HUB_USER_CERT_FILE" -hubkey "$CODESONAR_HUB_USER_KEY_FILE"
      

      with

               -auth password -hubuser "$CODESONAR_HUBUSER" -hubpwfile "$CODESONAR_HUBPWFILE"
      

      (note that there are multiple occurrences).