Friday 14 October 2011

Continuous Integration - Headless JS on CentOS

This was a bit of a pain to get working so I thought I would layout the steps to get Continuous Integration (CI) working on CentOS 5.5 with cruise control, rspec and cucumber when you have javascript scenarios you want to run without a real browser.

Before Cruise Control is set up:

1) Clone the latest version of CC from: http://cruisecontrolrb.thoughtworks.com/documentation to your server. (read the guide, update your database.yml etc...)

2) CC can run standalone so start the server. and add your project(s)

3) If you have apache running you will have to set up a virtual host and set it to run as a proxy to the CI e.g. my configuration is:


ServerAdmin EMAIL_ADDRESS
ServerName DOMAIN_NAME
ErrorLog PATH_TO_ERROR_LOG
CustomLog PATH_TO_CUSTOM_LOG
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]


Thanks TomJ.

4) vim lib/tasks/custom_cc.rake

desc 'Custom curise task for RSpec'
task :cruise do
ENV['RAILS_ENV'] = 'test'

if File.exists?(Dir.pwd + "/config/database.yml")
if Dir[Dir.pwd + "/db/migrate/*.rb"].empty?
raise "No migration scripts found in db/migrate/ but database.yml exists, " +
"CruiseControl won't be able to build the latest test database. Build aborted."
end

# perform standard Rails database cleanup/preparation tasks if they are defined in project
# this is necessary because there is no up-to-date development database on a continuous integration box
if Rake.application.lookup('db:test:purge')
CruiseControl::invoke_rake_task 'db:test:purge'
end

if Rake.application.lookup('db:migrate')
CruiseControl::reconnect
CruiseControl::invoke_rake_task 'db:migrate'
end
end

CruiseControl::invoke_rake_task 'spec'
CruiseControl::invoke_rake_task 'cucumber:ok'
end

After Cruise Control is set up

If all is going well then you should be able to start the builder for that project and it should be running the rspec and cucumber tests suite. Now you hit the requirement of writing the scenarios that require javascript and these are currently failing (not unexpected since we don't have a X11 system or browser installed). There are a couple of ways to get these tests running the method I chose was:

1. Add capybara-webkit and headless to the Gemfile:

group :test, :cucumber do
....
gem 'headless'
gem 'capybara-webkit'
....
end

2. Update the features/support/env.rb. Require headless and start it. Also set the capybara js driver to webkit.

require 'cucumber/rails'
require 'headless'

headless = Headless.new
headless.start

Capybara.javascript_driver = :webkit
Capybara.default_selector = :css
Capybara.server_boot_timeout = 50

ActionController::Base.allow_rescue = false

begin
DatabaseCleaner.strategy = :transaction
rescue NameError
raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it."
end

3. Now on the CI server we need to install some packages for the capybara-webkit gem (I hope you have permission)

sudo yum install -y Xvfb
sudo yum install -y qt4 qt4-devel

4. Almost there. Start the screen or capybara will give you an error like "webkit_server: cannot connect to X server"

Xvfb :1 -screen 0 1024x768x16 -nolisten inet6 &

It should now be running in the background, you can check ps or jobs

5. Kill the builder and reboot the CI app and then push the earlier changes. When you start the builder again all the tests should now run and if you're lucky they may even pass.

1 comment:

  1. Great post! This helped me out after I got the connect to X server error. I'm using evergreen in a CI environment.

    One this I did though, so I don't spawn multiple Xvfb processes (ie one for each build), was to use:

    xvfb-run -a bundle exec rake spec:javascripts RAILS_ENV=test

    Thanks Again

    Abe

    ReplyDelete