Creating a CI/CD Pipeline with Static Code Analysis for Java Projects

By naman
CI/CD Pipeline with Static Code Analysis

Each developer should follow coding standards when writing the code. Running Static code analysis timely fixes bugs, uncomplicating software testing and deployment process. It ensures the overall code quality.

Creating a CI/CD Pipeline with Static Code Analysis for software development is gaining popularity to develop apps faster with quality and predictability. Without executing the program, static code analysis tools find bugs by examining the code, such as concurrency, data flow, dynamic memory, numerical defects, etc..

This article will explore setting up static analysis for Java projects. To start with, we will be discussing three tools for static code analysis:

  • CheckStyle: CheckStyle is a development tool that helps you to write Java code adhering to the coding standard. It constantly checks the Java code to spare humans from this task. It is highly configurable and made to support almost any coding standard. 
  • Findbugs: Findbugs is a free software that uses static analysis to check for bugs in Java code. It generates a report that lists the bugs that lead to the software misbehavior.
  • PMD: PMD is an extensible cross-language static code analyzer that finds common programming flaws like unused variables, empty catch blocks in Java, etc. Also, a Copy/Paste Detector (CPD) is integrated with PMD to check duplicated code in a source code.

Set Up Static Code Analysis for Java 

To make things easy, we will consider Gradle as the build tool. It has inbuilt plugins that we can use for our static code analysis.

Key tip: 

  • Setup files will reside in./gradle/static-code-analysis folder. 
  • Each of our static analysis tools (along with the additional files) will have its dedicated folder. 
  • Finally, staticCodeAnalysis.gradle will aggregate all our static code analysis settings.

Setting up Static Code Analysis

First, add the Gradle CPD plugin to our Gradle script to run Copy/Paste detection. Here is how you can specify the buildscript section before applying the plugin:

buildscript {
   repositories {
       mavenCentral()
   }
   dependencies {
       classpath 'de.aaschmid:gradle-cpd-plugin:1.1'
   }
}
apply plugin: 'checkstyle'
apply plugin: 'findbugs'
apply plugin: 'pmd'
apply plugin: de.aaschmid.gradle.plugins.cpd.CpdPlugin

Once the plugins are included in the buildscript, you can configure all the plugins. Let’s first start with configuring the CheckStyle.

CheckStyle

For CheckStyle plugin, you must set ignoreFailures flag, toolVersion and configFile, which will point to the location of a configuration file. We will use Google Code Style settings to set the base for our configuration file. Make sure that you use four space indentation instead of 2 space indentation.

checkstyle {
   toolVersion = '8.12'
   ignoreFailures = false
   configFile = file("${rootGradleDir}/static-code-analysis/checkstyle/checkstyle.xml")
}

We have explicitly set the plugin not to ignore failures by writing code ignoreFailures = false. It means the project build will fail if we run into any issues during the static code analysis check. That is for any problem in our code base (compile failure, unit test failure); we won't continue with our pipeline as long as we have an issue. CI/CD pipeline will fail if we encounter any code base issue.

FindBugs

You should specify toolVersion and ignoreFailures. There are also other options you can set here: specify which bug detectors you want to run. In our blog, we will leave the default values; all default bug detectors will be run, and we won’t exclude any file from FindBugs detection.

findbugs {
   toolVersion = '3.0.1'
   ignoreFailures = false
}

PMD

For PMD, you should set toolVersion and ignoreFailures and the rule sets for code analysis. We can set the rule sets in two ways. 

You can specify them directly inside the PMD plugin configuration using the ruleSets array, or you can extract the rule sets to separate xml file and reference file using the ruleSetFiles configuration parameter. 

In our blog, we will continue extracting the rule sets since it is more descriptive and allows us to provide exclusions to default rule set categories, like for the code style category. We are excluding DefaultPackage, OnlyOneReturn rules.

pmd {
   toolVersion = '6.7.0'
   ignoreFailures = false
   ruleSetFiles = files("${rootGradleDir}/static-code-analysis/pmd/ruleset.xml")
   ruleSets = []
   rulePriority = 3
}

CPD (Copy/Paste bug detection)

For Copy/Paste bug detection, you should configure the CPD plugin. You can set the minimumTokenCount flag as per your program requirements. 

Let’s set the minimumTokenCount to 100. It means the plugin detects duplicate code bugs by getting 5–10 lines of the same code in separate places. If four or fewer lines of code are matched, bugs won’t be detected. 

One helpful option while using frameworks is setting the ignoreAnnotations flag to true. It allows us to ignore “false positives” and is useful where classes/ methods have the same 5–6 lines of annotations. Finally, enable generating xml by setting xml.enabled flag to true.

cpd {
   language = 'java'
   toolVersion = '6.0.0'
   minimumTokenCount = 100 
}
cpdCheck {
   reports {
       text.enabled = false
       xml.enabled = true
   }
   ignoreAnnotations = true
   source = sourceSets.main.allJava
}

 Now, the static analysis code is configured. Now, include staticCodeAnalysis.gradle into Gradle build script:

apply from: "${rootGradleDir}/staticCodeAnalysis.gradle"

Static Code Analysis

You can run a static code analysis plugin with the same Java version you use to run Gradle.

  • Each plugin will add its dependencies to the Java plugin check task, such as pmdMain and cpdMain. 
  • Whenever we run ./gradlew clean build, internal check tasks will be triggered, and static analysis steps will be run for our project. If any code analysis step fails, our build will also fail.
  • Static code analysis reports will be under ./build/reports.
  • If, you want to “loose” the specified static code rules, suppress static analysis errors using @SuppressWarnings annotation. For example, to suppress warnings for having too many methods in a class, you can write @SuppressWargning("PMD.TooManyMethods") on a given class.

Pro-Tip:

You should keep static analysis “on” for the test classes and treat tests as an integrated part of the project. 

Summary

We briefly explained how you can set up the static code analysis for a Java project. We hope you got a good overview of it and can use it in your project.

Share this blog:

Profile picture for user naman
naman
Naman Saxena, an SEO executive, excels in optimizing digital presence and driving online growth, helping businesses enhance visibility and achieve marketing goals.