Monday, 17 July 2017

Jenkins, Bitbucket and Static Analysis

Static Analysis

So you are running static analysis on your builds, great. However who actually views this after the first few weeks? We get all excited about driving home the gains of automatic potential bug finding but who really goes and fixes all the issues, cannot say I've seen many sprints with a ticket to fix a particular issue across the whole code base. But there is a better way of presenting this data, why not put those comments on a code review in Bitbucket and have them reviewed along with the code. This way in with the review you can get feedback on what your static analysis says about your code. I think this is by far the best place to have a snapshot of the information, but still have the full info on Jenkins or CI, so you can see the trends over time. This builds on the workflow that we have already in Jenkins and Bitbucket back in Jenkins pipeline + Bitbucket pull request, so if you haven't done that part yet please go back as we are building on that process.

 Process Requirements:

1.     User creates a pull request for his branch.
2.     Jenkins builds the pull request merged with the target branch.
3.     Static Analysis is done on the code during the Jenkins job.
4.     Comments on the pull request are reported back to Bitbucket.

This is the basic requirements that we will satisfy as normal we had some dependencies.

System requirements

Jenkins:

Jenkins (2.19.1)
Violation Comments to Bitbucket Server Plugin (1.51)

Starting in Jenkins 2.0 there are some security changes for parameters given via a URL and these parameters need to be whitelisted before Jenkins runs.

Special startup parameters:
To Whitelist the parameters you will need to add the parameters to the end of this system property.
“-Dhudson.plugins.git.GitStatus.safeParameters= PULL_REQUEST_TO_REPO_PROJECT_KEY
PULL_REQUEST_TO_REPO_SLUG”

For windows this can be done using the Jenkins.xml in the Jenkins home DIR. These need to be added before the -jar term as parameters after this are ignored.
Ubuntu:
File: /etc/default/Jenkins
Property: JAVA_ARGS
RedHat:
File: /etc/sysconfig/Jenkins
Property: JENKINS_JAVA_OPTIONS


General Jenkins Configuration


In the manage Jenkins GUI you can add to the default
Bitbucket Server Violations Server Defaults
    Username/password :  username and password to use for bitbucket
    Base URL: url of bitbucket in your organisation


Job Specific configuration


Add the following parameters to the build:

PULL_REQUEST_TO_REPO_PROJECT_KEY
PULL_REQUEST_TO_REPO_SLUG

For an example we can use pylint on python code in windows using this windows batch script:
mkdir pylint
for /R %%i in (*.py) do pylint -rn -f parseable "%%i" >> pylint\\pylint.log

In the post-build actions set the following:
Report violations to Bitbucket Server:

Project key: ${PULL_REQUEST_TO_REPO_PROJECT_KEY}
Repo_slug: ${PULL_REQUEST_TO_REPO_SLUG}
Pull Request ID: ${PULL_REQUEST_ID}

I set to comment one per violation as it's a little easier to see the comments on the line.
The file search for violations searches the absolute path, it's not relative to the workspace:
.*/*pylint\.log$

Now the way the plugin works is that the violations are uploaded from the node using the account in the job, I would use a service account for this, so it's easy to see that it has come from Jenkins. If you are using self-signed certificates, you will need to add the certificate to the Java keystore which the agent is using to connect.

Obtain the certificates that you need.
Use the keytool.exe in JAVA_HOME\bin\keytool.exe
Then use the keytool with commands similar to the following

"keytool -import -alias server_name -file cert.cer -keystore JAVA_HOME\lib\security\cacerts -storepass changeit -noprompt"


BitBucket Configuration


Building on the Jenkins git commit notify that we already have from Jenkins pull request building, we have a full build trigger of:

 (Jenkins_url)/git/notifyCommit?url=${PULL_REQUEST_TO_SSH_CLONE_URL}&branches=pr&sha1=${PULL_REQUEST_FROM_HASH}&PULL_REQUEST_URL=${PULL_REQUEST_URL}&PULL_REQUEST_ID=${PULL_REQUEST_ID}&PULL_REQUEST_TO_BRANCH=${PULL_REQUEST_TO_BRANCH}&PULL_REQUEST_TO_REPO_PROJECT_KEY=${PULL_REQUEST_TO_REPO_PROJECT_KEY}

I have only done this for a FreeStyle Job so far but there is a good example on the plugin page