Main Content

Sample Scripts for Polyspace Analysis with Jenkins

In a continuous integration process, developers submit code to a shared repository. An automated build system using a tool such as Jenkins® builds and tests each submission at regular intervals or based on predefined triggers and integrates the code. You can run a Polyspace® analysis as part of this process.

A flow diagram of a typical continuous integration workflow. Developers submit code to a shared repository. Polyspace Server products can run on the newly submitted code and upload the results to a Polyspace Access web server. Multiple reviewers can fetch the results from the server and review the results on a web browser.

This topic provides sample Shell scripts that run a Polyspace analysis using Polyspace Bug Finder™ Server™ and upload the results for review in the Polyspace Access™ web interface. The script also sends e-mail notifications to potential reviewers. Notified reviewers can login to the Polyspace Access web interface (if they have a Polyspace Access license) and review the results.

Extending Sample Scripts to Your Development Process

The scripts are written for a specific development toolchain but can be easily extended to the processes used in your project, team or organization. The scripts are also meant to be run in a Jenkins freestyle project. If you are using Jenkins Pipelines, see Sample Jenkins Pipeline Scripts for Polyspace Analysis.

In particular, the scripts:

  • Run on Linux® only.

    The scripts use some Linux-specific commands such as export. However, these commands are not an integral part of the Polyspace workflow. If you write Windows® scripts (.bat files), use the equivalent Windows commands instead.

  • Work only with Jenkins after you install the Polyspace plugin.

    The scripts are designed for the Jenkins plugin in these two ways:

    • The scripts uses helper functions $ps_helper and $ps_helper_access for simpler scripting. The helper functions export Polyspace results for e-mail attachments and use command-line utilities to filter the results.

      These helper functions are available only with the Jenkins plugin. However, the underlying commands come with a Polyspace Bug Finder Server installation. On build automation tools other than Jenkins, you can create these helper functions using the polyspace-report-generator command or polyspace-access (Polyspace Access) command (with the -export option). See Send Email Notifications with Polyspace Bug Finder Server Results.

      If you perform a distributed build in Jenkins, the plugin must be installed in the same folder in the same operating system on both the master node and the agent node executing the Polyspace analysis. Otherwise, you cannot use the helper functions.

    • The scripts create text files for e-mail attachments and mail subjects and bodies for personalized e-mails. If you install the Polyspace plugin in Jenkins, an extension of an e-mail plugin is available for use in your Jenkins projects. The e-mail plugin allows you to easily send the personalized e-mails with the previously created subjects, bodies and attachments. Without the Polyspace plugin, you have to find an alternative way to send the e-mails.

  • Run a Bug Finder analysis.

    The scripts run Bug Finder on the demo example Bug_Finder_Example. If you install the product Polyspace Bug Finder Server, the folder containing the demo example is polyspaceserverroot/polyspace/examples/cxx/Bug_Finder_Example. Here, polyspaceserverroot is the installation folder for Polyspace Server products, for instance, /usr/local/Polyspace Server/R2019a/.

    You can easily adapt the script to run Code Prover. Replace polyspace-bug-finder-server with polyspace-code-prover-server. You can use the demo example Code_Prover_Example specifically meant for Code Prover.

Prerequisites

To run a Polyspace analysis on a server and review the results in the Polyspace Access web interface, you must perform a one-time setup.

  • To run the analysis, you must install one instance of the Polyspace Server product.

  • To upload results, you must set up the components required to host the web interface of Polyspace Access.

  • To view the uploaded results, you (and each developer reviewing the results) must have one Polyspace license.

Similar requirements apply to a Polyspace Code Prover™ analysis on a server.

See Install Polyspace Server and Access Products.

To install the Polyspace plugin, in the Jenkins interface, select Manage Jenkins on the left. Select Manage Plugin. Search for the Polyspace plugin and then download and install the plugin.

Set Up Polyspace Plugin in Jenkins

