Tuesday, October 18, 2016

Integrating Jenkins With Sonar Qube

SonarQube (formerly Sonar) is an open source platform for continuous inspection of code quality. In this article we will see how we can integrate Sonar Qube in Jenkins. We will also build sample application which will use the integrated sonar Qube to test the code.

1. Sonar Qube Installation
a. Download the Sonar Qube with version 5.6.3
b. Unzip the sonar Qube
c. Go to <Sonar Qube>/bin/<OS-version>/
d. Run “sh sonar.sh console” command
e. Once the server is started, access the server from http://localhost:9000/ ( if you have a name to your system use that). This will be used in configuring the sonar qube servers in jenkins

2. Sonar Runner Installation
a. Download the Sonar-runner-2.4
b. Unzip the sonar runner
c. Don’t run the sonar-runner. This will be started from Jenkins.

Sonar Qube vs Sonar runner
SonarQube (formerly just "Sonar") is a server-based system. Of course you can install it on your local machine (the hardware requirements are minimal). But it is a central server with a database.
Analyses are performed by some Sonar "client" software, which could be the sonar runner, the sonar ant task, the sonar Eclipse plugin etc. The analysis results can be automatically uploaded to the server, where they can be accessed via the sonar Web application.

Once the Sonar Qube and Sonar runner are installed. We then need to install Sonar Plugin in the Jnekins

3. Download Jenkins Plugin
a. Download the Sonar Qube plugin 2.4.4 from Manage Jenkins => Manage Plugins

4. Configure the Jenkins – Sonar Qube Server
a. Configure System =>
    Under the Sonar Qube Server as,

Enter the Name.
Server URL – the one that we tried to access above when we started the Sonar qube

Note – Make sure to check the “Enable injection of sonarqube server configuration as build environment variables

5. Configure the Jenkins – Sonar Qube Scanner
 Under the Sonar Qube Scanner,

 Choose a new Sonar Qube Scanner Installation as,
Add the name and in the SONAR_RUNNER_HOME and pass the location of the unzip sonar-runner path above.

NOTE – also create a environment variable with SONAR_RUNNER_HOME variable with the location of the sonar-runner path

Save and Apply

6. Configure the Jenkins – Sonar Qube Project Properties file.
Every project that we want to check needs a sonar-project.properties file. The file can be a simple one by just passing the src location path. Here is a sample of the that I have

cat sonar-project.properties
# must be unique in a given SonarQube instance
# this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1.


# Encoding of the source code. Default is default system encoding

Save the file along with your source directory.
 7. Configure the Jenkins – Job
 Once the file is created, create a Job with the sonar qube as,
Check the “prepare SonarQube Scanner Environment”
In the Add pre-build Step , Choose the “Execute SonarQube Scanner”.
A new Item will be added and provide the path of the project’s “sonar-project.properties” file path as above.

Save and Run the Build. We can see the project Analysis at the sonar Qube Dashboard at http://localhost:9000/

That is all you need to do when configuring a Sonar Qube with Jenkins. More to Come. Happy Learning J
Read More

Monday, September 26, 2016

Nexus Rest API

Nexus is a collection of services available for us to automate. With the services available we can integrate them in the work flow that we need. Nexus also exposes the services as Rest services so that we can use them to automate things. In this article we will see how we can use the nexus rest api to automate things.

While nexus has a rich set of Rest end points for every thing from core actions like storing artifacts in the repository to creating users and repositories, but the documentation is little touch to find. Here are the steps you need to take to access this documentation:
  1. Login as an Administrator
  2. In the Administration section of the left-hand menu, click on Plugin Console to open the Plugin Console.
  3. Once in the Plugin Console you will see a list of Nexus Plugins. Click on a plugin to view the APIs it provides.
  4. Once you select a plugin, you should see a list of APIs. For example, the video below shows the Core API, click on the link in the Plugin Console to view the REST API documentation.

We will use the CURL command available in Linux to make the rest calls.  Nexus uses a single end point with changing services to communicate on the rest.

/nexus/service/local is the endpoint and by adding the service after this we can make a rest call to automate different things. Below are the few nexus services that we can use to communicate

nexus_status_service: status
nexus_users_service: users
nexus_repositories_service: repositories
nexus_roles_service: roles

Lets see a few examples on making use of the nexus rest API

Simple Get calls

Retrieve the status of the Nexus Server -
curl http://localhost:8081/nexus/service/local/status

Retrieve the available nexus repositories

