Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
former_member475940
Discoverer
SAP Community Moderator Note: This blog post is outdated. The SAP Cloud SDK for Continuous Delivery and its features have been merged into project "Piper". Therefore we recommend to use the General Purpose Pipeline of project "Piper" instead of the SAP Cloud SDK pipeline. The reasoning for this change, as well as further information on how to adopt the General Purpose Pipeline are described in this guide.

----------------------------------------------------------------------------------------------------------------------------

This blog post will guide you through the static code checks performed by the SAP Cloud SDK Pipeline as part of the Continuous integration and delivery (CI-CD) process.

Note: This post is part of a series. For a complete overview please visit the SAP Cloud SDK Overview.

 

The goal of this blog post


By the end of this article, you will have an overview of the static code checks stage and configuration involved. You should also be able to analyze the log and identify the cause of the failure of pipeline execution.

This tutorial will cover the following areas

  1. Introduction to static code check

  2. Static code check stage in CI-CD

  3. Why use both FindBugs and PMD

  4. Static code checks by FindBugs

  5. Static code checks by PMD




For a better understanding of this article, we suggest you read the following tutorials first:

Step 14 with SAP Cloud SDK: Continuous integration and delivery


Introduction to static code check


Analyzing the source code for detecting bugs and vulnerabilities is an important stage in a software development lifecycle (SDLC). Bugs that are detected in an early stage of SDLC can be fixed easily than that are identified in later stages such as bugs identified in a productive environment. Static code analysis and Dynamic code analysis are the two widely used code analysis techniques in enterprise software development.

Static code check is a systematic way of examining the application code base for identifying potential bugs that may arise during run-time. It is performed either on source code or on the binaries which are generated after compilation. Static code check with its white box visibility can analysis the entire application and detect bugs before executing the application.

Dynamic code analysis tools, on the other hand, are used to analyze system which is already in operation state and it can identify bugs that are too complicated for static code analysis. However, the scope of the dynamic code analysis is limited to the block of code that is in an execution state.

Static code check stage in CI-CD


SAP Cloud SDK Pipeline performs the static code checks of the application code in order to achieve the highest quality in the deliverable artifact. This is executed in parallel with the unit and integration test stages as you can see in the following figure. This stage currently examines code base with the help of two widely used static code analysis software namely FindBugs and PMD. Following sections will elaborate on the configuration of this software in detail in an SAP Cloud SDK Pipeline context.



Why use both FindBugs and PMD?


PMD performs static code analysis on source code level whereas FindBugs uses bytecode for analysis. PMD can identify issues like usage of == instead of equals whereas FindBugs can help to identify improper implementation of equals method.  Even though, both FindBugs and PMD overlaps on reporting few issues they largely complement each other. Hence, SAP Cloud SDK Pipeline makes use of the capabilities of both of these tools.

Static code checks by FindBugs


FindBugs is an open source software which performs static code analysis on Java programs to identify bugs. You can run FindBugs against your source code by using Command Line Interface (CLI) or with the help of maven plugin. FindBugs can also be integrated with most of the commonly used IDEs and with Jenkins as an additional plugin.

While using the Jenkins server which is set up by cx-server script, the FindBugs plugin is already installed for you. However, if you are using different Jenkins server then FindBugs plugin needs to be installed prior to executing SAP Cloud SDK Pipeline.

Execution as a maven goal


FindBugs can be locally executed as a maven goal with the below command in your project root directory. This will generate a bug report under the target directory with the name findbugsXml.xml.
$ mvn clean install findbugs:findbugs

FIndBugs can also be customized to include or whitelist some of the bugs during analysis. This can be achieved through the Filter Files which can be provided as an argument.
$ mvn clean install findbugs:findbugs -Dfindbugs.includeFilterFile=includeFilter.xml -Dfindbugs.excludeFilterFile=excludeFilter.xml

FindBugs as a Pipeline stage


SAP Cloud SDK Pipeline executes FindBugs plugin during static code checks. The include filter file used by the pipeline can be found here and the bug descriptions of individual filters can be found here. SAP Cloud SDK Pipeline has a zero tolerance to major bugs hence the execution of the pipeline will be marked as FAILURE if there is any major bug in the code or as many as 10 minor bugs. You will see a FindBugs trend graph on job dashboard of your Cx server. The intuitively red line in the graph indicates major bugs whereas yellow line indicates minor bugs.