The following steps outline how to set up a Polyspace analysis in Jenkins after installing the Polyspace plugin. Note that the steps refer to Jenkins version 2.150.1. The steps in your Jenkins version and your Polyspace plugin installation might be slightly different.

If you use a different build automation tool, you can perform similar setup steps.

Specify Paths to Polyspace Commands and Server Details for Polyspace Access Web Interface

Specify the full paths of the folder containing the Polyspace commands and host name and port number of the server hosting the Polyspace Access web interface. After you specify the paths, in your scripts, you do not have to use the full paths to the commands or the server details for uploading results.

  1. In the Jenkins interface, select Manage Jenkins on the left. Select Configure System.

  2. In the Polyspace section, specify the following:

    • Paths to Polyspace commands.

      The path refers to polyspaceserverroot/polyspace/bin, where polyspaceserverroot is the installation folder for Polyspace Server products, for instance, /usr/local/Polyspace Server/R2019a/.

      Enter the path to Polyspace commands and a short name for the path.

    • The host name, port number and protocol (http or https) used by the server hosting the Polyspace Access web interface.

      Enter the protocol, host and port name for the Polyspace Access server, and a short name to refer to the server.

    The Name field allows you to define a convenient shorthand that you use later in Jenkins projects.

  3. In the E-mail Notification section, specify your company's SMTP server (and other details needed for sending e-mails).

    Enter email server details.

Create Jenkins Project for Running Polyspace

When you create a Jenkins project (for instance, a Freestyle project), you can refer to the Polyspace paths by the global shorthands that you defined earlier.

To create a Jenkins project for running Polyspace:

  1. In the Jenkins interface, select New Item on the left. Select Freestyle Project.

  2. In the Build Environment section of the project, enter the two shorthand names you defined earlier:

    • The name for the path to the folder containing the Polyspace commands

    • The name for the details of the server hosting the Polyspace Access web interface.

    Also, enter a login and password that can be used to upload to the Polyspace Access web interface. The login and password must be associated with a Polyspace Access license.

    Enter path to Polyspace commands and Polyspace Access server details using short names you created earlier. Enter credentials that can be used to log in to Polyspace Access.

  3. In the Build section of the project, you can enter scripts that use the Polyspace commands and details of the server hosting the Polyspace Access web interface. The scripts run a Polyspace analysis and upload results to the Polyspace Access web interface.

    Script to run Polyspace analysis from Jenkins

  4. In the Post-build Actions section of the project, configure e-mail addresses and attachments to be sent after the analysis.

    Enter email addresses of recipients, name of file with Polyspace results, mail subject and mail body.

Script to Run Bug Finder, Upload Results and Send Common Notification

This script runs a Bug Finder analysis, uploads the results and exports defects with high impact for a common notification email to all recipients.

