Thursday, September 17, 2015

Jenkins + Gitlab + CI

Continuous Integration (CI) is a development practice that requires developers to integrate code into a shared repository several times a day. Each check-in is then verified by an automated build, allowing teams to detect problems early. Jenkins CI is the leading open-source continuous integration server. Hence, we'll deploy Jenkins on our CentOS Server and associate it with the Gitlab repository, so that every time we commit our project via git command, it will be built and deployed automatically by Jenkins.


Install Jenkins On CentOS

Firstly, add Jenkins repository to yum:
$ sudo wget -O /etc/yum.repos.d/jenkins.repo http://jenkins-ci.org/redhat/jenkins.repo
$ sudo rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key

Then, install Jenkins with one-line-command:
$ sudo yum install jenkins

After installation, there're some paths that we need to know:
/usr/lib/jenkins/, the place where jenkins.war resides in;
/etc/sysconfig/jenkins, the configuration file for Jenkins, in which we should modify JENKINS_USER to 'root' in our scenario. Remember to change all the related files and directories to JENKINS_USER correspondingly. And you'll notice that the default port for Jenkins service is 8080, change it if needed.
/var/lib/jenkins, Jenkins home;
/var/log/jenkins/jenkins.log, Jenkins log file.

Finally, we could start Jenkins via command:
$ sudo service jenkins start

The webpage of Jenkins should look like below if everything goes well:


Integrate Jenkins with Gitlab for CI

As for integrating Jenkins with gitlab, there's an official and detailed tutorial [REFERENCE_2] that we could follow. I just wanna take notes on some possible scenarios we may face during the procedure.

Firstly, we need to install GitLab Hook plugin as guided. there's a quick-and-dirty way by install it automatically [Jenkins webpage -> Manage Jenkins -> Manage Plugins], but it might be helpful to install it manually [REFERENCE_3], should any problem occur in that manner. Remember to watch on Jenkins log while restarting Jenkins after installing the plugin we need, in case there are some exceptions complaining.

Then we choose 'Jenkins webpage -> Manage Jenkins -> Configure System' to do the global configuration stuff, where we need to configure Maven, Git and Gitlab module, as depicted below:



Next, we choose 'New Item', and then configure for our project in Jenkins. In the 'Source Code Management' module, we need to set as follows.

The build procedures are threefold, namely, Pre Steps, Build and Post Steps. It is essentially quite self-explained, thus 'talk is cheap and just show the code':



There's a problem, though, concerning executing shell commands in Pre Steps or Post Steps. If the command spawns a subprocess to do its job, it may die after Pre Steps or Post Steps end. So this is a tricky part we need to know about, and the solution is stated in both REFERENCE_4 and REFERENCE_5 with keyword 'BUILD_ID'.

Eventually, we navigate to GitLab services page and activate Jenkins according to REFERENCE_2.


In this time, it will be automatically built and deployed as expected after we commit the changes from local to Gitlab.

But the above manner of configuration has a problem, that when we intend to associate the same Gitlab project to two or more Jenkins services, say, develop environment and production environment, then it fails because only one Jenkins CI could be set in one Gitlab's project.

According to REFERENCE_8, we could notify our Jenkins server via a Restful API provided by Jenkins. Let's configure our project in Jenkins first, or error 'No git jobs using repository:...' may complain [REFERENCE_9]. Go to the Dashboard, click on your project, click Configure, under 'Build Triggers' check the box for 'Poll SCM'. Then select our project in Gitlab, Settings -> Web Hooks, input the Restful API 'http://test.hide.com:8080/git/notifyCommit?url=git@gitlab.com:username/project-name.git' and save. Here, we could add web hooks no matter how many we want.



Security Configuration for Jenkins

Since everyone can access Jenkins if he knows the URL, it needs to be protected via security configuration provided by Jenkins itself. Here's the portal:

REFERENCE_6 is a great tutorial for the above configuring process.



REFERENCE:
1. CentOS 上 Jenkins 安装
2. Gitlab Documentation - Jenkins CI integration
3. How to install a plugin in Jenkins Manually
4. Starting integration tomcat via Jenkins shell script execution
5. Jenkins Doc - ProcessTreeKiller
6. Secure Jenkins with login/password
7. turn Jenkins security off by code
8. Push notification from repository - Git Plugins - Jenkins Doc
9. Jenkins job notification fails with “No git consumers for URI …”