Pipeline execution log upon any major bug discovery may look similar to the following.
[Pipeline] findbugs
12:38:58 [FINDBUGS] Collecting findbugs analysis files...
12:38:58 [FINDBUGS] Searching for all files in /var/jenkins_home/workspace/Controller-CF_test_findbugs that match the pattern **/findbugsXml.xml
12:38:58 [FINDBUGS] Parsing 1 file in /var/jenkins_home/workspace/Controller-CF_test_findbugs
12:38:58 [FINDBUGS] Successfully parsed file /var/jenkins_home/workspace/Controller-CF_test_findbugs/application/target/findbugsXml.xml with 3 unique warnings and 0 duplicates.
12:38:58 Skipping warnings blame since pipelines do not have an SCM link.%n
12:38:58 [FINDBUGS] Computing warning deltas based on reference build #24
12:38:58 [FINDBUGS] Plug-in Result: Failed - <a href="findbugsResult">2 warnings</a> of <a href="findbugsResult/HIGH">priority High</a> exceed the threshold of 0 by 2
[Pipeline] fileExists
[Pipeline] dir
12:38:58 Running in /var/jenkins_home/workspace/Controller-CF_test_findbugs/s4hana_pipeline/reports
[Pipeline] {
[Pipeline] sh
12:38:58 [reports] Running shell script
12:38:59 + cp -p /var/jenkins_home/workspace/Controller-CF_test_findbugs/application/target/findbugsXml.xml .
[Pipeline] }
[Pipeline] // dir
[Pipeline] echo
12:38:59 --- END LIBRARY STEP: checkFindbugs.groovy ---
[Pipeline] echo
12:38:59 Current build result: FAILURE
[Pipeline] error
[Pipeline] echo
12:38:59 ----------------------------------------------------------
12:38:59 --- ERROR OCCURED IN LIBRARY STEP: executeStaticCodeChecks
12:38:59 ----------------------------------------------------------
12:38:59
12:38:59 FOLLOWING PARAMETERS WERE AVAILABLE TO THIS STEP:
12:38:59 ***
12:38:59 [script:WorkflowScript@73c0cbf3]
12:38:59 ***
12:38:59
12:38:59 ERROR WAS:
12:38:59 ***
12:38:59 hudson.AbortException: Build was ABORTED and marked as FAILURE, please examine static code check results.
12:38:59 ***
12:38:59
12:38:59
[Pipeline] echo
12:38:59 --- END LIBRARY STEP: executeStaticCodeChecks.groovy ---
GitHub has been notified of this commit’s build result

ERROR: Build was ABORTED and marked as FAILURE, please examine static code check results.
Finished: FAILURE

Troubleshooting


Once the FindBugs reports any bug, you can get additional details about the file and about the block of code which resulted in the failure of the check by clicking on the FindBugs trend graph. Upon clicking on the graph you will be navigated to a detailed view as shown in the below image.



Click on the source file name to see the reason for the warning and the source code which needs a fix.





 

Upon fixing the bugs, a successful FindBugs analysis log will look like below.
[Pipeline] findbugs
12:36:24 [FINDBUGS] Collecting findbugs analysis files...
12:36:24 [FINDBUGS] Searching for all files in /var/jenkins_home/workspace/Controller-CF_test_findbugs that match the pattern **/findbugsXml.xml
12:36:24 [FINDBUGS] Parsing 1 file in /var/jenkins_home/workspace/Controller-CF_test_findbugs
12:36:24 [FINDBUGS] Successfully parsed file /var/jenkins_home/workspace/Controller-CF_test_findbugs/application/target/findbugsXml.xml with 0 unique warnings and 0 duplicates.
12:36:24 Skipping warnings blame since pipelines do not have an SCM link.%n
12:36:24 [FINDBUGS] Computing warning deltas based on reference build #23
12:36:24 [FINDBUGS] Ignore new warnings since this is the first valid build
12:36:24 [FINDBUGS] Plug-in Result: Success - no threshold has been exceeded

Configuration


SAP Cloud SDK Pipeline requires no configuration in the project level to execute FindBugs. However, if a bug which is identified by FindBugs has to be reclassified with a different priority in your project then you can configure the same as part of Exclude filter. An example FindBugs exclude filter file excludeFilter.xmlis shown below.
<FindBugsFilter>
<Match>
<Class name="com.foobar.MyClass" />
<Method name="someMethod" />
<Bug pattern="IJU_NO_TESTS" />
<Priority value="2" />
</Match>
</FindBugsFilter>