The script assumes that the current folder contains a folder sources with .c files. Otherwise modify the line gcc -c sources/*.c with the full path to the sources.

set -e
export RESULT=ResultBF
export PROG=Bug_Finder_Example
export PARENT_PROJECT=/public/BugFinderExample_PRS_01

# ================================================================
# Trace build command and create an options file

build_cmd="gcc -c sources/*.c"
polyspace-configure \
      -allow-overwrite \
      -allow-build-error \
      -prog $PROG \
      -author jenkins \
      -output-options-file $PROG.psopts \
      $build_cmd


# ================================================================
# Run Bug Finder on the options file

polyspace-bug-finder-server -options-file $PROG.psopts -results-dir $RESULT

# ================================================================
# Upload results to Polyspace Access web interface

$ps_helper_access -create-project $PARENT_PROJECT
$ps_helper_access \
      -upload $RESULT \
      -parent-project $PARENT_PROJECT \
      -project $PROG

# ================================================================
# Export results filtered for defects with "High" impact

$ps_helper_access \
      -export $PARENT_PROJECT/$PROG \
      -output Results_All.tsv \
      -defects High

# ================================================================
# Finalize Jenkins status

exit 0

After the script is run, you can create a post-build action to send an e-mail to all recipients with the exported file Results_All.tsv.

Enter email addresses of recipients, name of file with Polyspace results, mail subject and mail body.

In this script, $ps_helper_access is a shorthand for the polyspace-access (Polyspace Access) command with the options specifying host name, port, login and encrypted password included. The other polyspace-access options are explicitly written in the script.

Script to Run Bug Finder, Upload Results and Send Personalized Notification

This script runs the previous Bug Finder analysis and uploads the results. However, the script differs from the previous script in these ways:

  • The script uses a run_command function that prints a message when running a command. The function helps determine from the console output which part of the script is running.

  • When exporting the results, the script creates a separate results file for different owners.

    • A main file Results_All.tsv contains all results. This file is sent in e-mail attachment to a manager. The manager email is configured in the post-build step.

      If the file contains more than 10 defects, the build status is considered as a failure. The script sends a status UNSTABLE in the e-mail notification.

    • The results file Results_Users_userA.tsv exported for userA contains defects from the group Programming and with impact High.

      This result file is sent in e-mail attachment to userA.

    • The results file Results_Users_userB.tsv exported for userB contains defects from the function bug_memstdlib().

      This result file is sent in e-mail attachment to userB.

  • A separate mail subject is created for the manager in the file mailsubject_manager.txt and for users userA and userB in the files mailsubject_user_userA.txt and mailsubject_user_userB.txt respectively.

    A mail body is created for the email to the manager in the file mailbody_manager.txt.

The script:

  • Assumes that the current folder contains a folder sources with .c files.

    Otherwise, modify the line gcc -c sources/*.c with the full path to the sources.

  • Assumes users named userA and userB. In particular, the email addresses userA@companyname.com and userB@companyname.com (determined from the user name and SMTP server configured earlier) must be real e-mail addresses.

    Replace the names with real user names.

set -e
export RESULT=ResultBF
export PROG=Bug_Finder_Example
export REPORT=Results_List.tsv


# ================================================================
# Define function to print message while running command
run_command()
{
# $1 is a message
# $2 $3 ... is the command to dump and to run
message=$1
shift
cat >> mailbody_manager.txt << EOF
$(date): $message

EOF
"$@"
}

# ================================================================
# Initialize mail body
cat > mailbody_manager.txt << EOF
Dear Manager(s)

Here is the report of the Jenkins Job ${JOB_NAME} #${BUILD_NUMBER}
It contains all Red Defect found in Bug Finder Example project

EOF

# ================================================================
# Trace build command and create options file

build_cmd="gcc -c sources/*.c"
run_command "Tracing build command",               \
            polyspace-configure                   \
                -allow-overwrite                  \
                -allow-build-error                \
                -prog $PROG                       \
                -author jenkins                   \
                -output-options-file $PROG.psopts \
                    $build_cmd

# ================================================================
# Run Bug Finder on the options file

run_command "Running Bug finder" \
            polyspace-bug-finder-server -options-file $PROG.psopts -results-dir $RESULT



# ================================================================
# Upload results to Polyspace Access web interface

run_command "Creating Project $PARENT_PROJECT" \
  $ps_helper_access -create-project $PARENT_PROJECT

run_command "Uploading on $PARENT_PROJECT/$PROG" \
  $ps_helper_access \
        -upload $RESULT \
        -parent-project $PARENT_PROJECT \
        -project $PROG \
        -output upload.output
PROJECT_RUNID=$($ps_helper prs_print_runid upload.output)
PROJECT_URL=$($ps_helper prs_print_projecturl upload.output $POLYSPACE_ACCESS_URL)

# ================================================================
# Export report

run_command "Exporting report from $PARENT_PROJECT/$PROG" \
  $ps_helper_access \
        -export $PROJECT_RUNID \
        -output $REPORT \
        -defects High


# ================================================================
# Filter Reports

run_command "Filtering reports for defects" \
            $ps_helper report_filter \
                $REPORT \
                Results_All.tsv \
                Family Defect \


# ================================================================
# Filter Reports for userA and userB

run_command "Filtering Reports for userA: Group=='Programming' and Information=='Impact: High'" \
            $ps_helper report_filter \
                $REPORT \
                Results_Users.tsv \
                userA \
                Group Programming \
                Information "Impact: High"
run_command "Filtering Reports for userB: Function=='bug_memstdlib()'" \
            $ps_helper report_filter \
                $REPORT \
                Results_Users.tsv \
                userB \
                Function "bug_memstdlib()"


# ================================================================
# Update Jenkins status
# Jenkins build status is unstable when there are more than 10 Defects

BUILD_STATUS=$($ps_helper report_status Results_All.tsv 10)

# ================================================================
# Update mail body and mail subject

NB_FINDINGS_ALL=$($ps_helper report_count_findings Results_All.tsv)
NB_FINDINGS_USERA=$($ps_helper report_count_findings Results_Users_userA.tsv)
NB_FINDINGS_USERB=$($ps_helper report_count_findings Results_Users_userB.tsv)
cat >> mailbody_manager.txt << EOF

Number of defects: $NB_FINDINGS_ALL
Number of findings owned by userA: $NB_FINDINGS_USERA
Number of findings owned by userB: $NB_FINDINGS_USERB

All results are uploaded in: $PROJECT_URL

Build Status: $BUILD_STATUS

EOF

cat >> mailsubject_manager.txt << EOF
Jenkins for Manager - Polyspace run completed with status $BUILD_STATUS and $NB_FINDINGS_ALL findings
EOF

for user in userA userB
do
  echo "Jenkins for $user - $($ps_helper report_count_findings Results_Users_$user.tsv)) findings" > mailsubject_user_$user.txt
done



# ================================================================
# Exit with correct build status

[ "$BUILD_STATUS" != "SUCCESS" ] && exit 129
exit 0

set -e
export RESULT=ResultBF
export PROG=Bug_Finder_Example
export REPORT=Results_List.tsv


# ================================================================
# Define function to print message while running command
run_command()
{
# $1 is a message
# $2 $3 ... is the command to dump and to run
message=$1
shift
cat >> mailbody_manager.txt << EOF
$(date): $message

EOF
"$@"
}

# ================================================================
# Initialize mail body
cat > mailbody_manager.txt << EOF
Dear Manager(s)

Here is the report of the Jenkins Job ${JOB_NAME} #${BUILD_NUMBER}
It contains all Red Defect found in Bug Finder Example project

EOF

# ================================================================
# Trace build command and create options file

build_cmd="gcc -c sources/*.c"
run_command "Tracing build command",               \
            polyspace-configure                   \
                -allow-overwrite                  \
                -allow-build-error                \
                -prog $PROG                       \
                -author jenkins                   \
                -output-options-file $PROG.psopts \
                    $build_cmd

# ================================================================
# Run Bug Finder on the options file

run_command "Running Bug finder" \
            polyspace-bug-finder-server -options-file $PROG.psopts\
            -results-dir $RESULT



# ================================================================
# Upload results to Polyspace Access web interface

run_command "Creating Project $PARENT_PROJECT" \
  $ps_helper_access -create-project $PARENT_PROJECT

run_command "Uploading on $PARENT_PROJECT/$PROG" \
  $ps_helper_access \
        -upload $RESULT \
        -parent-project $PARENT_PROJECT \
        -project $PROG \
        -output upload.output
PROJECT_RUNID=$($ps_helper prs_print_runid upload.output)
PROJECT_URL=$($ps_helper prs_print_projecturl upload.output $POLYSPACE_ACCESS_URL)

# ================================================================
# Export report

run_command "Exporting report from $PARENT_PROJECT/$PROG" \
  $ps_helper_access \
        -export $PROJECT_RUNID \
        -output $REPORT \
        -defects High


# ================================================================
# Filter Reports

run_command "Filtering reports for defects" \
            $ps_helper report_filter \
                $REPORT \
                Results_All.tsv \
                Family Defect \


# ================================================================
# Filter Reports for userA and userB

run_command "Filtering Reports for userA based on Group and Information" \
            $ps_helper report_filter \
                $REPORT \
                Results_Users.tsv \
                userA \
                Group Programming \
                Information "Impact: High"
run_command "Filtering Reports for userB based on Function" \
            $ps_helper report_filter \
                $REPORT \
                Results_Users.tsv \
                userB \
                Function "bug_memstdlib()"


# ================================================================
# Update Jenkins status
# Jenkins build status is unstable when there are more than 10 Defects

BUILD_STATUS=$($ps_helper report_status Results_All.tsv 10)

# ================================================================
# Update mail body and mail subject

NB_FINDINGS_ALL=$($ps_helper report_count_findings Results_All.tsv)
NB_FINDINGS_USERA=$($ps_helper report_count_findings Results_Users_userA.tsv)
NB_FINDINGS_USERB=$($ps_helper report_count_findings Results_Users_userB.tsv)
cat >> mailbody_manager.txt << EOF

Number of defects: $NB_FINDINGS_ALL
Number of findings owned by userA: $NB_FINDINGS_USERA
Number of findings owned by userB: $NB_FINDINGS_USERB

All results are uploaded in: $PROJECT_URL

Build Status: $BUILD_STATUS

EOF

cat >> mailsubject_manager.txt << EOF
Polyspace run completed with status $BUILD_STATUS and $NB_FINDINGS_ALL findings
EOF

for user in userA userB
do
echo "$user - $($ps_helper report_count_findings Results_Users_$user.tsv)) findings"\
      > mailsubject_user_$user.txt
done



# ================================================================
# Exit with correct build status

[ "$BUILD_STATUS" != "SUCCESS" ] && exit 129
exit 0

After the script is run, you can create a post-build action to send an e-mail to a manager with the exported file Results_All.tsv. Specify the e-mail address in the Recipients field, the email subject in the Mail Subject field and the email body in the Mail Body field.

In addition, a separate e-mail is sent to userA and userB with the files Results_Users_userA.tsv and Results_Users_userB.tsv in attachment (and the content of mailsubject_user_userA.txt and mailsubject_user_userB.txt as mail subjects). The e-mail addresses are userA@companyname.com and userB@companyname.com (determined from the user name and SMTP server configured earlier).

Enter email addresses of recipients, name of file with Polyspace results, mail subject and mail body.

The script uses the helper function $ps_helper to filter the results based on group, impact and function. The helper function uses command-line utilities to filter the main file for results and perform actions such as create a separate results file for each owner. The function takes these actions as arguments:

  • report_filter: Filters results from exported text file based on contents of the text file.

    For instance:

    $ps_helper report_filter \
                    Results_List.tsv \
                    Results_Users.tsv \
                    userA \
                    Group Programming \
                    Information "Impact: High"
    reads the file Results_List.tsv and writes to the file Results_Users_userA.tsv. The text file Results_List.tsv contains columns for Group and Information. Only those rows where the Group column contains Programming and the Information column contains Impact: High are written to the file Results_Users_userA.tsv.

  • report_status: Returns UNSTABLE or SUCCESS based on the number of results in a file.

    For instance:

    BUILD_STATUS=$($ps_helper report_status Results_All.tsv 10))
    returns UNSTABLE if the file Results_All.tsv contains more than 10 results (10 rows).

  • report_count_findings: Reports number of results in a file.

    For instance:

    NB_FINDINGS_ALL=$($ps_helper report_count_findings Results_All.tsv)
    returns the number of results (rows) in the file Results_All.tsv.

  • prs_print_projecturl: Uses the host name and port number to create the URL of the Polyspace Access web interface.

    For instance:

    PROJECT_URL=$($ps_helper prs_print_projecturl Results_All.tsv $POLYSPACE_ACCESS_URL)
    
    reads the file Results_All.tsv (exported by the polyspace-access command) and extracts the URL of the Polyspace Access web interface in $POLYSPACE_ACCESS_URL and the URL of the current project in $PROJECT_URL.

See Also

| (Polyspace Code Prover) | | (Polyspace Access) |

Related Topics