Authenticated REST - GET requests  
User Details– In order to retrieve some details we need to send the credentials details. Curl Command also allows us to pass the credentials. In order to retrieve a user details the Rest call needs the credentials and this can be done as,

Delete Repositories
We can also pass other HTTP parameter like DELETE using the curl command and make a Rest call as,

curl -X DELETE -v -u admin:admin123 http://localhost:8081/nexus/service/local/repositories/my-releases-xml

Post Calls – The most important call will be the Post call since we will be using this to create things. Lets see on creating a repository using the CURL post call along with the XML payload

Create a XML file new_user.xml with user details as,

<?xml version="1.0" encoding="UTF-8"?>

In the above snippet we are creating a new user master. In order to make the call we can call the CURL command as,

curl -i -H "Accept: application/xml" -H "Content-Type: application/xml; charset=UTF-8"  -v -d "@new_user.xml" -u admin:admin123 http://puppet.jas.com:8081/nexus/service/local/users

In the above command we are using the users service to make the rest call and create a user by passing the xml payload that we created in the file. Once we ran the curl command we can see the output as below which includes the necessary return code details.

* About to connect() to puppet.jas.com port 8081 (#0)
*   Trying
* Connected to puppet.jas.com ( port 8081 (#0)
* Server auth using Basic with user 'admin'
> POST /nexus/service/local/users HTTP/1.1
> Authorization: Basic YWRtaW46YWRtaW4xMjM=
> User-Agent: curl/7.29.0
> Host: puppet.jas.com:8081
> Accept: application/xml
> Content-Type: application/xml; charset=UTF-8
> Content-Length: 424
* upload completely sent off: 424 out of 424 bytes
< HTTP/1.1 201 Created
HTTP/1.1 201 Created
< Date: Wed, 31 Aug 2016 08:27:23 GMT
Date: Wed, 31 Aug 2016 08:27:23 GMT
< X-Frame-Options: SAMEORIGIN
X-Frame-Options: SAMEORIGIN
< X-Content-Type-Options: nosniff
X-Content-Type-Options: nosniff
< Server: Nexus/2.13.0-01 Noelios-Restlet-Engine/1.1.6-SONATYPE-5348-V8
Server: Nexus/2.13.0-01 Noelios-Restlet-Engine/1.1.6-SONATYPE-5348-V8
< Content-Type: application/xml; charset=UTF-8
Content-Type: application/xml; charset=UTF-8
< Content-Length: 388
Content-Length: 388

* Connection #0 to host puppet.jas.com left intact

Besides passing the XML file as payload , nexus also accepts the JSON content as payload even and CURL command allows us to do so. Create a file repo.json with the repository details as,

[puppet@root$:/test]$  cat repo.json
    "data": {
        "repoType": "proxy",
        "id": "somerepo",
        "name": "Some Repo Name",
        "browseable": true,
        "indexable": true,
        "notFoundCacheTTL": 1440,
        "artifactMaxAge": -1,
        "metadataMaxAge": 1440,
        "itemMaxAge": 1440,
        "repoPolicy": "RELEASE",
        "provider": "maven2",
        "providerRole": "org.sonatype.nexus.proxy.repository.Repository",
        "downloadRemoteIndexes": true,
        "autoBlockActive": true,
        "fileTypeValidation": true,
        "exposed": true,
        "checksumPolicy": "WARN",
        "remoteStorage": {
            "remoteStorageUrl": "http://puppet.jas.com:8081/local",
            "authentication": null,
            "connectionSettings": null

Now we can run the CURL command as,

curl -H "Content-Type: application/json" -X POST -d @virtual.json -u admin:admin123 http://puppet.jas.com:8081/nexus/service/local/repositories

In the above command we have changed the content-type to json unlike xml.

That’s all about using the nexus Rest api and curl command.  Below are the few examples on using nexus Rest api

Get Single Repository Details
curl -k http://puppet.jas.com:8081/nexus/service/local/repositories/releases -u

Get Repository Status
curl -k http://puppet.jas.com:8081/nexus/service/local/repository_statuses -u admin:admin123

Getting a list of all users, now with authenticating as admin user
curl -X GET -u admin:admin123 http://localhost:8081/nexus/service/local/users

Retive the account Details
curl -k http://puppet.jas.com:8081/nexus/service/local/user_account/admin -u admin:admin123

Get the list of users available
curl -X GET -u admin:admin123

Get the list of repositories available

Hope this Helps.
Read More

Ansible Rest Calls

Rest API’s calls are now a days the main API to integrate with different applications. If you want to connect to an existing infrastructure we can expose the infrastructure as rest API and other applications can you the API to make calls.

Ansible also provides us a way to make the Rest calls using URI module. The URI module allows us to send XML or JSON payload and get the necessary details. In this article we will see how we can use the URI module and make the Rest calls. As for the article I will be using the Nexus artifactory to connect which run on the 8081 Port. The URL are specified in the vars/main.yml file.

Make a Get Call - Using the Ansible URI module to make get call is pretty easy. We can use

- name: Maker a Call
   url: "{{nexus_url}}/repositories"
   method: GET
   user: admin
   password: admin123
   force_basic_auth: yes
   return_content: yes

In the above snippet, I am making a Rest call to the “nexus_url/respositories” URL by passing them the user name and password along with the method as “Get” and the return_content.  We can use the Ansible debug to check the obtained response.

Make a Post call – Making a Post call needs a little extra details. Now for making a post call we need the JSON data. We can both create a file with JSON data and pass that to the file or we can include the JSON data at the same place. Lets create a JSON file first as

    "data": {
        "repoType": "proxy",
        "id": "somerepo1",
        "name": "Some Repo Name1",
        "browseable": true,
        "indexable": true,
        "notFoundCacheTTL": 1440,
        "artifactMaxAge": -1,
        "metadataMaxAge": 1440,
        "itemMaxAge": 1440,
        "repoPolicy": "RELEASE",
        "provider": "maven2",
        "providerRole": "org.sonatype.nexus.proxy.repository.Repository",
        "downloadRemoteIndexes": true,
        "autoBlockActive": true,
        "fileTypeValidation": true,
        "exposed": true,
        "checksumPolicy": "WARN",
        "remoteStorage": {
            "remoteStorageUrl": "http://puppet.jas.com:8081/local",
            "authentication": null,
            "connectionSettings": null

Save the file as proxy.json and move the file to the files location. Now we can use the proxy.json using the lookup in ansible as,

- name: Make a Proxy Repository
    url: "{{ nexus_url }}/repositories"
    method: POST
    body: "{{ lookup('file','proxy.json') }}"
    user: admin
    password: admin123
    force_basic_auth: yes
    body_format: json
    HEADER_Content-Type: application/json
    HEADER_Accept: application/json,version=2
    return_content: yes
    status_code: 201

IN the above snippet I passed the JSON file an argument to the  Ansible lookup. Besides this I passed the user name , password and most importantly the body_format , Header fields etc. We also need to pass the return code of the Rest call so that Ansible will compare the return status code with the status code that we defined. In the above example I passed the status code as 201. In this case the Ansible will check the rest call status code and passed status code to check if that is success or not. Even though the rest call is success if the status codes are not same Ansible will throw an error.

If we want to pass the JSON format in the body itself without using the file, we can use

- name: Make a Hosted Repository
    url: "{{nexus_url}}/{{ nexus_endpoint }}/{{ nexus_repositories_service }}"
    method: POST
    body: >
      data: {
        "repoType": "{{ hosted_repo_data.repoType }}",
        "id": "{{ repoId }}",
        "name": "{{ repoName }}",
        "provider": "{{ repoProvider}}",
        "browseable": {{ hosted_repo_data.browseable }},
        "repoPolicy": {{ hosted_repo_data.repoPolicy }},
        "providerRole": {{ hosted_repo_data.providerRole }}
    user: "{{ nexus_admin }}"
    password: "{{ nexus_admin_password }}"
    force_basic_auth: yes
    body_format: json
    HEADER_Content-Type: application/json
    HEADER_Accept: application/json,version=2
    return_content: yes
    status_code: 201

The body can be added directory to the Body method in the Ansible JSON call.

That’s all about Ansible URL module and rest calls. Hope this helps. 
Read More

Friday, August 26, 2016

Jenkins – SMTP setup

There is always a need for getting the Status of the nightly Build that we configure. Jenkins does provide a Email Notification option which allows us to configure Email Notifications that can be used to get the status of the Build. In this article we will see how we can configure the SMTP Configuration in Jenkins and get a mail for the Failed Build.

1. Configure the SMTP Setup
Configure System -> Email Notification ( Enter the Values accordingly )

SMTP Server – smtp.gmail.com (Click Advanced)
Check “Use SMTP Authentication”

User Name –Mail ID you want to Send mail from
Password – Enter the Password for the above configured Mail ID
SMTP Port – 587
Reply-To- Address – Same above mail
Charset – UTF-8

Check the Test Configuration by sending a test E-mail, it will send a test email.

Note – At this moment there may be case where we see some errors saying

a) Must Issue a STARTLS Command first.

For this Error, please add the startls command to the JAVA Command line that start Jenkins. For me the Jenkins file is located at “/etc/sysconfig/Jenkins”

Add the “-Dmail.smtp.starttls.enable='true'” to the existing JENKINS_JAVA_OPTSIONS variable as

JENKINS_JAVA_OPTIONS="-Djava.awt.headless=true -Dmail.smtp.starttls.enable='true'"

b) javax.mail.AuthenticationFailedException: 534-5.7.14 <https://accounts.google.com/signin/continue?sarp=1&scc=1&plt=AKgnsbu9

If the above error, comes login to you Gmail account that you want to send mail and browse the below link “https://www.google.com/settings/security/lesssecureapps“

Click the “Turn ON” Check box and error will go off.

This feature is disabled to block less secure apps from accessing Google Apps accounts

2) Once the SMTP configuration is success, we now need to configure email settings for the Build Job. Click the build job and in the Build Setting , check the Email Notification.

Enter the Recipients main in the Recipients Box and Check the “Send e-mail for every unstable build”

This will make sure that for every failed build a mail alert is sent to the people in the Recipients list.
That’s all you need to do for configuring the Mail alerts in Jenkins. More to Come. Happy Coding.
Read More

Jenkins Slave – Remote Host With SSH

In the previous article we have seen how we can configure a Jenkins slave on a remote machine. In this article we will see how we can configure Slave on the remote machine using SSH configuration.

1. On the Remote machine (Ex- create a SSH Key. Use the Same Jenkins User as we configured in the last article. Login as Jenkins and run the ssh key generation commands as,

[jenkins@devm ~]$ ssh-keygen -t rsa -C "this is access to Jenkins Slave"
Generating public/private rsa key pair.
Enter file in which to save the key (/home/jenkins/.ssh/id_rsa):
Created directory '/home/jenkins/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/jenkins/.ssh/id_rsa.
Your public key has been saved in /home/jenkins/.ssh/id_rsa.pub.
The key fingerprint is:
af:e3:74:ae:24:96:53:0a:c6:fd:43:29:e7:e6:47:f3 this is access to Jenkins Slave
The key's randomart image is:
+--[ RSA 2048]----+
|                 |
|                 |
|                 |
|   . .   .       |
|    + o S        |
|   . . X .o      |
|      * B.oo     |
|     . B.=. E    |
|       .=+.      |

Save the Keys in the default location. Once keys are created we can see the public and private keys in the /home/Jenkins/.ssh location. Copy the Public key ( id_rsa.pub ) to authorized_keys file.  

[jenkins@devm ~]$ cd /home/jenkins/
[jenkins@devm ~]$ cd .ssh/
[jenkins@devm .ssh]$ ll
total 8
-rw-------. 1 jenkins jenkins 1675 Aug 25 09:50 id_rsa
-rw-r--r--. 1 jenkins jenkins  413 Aug 25 09:50 id_rsa.pub
[jenkins@devm .ssh]$ cat id_rsa.pub >> authorized_keys
Make Sure the file permissions on the authorized_keys file is 0644.

2.  Once the key generation is done, we need to copy the private key to the Jenkins so that Jenkins can communicate with the host.

On the Jenkins Side -> Credentials -> System -> Global Credentials -> Add Credentials
ON the Right Hand ,
Select Kind -> “SSH Username and Private Key”
Scope -> Global
User name -> Jenkins
Private Key -> Enter Directly ( This will give you a text box at bottom , enter the Contents that are copied from id_rsa file in the remote machine that we created the keys for)

By this we have configured the SSH Private Key to the Credentials.

3. Create a Slave but Choose different options in the Launch method
Launch method -> Launch Slave agents on Unix machine via SSH. This gives you a Host and Credentials elements under this

Enter the Host Name (Ex-
Select the newly Created user name Jenkins that we created above from the Credentials List Box.

Once saved, the salve will be automatically stared. Make sure JAVA is configured and is available for the Jenkins to start or else we will see Java Not found exceptions

More To Come, Happy learning J
Read More

Jenkins Slave – Remote Host

As we already know that Jenkins besides acting as a continuous integration tool allows other configuration options including master – slave configuration. We already discussed master-slave configuration (Check Here for details). In this article we will see how we can configure Slave on a Remote Host using the Username and password.

1. Create a user name “Jenkins” on the remote machine with Password on the remote Machine (Ex-

[root@devm local]# adduser jenkins
[root@devm local]# passwd jenkins
Changing password for user jenkins.
New password:
BAD PASSWORD: The password is shorter than 8 characters
Retype new password:
passwd: all authentication tokens updated successfully.

2. Create a home directory for the Jenkins Slave

[root@devm local]# cd /home/jenkins/
[root@devm jenkins]# mkdir jenkins-slave

3. Create a New Node in the Jenkins Master server with the below configuration,
a. Enter the Name of the Slave “JenkinsSlave1”
b. In the Remote root Directory – (enter the location that we created in the remote machine) /home/Jenkins/Jenkins-salve
c. In the Launch Method – Launch slave agents on Unix Machine via SSH
This gives Host and Credentials boxes under this where we need to enter the Host name and Select the User name and password that are added in the global credentials

The credentials are same as the one that we created on the remote machine above. Once saved, the Slave will automatically gets started and we can see the slave running on the remote machine. Make sure JAVA is configured and is available for the Jenkins to start or else we will see Java Not found exceptions.

In the next article we will see how we can configure a Jenkins Slave on a remote Host using SSH keys

More to Come, happy learning J
Read More

Thursday, August 25, 2016

Sonar Integration with maven

In the next series of sonar, we will see how we can integrate sonar with maven and use maven command in analyzing the source code of a project and display the results on the sonarqube console.

1. Make sure JDK,Maven and Sonar are available ( with sonar running ).
2. Make the changes to the global maven setting.xml file available at location ~/.m2
3. Add the pluginGroups as,

4. Add the Profile pointing the location of the sonar console as,


4. Once the changes are done, Move to you java application and run,

[puppet@root$:/work/testing/javaee7-simple-sample]$ mvn clean verify sonar:sonar
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building javaee7-simple-sample 1.11-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] --- maven-war-plugin:2.3:war (default-war) @ javaee7-simple-sample ---
[INFO] Packaging webapp
[INFO] Assembling webapp [javaee7-simple-sample] in [/work/testing/javaee7-simple-sample/target/javaee7-simple-sample]
[INFO] Processing war project
[INFO] Copying webapp resources [/work/testing/javaee7-simple-sample/src/main/webapp]
[INFO] Webapp assembled in [63 msecs]
[INFO] Building war: /work/testing/javaee7-simple-sample/target/javaee7-simple-sample.war
[INFO] ------------------------------------------------------------------------
[INFO] Building javaee7-simple-sample 1.11-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] --- sonar-maven-plugin:3.0.2:sonar (default-cli) @ javaee7-simple-sample ---
 [INFO] User cache: /root/.sonar/cache
[INFO] SonarQube version: 4.5.7
[INFO] Default locale: "en_US", source code encoding: "UTF-8"
[INFO] [02:21:17.060] Load global referentials...
[INFO] [02:21:17.393] Load global referentials done: 334 ms
[INFO] [02:21:17.411] User cache: /root/.sonar/cache
[INFO] [02:21:17.420] Install plugins
[INFO] [02:21:17.739] Install JDBC driver
[INFO] [02:21:17.743] Create JDBC datasource for jdbc:h2:tcp://localhost/sonar
[INFO] [02:21:18.596] Initializing Hibernate
[INFO] [02:21:19.930] Load project referentials...
[INFO] [02:21:20.315] Load project referentials done: 385 ms
[INFO] [02:21:20.315] Load project settings
[INFO] [02:21:21.131] Loading technical debt model...
[INFO] [02:21:21.151] Loading technical debt model done: 20 ms
[INFO] [02:21:21.153] Apply project exclusions
[INFO] [02:21:21.395] -------------  Scan javaee7-simple-sample
[INFO] [02:21:21.398] Load module settings
[INFO] [02:21:21.720] Loading rules...
[INFO] [02:21:22.089] Loading rules done: 369 ms
[INFO] [02:21:22.113] Configure Maven plugins
[INFO] [02:21:22.170] No quality gate is configured.
[INFO] [02:21:22.329] Initializer FindbugsMavenInitializer...
[INFO] [02:21:22.330] Initializer FindbugsMavenInitializer done: 1 ms
[INFO] [02:21:22.330] Base dir: /work/testing/javaee7-simple-sample
[INFO] [02:21:22.330] Working dir: /work/testing/javaee7-simple-sample/target/sonar
[INFO] [02:21:22.330] Source paths: src/main/webapp, pom.xml, src/main/java
[INFO] [02:21:22.330] Binary dirs: target/classes
[INFO] [02:21:22.331] Source encoding: UTF-8, default locale: en_US
[INFO] [02:21:22.331] Index files
[INFO] [02:21:22.363] 4 files indexed
[INFO] [02:21:22.414] Quality profile for java: Sonar way
[INFO] [02:21:22.427] Sensor JavaSquidSensor...
[INFO] [02:21:22.600] Java Main Files AST scan...
[INFO] [02:21:22.603] 4 source files to be analyzed
[INFO] [02:21:22.765] 4/4 source files analyzed
[INFO] [02:21:22.767] Java Main Files AST scan done: 167 ms
[INFO] [02:21:22.768] Java bytecode scan...
[INFO] [02:21:22.790] Java bytecode scan done: 22 ms
[INFO] [02:21:22.790] Java Test Files AST scan...
[INFO] [02:21:22.790] 0 source files to be analyzed
[INFO] [02:21:22.791] Java Test Files AST scan done: 1 ms
[INFO] [02:21:22.791] 0/0 source files analyzed
[INFO] [02:21:22.795] Package design analysis...
[INFO] [02:21:22.799] Package design analysis done: 4 ms
[INFO] [02:21:22.822] Sensor JavaSquidSensor done: 395 ms
[INFO] [02:21:22.822] Sensor QProfileSensor...
[INFO] [02:21:22.826] Sensor QProfileSensor done: 4 ms
[INFO] [02:21:22.826] Sensor InitialOpenIssuesSensor...
[INFO] [02:21:22.863] Sensor InitialOpenIssuesSensor done: 37 ms
[INFO] [02:21:22.863] Sensor ProjectLinksSensor...
[INFO] [02:21:22.866] Sensor ProjectLinksSensor done: 3 ms
[INFO] [02:21:22.867] Sensor VersionEventsSensor...
[INFO] [02:21:22.872] Sensor VersionEventsSensor done: 4 ms
[INFO] [02:21:22.872] Sensor FileHashSensor...
[INFO] [02:21:22.873] Sensor FileHashSensor done: 1 ms
[INFO] [02:21:22.873] Sensor SurefireSensor...
[INFO] [02:21:22.874] parsing /work/testing/javaee7-simple-sample/target/surefire-reports
[WARN] [02:21:22.874] Reports path not found: /work/testing/javaee7-simple-sample/target/surefire-reports
[INFO] [02:21:22.874] Sensor SurefireSensor done: 1 ms
[INFO] [02:21:22.874] Sensor Maven dependencies...
[INFO] [02:21:22.897] Sensor Maven dependencies done: 23 ms
[INFO] [02:21:22.897] Sensor CPD Sensor (wrapped)...
[INFO] [02:21:22.897] JavaCpdEngine is used for java
[INFO] [02:21:22.898] Cross-project analysis disabled
[INFO] [02:21:22.917] Sensor CPD Sensor (wrapped) done: 20 ms
[INFO] [02:21:23.018] Execute decorators...
[INFO] [02:21:23.121] Store results in database
[INFO] [02:21:23.208] ANALYSIS SUCCESSFUL, you can browse http://puppet.jas.com:9000/dashboard/index/org.javaee7.sample:javaee7-simple-sample
[INFO] [02:21:23.255] Executing post-job class org.sonar.plugins.core.issue.notification.SendIssueNotificationsPostJob
[INFO] [02:21:23.255] Executing post-job class org.sonar.plugins.core.batch.IndexProjectPostJob
[INFO] [02:21:23.272] Executing post-job class org.sonar.plugins.dbcleaner.ProjectPurgePostJob
[INFO] [02:21:23.283] -> Keep one snapshot per day between 2016-07-27 and 2016-08-23
[INFO] [02:21:23.284] -> Keep one snapshot per week between 2015-08-26 and 2016-07-27
[INFO] [02:21:23.284] -> Keep one snapshot per month between 2011-08-31 and 2015-08-26
[INFO] [02:21:23.284] -> Delete data prior to: 2011-08-31
[INFO] [02:21:23.288] -> Clean javaee7-simple-sample [id=1]
[INFO] ------------------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 38.600 s
[INFO] Finished at: 2016-08-24T02:21:23-04:00
[INFO] Final Memory: 30M/319M
[INFO] ------------------------------------------------------------------------

Once the Build is success we can see the results in the console as,

More to Come, Happy learning J
Read More