Once you create such an Exclude filter file, configure your pipeline_config.yml file by adding below configuration in steps block.
steps:
checkFindbugs:
excludeFilterFile : excludeFilter.xml

Static code checks by PMD


Like FindBugs, PMD is also an open source static code analysis tool. PMD performs static code analysis on source code instead of bytecode. Every violation of standard coding practice is classified as one of the five priorities where priority 1 signifies the critical violation and 5 can be considered as a minor violation. You will see a PMD trend graph on your Cx server job dashboard after the execution of the pipeline that would look similar to the following image.



Execution as a maven goal


You can also execute PMD against the source code by invoking maven plugin. However, this will not check SAP specific rules.
$ mvn clean install pmd:pmd 


PMD as part of Pipeline


Execution of PMD as part of SAP Cloud SDK Pipeline will perform SAP specific static code analysis on the source code in addition to standard PMD rules. In order to achieve this, PMD has been extended as a custom plugin which is distributed along with SAP Cloud SDK. Below is the list of quality rules used by the SAP Cloud SDK Pipeline during PMD static code checks.

OnlyUseCloudLoggerFactoryRule


The CloudLogger helps to log all important result in a way that it can be easily consumed by the SAP Cloud Platform. When instantiating a logger only use the CloudLoggerFactory which is provided by the SDK. Logging on SAP Cloud SDK provides an overview of logging mechanism in SDK. This rule has a priority of 2.

Example:
//Use 
private static final Logger logger = CloudLoggerFactory.getLogger(Foo.class);

//Instead of
private static final Logger logger = LoggerFactory.getLogger(Foo.class);


HandleExceptionsRule


In order to allow postmortem analyzability of the application, it is important to log the exception in the catch block or in a method that has been invoked in a catch block or referencing the exception in a newly thrown exception. This rule has a priority of 1.
// Use
protected List<Foo> convertResult (Result result){
try {
return result.asList(Foo.class);
} catch (final Exception e) {
throw new CustomExceptionHandler(e); // Use own exception handler to deal with exception object 'e'
}
}

//Instead of
protected List<Foo> convertResult (Result result){
try {
return result.asList(Foo.class);
} catch (final Exception e) {
handleException();
}
}

ReferenceExceptionRule


If you log an error or warning in an exception you should reference the exception object in your logger entry. This rule has a priority of 2.
// Use
protected List<Foo> convertResult (Result result){
try {
return result.asList(Foo.class);
} catch (final Exception e) {
logger.warn("Some exception happened", e);
}
}

//Instead of
protected List<Foo> convertResult (Result result){
try {
return result.asList(Foo.class);
} catch (final Exception e) {
logger.warn("Some exception happened");
}
}

 

UseSdkPlatformAbstractionsRule


SAP cloud SDK provides an abstraction to access some platform level information such as

  • Cloud platform environment

  • Destination and connectivity services

  • Tenant context

  • User context

  • Audit logging


For a complete list of platform abstraction and examples please visit the blog post on Cloud Platform Abstractions. In order to allow a smooth transition from Neo to CloudFoundry you should use the platform abstractions provided by the SAP Cloud SDK. This rule has a priority of 2.

Generic PMD rules


In addition to SAP specific rules, generic quality rules from PMD is also being used by the pipeline. They are listed below. These rules are subset of rules of PMD which can be found here.

  • rulesets/java/basic.xml/BrokenNullCheck

  • rulesets/java/basic.xml/MisplacedNullCheck

  • rulesets/java/basic.xml/ReturnFromFinallyBlock

  • rulesets/java/basic.xml/UnconditionalIfStatement

  • rulesets/java/clone.xml/CloneThrowsCloneNotSupportedException

  • rulesets/java/design.xml/AvoidInstanceofChecksInCatchClause

  • rulesets/java/design.xml/NonCaseLabelInSwitchStatement

  • rulesets/java/design.xml/PreserveStackTrace

  • rulesets/java/empty.xml/EmptyCatchBlock

  • rulesets/java/imports.xml/UnusedImports

  • rulesets/java/logging-java.xml/LoggerIsNotStaticFinal

  • rulesets/java/logging-java.xml/MoreThanOneLogger

  • rulesets/java/logging-java.xml/SystemPrintln

  • rulesets/java/strictexception.xml/AvoidThrowingNewInstanceOfSameException

  • rulesets/java/strictexception.xml/AvoidThrowingNullPointerException

  • rulesets/java/strictexception.xml/AvoidThrowingRawExceptionTypes

  • rulesets/java/strictexception.xml/DoNotThrowExceptionInFinally

  • rulesets/java/strictexception.xml/SignatureDeclareThrowsException

  • rulesets/java/sunsecure.xml/MethodReturnsInternalArray


 

Log entry of your pipeline will look similar to the extract of the log below.
[Pipeline] pmd
11:56:49 [PMD] Collecting PMD analysis files...
11:56:50 [PMD] Searching for all files in /var/jenkins_home/workspace/Controller-CF_test_PMD that match the pattern **/target/pmd.xml
11:56:50 [PMD] Parsing 3 files in /var/jenkins_home/workspace/Controller-CF_test_PMD
11:56:50 [PMD] Successfully parsed file /var/jenkins_home/workspace/Controller-CF_test_PMD/application/target/pmd.xml with 4 unique warnings and 0 duplicates.
11:56:50 [PMD] Successfully parsed file /var/jenkins_home/workspace/Controller-CF_test_PMD/integration-tests/target/pmd.xml with 4 unique warnings and 0 duplicates.
11:56:50 [PMD] Successfully parsed file /var/jenkins_home/workspace/Controller-CF_test_PMD/unit-tests/target/pmd.xml with 4 unique warnings and 0 duplicates.
11:56:50 Skipping warnings blame since pipelines do not have an SCM link.%n
11:56:50 [PMD] Computing warning deltas based on reference build #33
11:56:50 [PMD] Plug-in Result: Failed - <a href="pmdResult">1 warning</a> of <a href="pmdResult/HIGH">priority High</a> exceeds the threshold of 0 by 1
[Pipeline] echo
11:56:50 --- END LIBRARY STEP: checkPmd.groovy ---

 

Troubleshooting


Once you encounter a failure in the pipeline due to PMD analysis, you can visit the build dashboard of your Cx server which will contain the summary of the PMD scan along with the PMD graph.



 

SAP Cloud SDK Pipeline has zero tolerance for any major violation. When PMD scan fails, kindly look into the analysis details either by clicking on the PMD warning icon  or on the PMD Trend graph to get additional details on the reported issues. Upon clicking on the icon you will be navigated to a detailed view of the analysis report.



Click on the source file of your interest and navigate to Details tab to check the root cause of the error.

 





 

 

 

 

 

Upon fixing the bugs, a successful PMD analysis log will look like below.
[Pipeline] pmd
12:13:22 [PMD] Collecting PMD analysis files...
12:13:22 [PMD] Searching for all files in /var/jenkins_home/workspace/Controller-CF_test_PMD that match the pattern **/target/pmd.xml
12:13:22 [PMD] Parsing 3 files in /var/jenkins_home/workspace/Controller-CF_test_PMD
12:13:22 [PMD] Successfully parsed file /var/jenkins_home/workspace/Controller-CF_test_PMD/application/target/pmd.xml with 3 unique warnings and 0 duplicates.
12:13:22 [PMD] Successfully parsed file /var/jenkins_home/workspace/Controller-CF_test_PMD/integration-tests/target/pmd.xml with 3 unique warnings and 0 duplicates.
12:13:22 [PMD] Successfully parsed file /var/jenkins_home/workspace/Controller-CF_test_PMD/unit-tests/target/pmd.xml with 3 unique warnings and 0 duplicates.
12:13:22 Skipping warnings blame since pipelines do not have an SCM link.%n
12:13:22 [PMD] Computing warning deltas based on reference build #35
12:13:22 [PMD] Plug-in Result: Success - no threshold has been exceeded

Configuration


SAP Cloud SDK Pipeline requires no configuration at the project level to execute PMD. However, like FindBugs you can whitelist files from PMD scan by configuring them in Stage configuration of the pipeline_config.yml file.
stages:
staticCodeChecks:
findbugsExcludesFile: '' #Path to findbugs exclude file
pmdExcludes: '**/*Manifest.java' # List or ANT style patterns

Conclusion


Static code analysis helps you to improve the quality of the code and avoid propagation of bugs to later stages of the SDLC. Integration of Static code check in an SAP Cloud SDK Pipeline is a step towards ensuring better quality production system. The requirement of no pre-configuration makes it an easy to use feature.
5 Comments