Continuous Integration in Pipeline as Code Environment with Jenkins, JaCoCo, Nexus and SonarQube

Github Link for the source code: https://github.com/vishwakarmarhl/jenkinstest

Here we discuss the setup for a Continuous integration pipeline. This is for mavenized Spring boot build with JaCoCo coverage reports and Sonar metrics. I used a windows machine with Tomcat 8 for hosting jenkins, but similar setup can be done on any OS where Sonar server can run on the same system.

A. Get the following artifacts on the system

  1. Tomcat server with Java JDK – Configure the server.xml to run on port 8099
  2. Setup Maven & other build utilities on your machine
  3. Access to Github source code
  4. Source code should have the Jenkinsfile in project root to be used by the pipeline
  5. Source should have the sonar-project.properties in project root for the SonarQube project linkage & source paths

JenkinsFile

Jenkinsfile and sonar-project.properties snapshot

B. Setup & Startup SonarQube

  1. Download the SonarQube package from https://www.sonarqube.org/#downloads
  2. Start sonar server: SONAR_HOME\bin\windows-x86-32\StartSonar.bat (for 32 bit Windows)
  3. Open Sonar admin page “http://localhost:9000“. Default credentials – admin/admin
  4. Create user in security tab and generate an access token, 50997f4a8c26d5698cccee30cf398c0ed9b98de0
  5. Create a project SPRINGBOOT with a key
  6. Download SonarQube scanner from https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner
  7. Additional configuration from https://docs.sonarqube.org/display/SCAN/Advanced+SonarQube+Scanner+Usages

C. Setup & Startup Tomcat

  1. Download jenkins.war from https://jenkins.io/download
  2. Put the jenkins.war file in webapps folder of Tomcat home
  3. Set Environment Variables as follows,
  4. SET JENKINS_HOME=”C:/Users/vishwaka/Documents/Workspace/git/jenkinstest/cisetup/jenkins_home”
  5. SET CATALINA_OPTS=”-DJENKINS_HOME=C:/Users/vishwaka/Documents/Workspace/git/jenkinstest/cisetup/jenkins_home”
  6. Start the server using startup.bat

JenkinsHome

Initial launch of Jenkins

D. Initialize Jenkins

  1. Access Jenkins at http://localhost:8099/jenkins
  2. Provide the initial credentials from jenkins_home/secrets/initialPassword*
  3. Install the default set of plugins and proceed
  4. Create a user for this installation
  5. Use “New Item” for creating a pipeline and provide the Jenkinsfile pipeline script from Git SCM for this

JenkinsCreatePipeline

Create pipeline project

E. Plugin & Configuration to Jenkins

  1. Add the “JaCoCo plugin” through the Manage Jenkins > Manage Plugins and install without restart
  2. Add “SonarQube Scanner for Jenkins” through the same Plugin Manager as above
  3. Go to the Manage Jenkins > Configure system and provide the credentials for Sonar Server
  4. Add the “SonarQube Server” name running on URL http://localhost:9000 alongwith user authentication key generated in SonarQube Server user administration page
  5. Remove the auto install option and add the “Sonar Scanner” env variable SONAR_RUNNER_HOME installation path as $JENKINS_HOME/sonar-scanner-3.0.3.778-windows through “Global Tool Configuration”
  6. Make sure the Sonar scanner path is configured properly as its path is hard coded in Jenkinsfile.

JenkinsGlobalProperties

Global Tool Configuration

F. Run the Build now for this pipeline

  1. The pipeline is at http://localhost:8099/jenkins/job/JENKINS-BOOT/JenkinsStatusPipeline
  2. Checkout the coverage report within the pipeline reports JenkinsJacoco
  3. You can also look at the Sonar reports at http://localhost:9000/dashboard?id=JENKINSBOOT JenkinsToSonar
  4. If you have many such projects then its better to execute all your Job Pipelines from a parent Job Pipeline. You can create one and call it “BUILD-ALL-JOBS”. It can be configured using the below pipeline script to run your JENKINS-BOOT job described in the example above as well as any other fictitious job call JENKINS-BOOT-XXX.
node {
    stage('JENKINS-BOOT-STAGE-A') {
        build job: 'JENKINS-BOOT'
    }
    stage('JENKINS-BOOT-STAGE-B') {
        build job: 'JENKINS-BOOT-XXX'
    }
}

There are plugins to build jobs in parallel as well but that depends on what workflow you want to build in your system.

G. Adding Nexus repository management capability to your CI environment from my blog

Click on the text link below:

Repository Management with Nexus 3 for your Mavenized project, including release and snapshot distribution

H. Finally put everything into a script that can run it all

Pardon my naive & careless script, considering my setup is on a local windows development workstation.

@echo off
echo "--------------------------------------------------------------------------"
echo "------------------------- CI STARTUP SCRIPT ------------------------------"
echo "--------------------------------------------------------------------------"

echo "Startup SonarQube Server"
echo "------------------------"
START CMD /C "cd c:\Dock\ci\sonar\sonarqube-6.4\bin\windows-x86-64 & CALL StartSonar.bat"
echo "Sonar may be up on http://localhost:9000/"

echo "Startup Nexus Repository Manager"
echo "--------------------------------"
START CMD /C "cd c:\Dock\ci\nexus\nexus-3.3.1-01\bin & nexus.exe /run"
echo "Nexus may be up on http://localhost:8081/"

echo "Startup Jenkins on Tomcat"
echo "-------------------------"
START CMD /C "cd c:\Dock\ci\jenkins\apache-tomcat-8.5.15\bin & startup.bat"
echo "Jenkins may be up on http://localhost:8099/jenkins"

echo "-------------------------------- END -------------------------------------"

 

Thanks.

 

Show off your spring web services through swagger, Just like that…

A backend blackhole services developer can become a shooting star with swagger.  This is like a new super power that can take you to a whole new level. I have been trying to get deeper into it. I think i can discuss some basic stuff to kick start you on this.

Nirvana hits when you realize that you can even try out your web services right through this user interface.Holiness all the way.

Swagger: http://swagger.wordnik.com/

Based on the beautiful and easy to strap spring-mvc work from MartyPitt:

https://github.com/martypitt/swagger-springmvc-example

Step 1: Maven dependencies

<!-- Swagger for API Documentation -->
 <dependency>
 <groupId>org.projectlombok</groupId>
 <artifactId>lombok</artifactId>
 <version>0.10.8</version>
 <scope>provided</scope>
 </dependency>
 <dependency>
 <groupId>com.mangofactory</groupId>
 <artifactId>swagger-springmvc</artifactId>
 <version>0.6.6</version>
 </dependency>
 <dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-databind</artifactId>
 <version>2.1.1</version>
 </dependency>
 <dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-annotations</artifactId>
 <version>2.1.1</version>
 </dependency>
 <dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-core</artifactId>
 <version>2.1.1</version>
 </dependency>
 <dependency>
 <groupId>joda-time</groupId>
 <artifactId>joda-time</artifactId>
 <version>2.1</version>
 </dependency>
 <dependency>
 <groupId>org.springframework.hateoas</groupId>
 <artifactId>spring-hateoas</artifactId>
 <version>0.3.0.RELEASE</version>
 </dependency>
 </dependencies>

2. Include a swagger.properties file in your resources folder

documentation.services.basePath=http://localhost:8080/myspringwebapp 
documentation.services.version=1.0

3. Add the configuration for the swagger to discover all the a=spring based annotations and create the api docs service

<context:component-scan base-package="com.myspringwebapp.generic" />
 <mvc:annotation-driven/>
 <context:annotation-config/>
<bean id="propertyPlaceholderConfigurer"
 class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
 <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
 <property name="locations">
 <list>
 <value>classpath:swagger.properties</value>
 </list>
 </property>
 </bean>
<mvc:default-servlet-handler/>
<!-- To enable @RequestMapping process on type level and method level -->
 <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
 
 <!-- creates a controller at /api-docs from this uri, which serves swagger's raw documentation in JSON format. -->
 <bean id="documentationConfig" class="com.mangofactory.swagger.configuration.DocumentationConfig"></bean>


4. Add the swagger-ui dependencies and the relevant css, js, and html pages. I had to update the swagger-ui javascript but am sure the one shared by martypitt also works as i tried it too.

https://github.com/martypitt/swagger-springmvc-example/tree/master/src/main/webapp

5. Voila, just run this application in the container you are in love with

Test it out locally
http://localhost:8080/myspringwebapp/api-docs
The above url should return a list of controllers available in your spring mvc project
Doc UI: 
http://localhost:8080/myspringwebapp/index.html
The html has all that it takes to read the api and beautify it, such that you can read, play and do everything you could with it.

Swagger was smooth and as a project it was amazing to use and showcase the beautiful API doc to stakeholders. If you are just curious then take a peek at the beauty in the attached screen shot of a GET and a POST interface on my REST user spring controllers.

A beautiful proof of the working api doc

A beautiful proof of the working api doc