BenZhang' Home

My coding Journal

Setup Jenkins for Rails CI on Ubuntu

Continuous integration aims to improve the quality of our softwares. The theory behind the theme is quite simple, to make sure the software will work, we have to make every build tested. From the technical point of view, it is basically a global hook that will be triggered when a push was made to our repository. As for static languages, such as Java, C, C++, languages needs to be compiled, CI comes with more steps cause we have to build the source code before we run the tests. The term continuous integration is pretty funcy when we are using static languages. In addition, We need to compile and build the source code and run the test across the whole project. That can be extremely complicated for a big project. However, as for the dynamic languages like Ruby, Python, CI can be very trivial. Since Rails comes with a great testing framework, there is not much we need to do for the CI but trigger the test command. This is an article provides some guidelines to setup a CI server using Jenkins on Ubuntu.

Install Jenkins server

First of all, run the following commands to install Jenkins.

1
2
3
4
wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'
sudo aptitude update
sudo aptitude install jenkins

Once the installing is finished, your server is up. Go to http://localhost:8080. You should be able to see the welcome page.

Jenkins Plugins

Jenkins comes with a lot of plugins. Go to Jenkins > Manage Jenkins > Manage Plugins. For our case, we need to have Github Plugin installed. Once it is done. You can create a new task. Put your ssh repository url into GitHub project and Source Code Management. You can make the task runs automatically whenever a push is made by choosing Build when a change is pushed to GitHub. You need to go to your github and set the Service Hooks / Post-Receive URLs to your url of CI server, http://your-url/github-webhook.

Configure the build

One thing we need to explain is that the jenkins service is running under the user jenkins in your system. Therefore in order to run your tests, you need to have the Rails environment setup for user jenkins. First of all, generate ssh key for jenkins user

1
2
3
4
# login as jenkins
sudo su - jenkins
# generate ssh key
ssh-keygen -t rsa

If you are using RVM in your server you will have to do the configuration for jenkins user or you have the RVM enabled for all the users in your server. Remember to set the jenkins user to trust .rvmrc file by going to /var/lib/jenkins/.rvmrc, and append this line

1
export rvm_trust_rvmrcs_flag=1

And create file /var/lib/jenkins/.bashrc with the following content

1
[ -s "/var/lib/jenkins/.rvm/scripts/rvm" ] && source "/var/lib/jenkins/.rvm/scripts/rvm"

You are almost done here. The last step is create a Jenkins task fill up your repository url and go to Jenkins build session select Execute shell, and add the following command.

1
2
3
4
5
6
7
#!/bin/bash -x
source ~/.bashrc
cd .
bundle install
mv database.yml.example database.yml
bundle exec rake db:test:load RAILS_ENV=test
bundle exec rake RAILS_ENV=test

Now your Rails CI server should be up and running.

Security problem

Jenkins does not come with the security default setting. I guess no one would like to share their CI server with the world. To enable the security is fairly easy. Go to Manage Jenkins > Configure System > Access Control. You can select the suitable solution for your own need.

Deploying a Rails Application on Ubuntu 12.04

First thing first, make you server up to date.

1
2
sudo apt-get update
sudo apt-get upgrade

Install git

1
apt-get -y install curl git-core python-software-properties

Email service

1
apt-get -y install telnet postfix

MySQL

1
sudo apt-get install mysql-server libmysqlclient15-dev

Install RVM

1
2
curl -L https://get.rvm.io | bash -s stable
source /home/your name/.rvm/rvm.sh

Once it is finished, you can run this command to install the required libs

1
rvm requirements

Install required libs Ruby needed.

1
sudo apt-get install build-essential openssl libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev automake libtool bison subversion

Then install Ruby

1
2
rvmsudo rvm install ruby
rvm use --default 1.9.3

Install Passenger and Nginx. Note that if you want to use passenger do not install Nginx first, cause the passenger module has to be compiled into Nginx.

1
2
gem install passenger --no-ri --no-rdoc
rvmsudo passenger-install-ngnix-module

When you finish that. If you use default setting, go to /opt/nginx/nginx.conf, and add the Ruby and your project config according to the instruction. Install and add nginx to system service

1
2
3
4
5
cd /etc/init.d
sudo wget https://raw.github.com/chloerei/nginx-init-ubuntu-passenger/master/nginx
sudo update-rc.d nginx defaults
sudo chmod +x nginx
sudo service nginx start

Git Checkout

Git is a veryd powerfully version control tool. Here is a summary how to make use of git checkout.

Switch branch

When we type

1
git branch

in a git repo, we will get result like this

1
2
* master
  develop

If we want to switch to develop, we can simple checkout it.

1
git checkout develop

Switch commit

When we check the git log, it will list commits we have made so far. For example

1
2
3
4
5
commit 20f9981e35eee840207bfcab423a8056e648ae3f
Author: Ben Zhang <bzbnhang@gmail.com>
Date:   Thu Aug 9 12:34:41 2012 +0930

    add new feature #436

We can refer to this commit using the hash code, in addition partial of hash code, such as 20f99. Therefore we can checkout whatever commit we like using hash code.

1
2
3
4
git checkout 20f99

* (no branch)
  master

When we checkout a commit, we are actually not in any branch.

Checkout tag

We can give name to our commits by using git’s tag feature. We can set a tag to the current commit by using

1
git tag -a tag_name

It would be so handy if we want to go to a specific tag without checking the history. We can simply checkout this commit by using the tag name

1
git checkout tag_name

Checkout partial files

What if we want to checkout partial files from other branches or commits? Cherry-pick would be an common option, but we can make use the checkout command. Suppose we are in master branch, and we want to bring the index.html file from develop branch. We can do this

1
git checkout develop index.html

Typing in git branch, we will find out we are still in master branch, but index.html has been updated.

Summary

Git checkout is very handy. Feel free to shoot me an Email if you know any other cool features.