Jenkins CI setup for Rails application from scratch by makaroni4
CI (Continuous Integration) was originally intended to be used in combination with automated unit tests written through the practices of Test driven development. Initially this was conceived of as running all unit tests and verifying they all passed before committing to the mainline.

After reading this post you will know everything to install and configure Jenkins CI for building Rails application i.e. running all tests and sending notifications if build was failed.
First lets check that we have the same environment:
uname -a
# Linux staff-vm 3.2.0-29-generic #46-Ubuntu SMP Fri Jul 27 17:03:23 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
Just a reminder: NEVER install Jenkins on your production server and here is why:

It is NewRelic graph which shows us that there is huge impact on the database which enlarge response time significantly.
RVM and Ruby
OK, lets check if we have ruby or mysql installed. You should get the same output:
rvm -v
# => -bash: rvm: command not found
ruby -v
# => -bash: ruby: command not found
mysql --version
# => -bash: mysql: command not found
For rvm installation we need to have git core and curl, install them like this:
sudo apt-get install build-essential git-core
sudo apt-get install curl
Now we can install rvm with ruby:
curl -L https://get.rvm.io | bash -s stable --ruby
and if you don't need the latest version of ruby don't forget to install one (1.8.7 for example):
rvm install ruby-1.8.7
Mysql
To install mysql just run in your terminal:
sudo apt-get install mysql-client mysql-server libmysql-ruby libmysqlclient-dev
Postgres
sudo aptitude install libpq-dev
If you had a problem with UTF-8 take a look at http://wiki.gentoo.org/wiki/PostgreSQL
Jenkins
So lets install Jenkins, original manual could be found here:
https://wiki.jenkins-ci.org/display/JENKINS/Installing+Jenkins+on+Ubuntu
To follow that manual we need to install aptitude:
sudo apt-get install aptitude
For now we will need just this block of commands:
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
Lets start jenkins like this (or through service command):
sudo /etc/init.d/jenkins start
If you need port different from 8080 you can edit jenkins HTTP_PORT config param:
sudo vi /etc/default/jenkins
Nginx config
If you also need to config nginx try to find it with (on my machine config was lost in the folders so this is why I pay attention to that):
sudo find / -name nginx
So now we need to configure nginx and not only for proxying but to hide jenkins web interface. When I first installed Jenkins there was a bug – if you enable jenkins authorization you can't build project via url hook (get request with token as param). So the solution was simply to hide jenkins with http-auth and to enable hooks to specific locations like this:
upstream jenkins {
server 127.0.0.1:8080;
}
server {
listen 111.111.111.111:80;
server_name ci.our_project.com *.ci.our_project.com;
try_files $uri @jenkins;
location @jenkins {
proxy_pass http://jenkins;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
auth_basic "Restricted";
auth_basic_user_file /path/to/htpasswd.jenkins;
}
location ~ /job/\w+/build {
root /var/cache/.jenkins/war;
try_files $uri @jenkins;
}
location / {
root /var/cache/jenkins/war/;
# Optional configuration to detect and redirect iPhones
if ($http_user_agent ~* '(iPhone|iPod)') {
rewrite ^/$ /view/iphone/ redirect;
}
auth_basic "Restricted";
auth_basic_user_file /path/to/htpasswd.jenkins;
try_files $uri @jenkins;
}
}
OKay, so by this moment we should have jenkins web interface working and available at ci.our_project.com:

Jenkins user
Now we need to configure Jenkins for fetching data from git repo and run tests. So since Jenkins has its own user lets generate ssh pair for it:
sudo su jenkins
ssh-keygen -t rsa
To trigger builds remotely you should enable security (in Manage Jenkins -> Configure system). Just set matrix based authorization and anonymous is Administrator.
Now check you bash config, for me it looks like this by now:
cat /var/lib/jenkins/.bashrc
PATH=$PATH:/home/your_project/.rvm/bin # Add RVM to PATH for scripting
if [[ -s "$HOME/.rvm/scripts/rvm" ]]; then . "$HOME/.rvm/scripts/rvm"; fi
Git repo
OK, so now we are ready to create Jenkins job for our project. New Job -> Free-style project. If you use Git be sure to install some plugins: Manage Jenkins -> Manage Plugins and install Git plugin, Github plugin to enable fetching data and configuring Github url hook for Jenkins.
After creating a job navigate to its configuration, choose Source Code Management as Git and enter your Repository URL:
After installing Git plugin you can specify path to you repo:

URL hook
For triggering build we will use URL hook, for this you need to specify build token for you trigger in Build triggers section:

Build section, we are almost done. For our case choose Execute shell option so textarea for shell commands will appear. I have config like this:
Configure build
#!/bin/bash -x
sudo su jenkins
source /var/lib/jenkins/.bashrc
rvm use 1.9.3
bundle install
read -d '' database_yml <<"EOF"
login: &login
adapter: mysql2
username: "root"
password: "password"
encoding: utf8
test: &test
database: my_project_test
<<: *login
EOF
echo "$database_yml" > config/database.yml
rake db:test:prepare RAILS_ENV=test
rake ci:setup:rspec spec RAILS_ENV=test
CI reporter
You may notice that we don't use rspec spec in the last command. This is because of Jenkins doesn't understand rspec console output. For Jenkins to understand it we need to use ci_reporter gem which generate xml output for our tests: https://github.com/nicksieger/ci_reporter
group :test do
gem 'ci_reporter'
end
Bundle issues
On each build we will run bundle so be sure to install all necessary libraries for you project. For me it was smth like this:
sudo apt-get install libxslt-dev libxml2-dev
sudo apt-get install libmagickwand-dev
<http://nokogiri.org/tutorials/installing_nokogiri.html>
sudo aptitude install memcached
sudo apt-get install sphinxsearch
Jenkins folder rights
But even if you forget to install smth Jenkins will fail build and notify you.
Your app will be downloaded to /var/lib/jenkins/jobs/YOUR_PROJECT/workspace
If your app create some file (uploads testing for example) don't forget to give jenkins user permission for writing:
sudo chmod 757 -R /var/lib/jenkins/jobs/
Email notifications
Also don't forget to setup email notifications, for example you can create jenkins gmail account and set up gmail smtp:
http://kb.siteground.com/article/How_to_use_Googles_free_SMTP_server.html
In Jenkins config for your project add post-build action as Send email like this:

Git tag issue
After adding multiple gits (unfuddle, github) I got error with git tag command.
Solution: http://fijiaaron.wordpress.com/2012/03/08/skip-internal-tag-jenkins-git/
Github gook
Github intagration: http://fourkitchens.com/blog/2011/09/20/trigger-jenkins-builds-pushing-github
Have nice development with Jenkins!

Uninstall Jenkins is easy too, just:
sudo apt-get remove jenkins
Comments
rimidl commented 7 months ago
Thanks!
pbiggar commented 7 months ago
We have a service which does this all for you in one click, you might like it: https://circleci.com. You'll get it set up in literally 20 seconds, and it will also run your tests way faster.
kirs commented 6 months ago
You should probably write a Chef recipe for Jenkins on Ubuntu.
kidbrax commented 4 months ago
You may also want to look at https://semaphoreapp.com/. We have had good luck with it.
kirs commented 4 months ago
@kidbrax it's hosted. Most of all companies can't share code to 3rd party services
markoa commented 4 months ago
@kirs depends what you mean by most, it's a bit like saying "most companies can't use GitHub".
If you are on GitHub though, the setup and learning curve on Semaphore is pretty much non existent. It's focused on Ruby, rock solid and you can easily run your tests in multiple threads.
kirs commented 4 months ago
@markoa is it possible to use self-hosted Semaphore?