Thursday, October 9, 2008

Building Custom Deployment directories using sprinkle

At work we deploy multiple RoR applications on each server. Managing the environments for all these applications is a huge headache. We have applications in production using Rails 1.2.5 all the way till Rails 2.1.1. In addition to rails, other gems need updates routinely as well. This breaks applications that have been running smoothly for the past year or so.
Further, new IT policy changes have taken away developer's sudo access on these servers, which makes developing cumbersome and difficult - having to go through IT for every environment update request.

So I set upon the task of developing an easy way to deploy each application in its own environment.
Following are the goals I wanted to achieve:
  • Each application runs in its own deployment environment. By environment I mean a complete directory structure that has its own ruby and gem installation, along with any additional software such as database, web server, Imagemagick, reverse proxy etc.
  • The environment should be easy to duplicate for staging and development, thus keeping the production environment isolated until QA is done and the application is ready to be deployed in production
  • The environment should be easy to build - fire off a script and go get a coffee while the environment is being built and configured.
I gave Fiveruns install a try. It is a great product, but the stack is not extensible - I cannot add additional software components to the install process.

I came upon Marcus Crafter's sprinkle which allows easy provisioning of new VPS systems. It is an awesome piece of code that makes setting up new systems a breeze.

Sprinkle is a new prototype tool that you can use to provision your servers/slices. Its declarative policy/state based approach for specifying how a remote system should be provisioned with intelligent logic to support dependencies, multiple installer types and remote installation is really compelling.

The ruby based DSL used to describe the provisioning setup is easy to understand and maintain.

However, sprinkle in its current form provisioned the entire system to a specific deployment environment - not what I had in mind.
So I created a fork of the sprinkle codebase on github and added the capability to build local deployment directories to sprinkle.
Here is a log of the functionality I added:
  1. bin/sprinkle - updated to accept -d option and create a environment source file at the end
  2. sprinkle.gemspec - added actors/local.rb which was missing
  3. lib/sprinkle/actors/local.rb - updated to set env vars before calling the system command (sets PATH and LD_LIB to the deploy dir), also raises an exeception if a command fails
  4. lib/sprinkle/installers/gem.rb - by default doesn't build ri and rdoc anymore - need to specify build_docs as a gem option
  5. lib/sprinkle/installers/source.rb - custom_install is now an array of commands, added custom_stage , cmd to override default stages, source now accepts a path as a valid option to copy the archive from.
  6. lib/sprinkle/verifiers/ruby.rb - removed sudo while verifying a gem
  7. Added has_successful_execution verifier to verify installations

To get started with this new functionality:

  1. Install the sprinkle gem.
    - git clone git://
    - cd sprinkle
    - gem build sprinkle.gemspec
    - gem install sprinkle.gemspec
  2. Create a sprinkle recipe (download)
  3. Run sprinkle and go get a coffee
    - sprinkle -c - v -d deploy_dir -s build_deployment_env.rb
  4. Source the env.
    - source deploy_dir/source_env.tcsh
  5. Test the paths
    - which ruby
    - which gem
    - gem list

Now cd to your rails application dir and start up the server - Voila - custom a la carte deployment environments :)


No comments: