Deploying with Foreman in multiple environments

Foreman is a gem that allows you to define what processes an (rails) app needs to run. For example background workers, pubsub etc.

Typically I like to deploy my applications to at least two environments: staging and production, not to mention running it in development locally. I had to do a bit of wrangling to get Foreman to do this. Specifically I need to start my services using different rails environments, and Foreman does not seem have have built in support for this. (Heroku seem to not care about environments in the Procfile  – I assume they have their own magic way of dealing with this)

First I set up a directory

config/procfiles

and in there I put the following to files

production.proc
-------------------
worker: RAILS_ENV=production bundle exec rake jobs:work

and

staging.proc
---------------
worker: RAILS_ENV=staging bundle exec rake jobs:work

Then I added the following Capistrano tasks into deploy.rb (which handle installing and restarting the processes as upstart scripts on my server)

  namespace :services do

    desc "Restart all the services"
    task :restart do
      run "#{sudo} restart #{application}"
    end

    desc "Wipe and recreate the upstart scripts - (also restarts the services)"
    task :reinstall do

      raise "STOP!!!" if application.nil?

      begin
        run "#{sudo} stop #{application}"
      rescue
        # don't care if we can't stop. just means it wasn't running
      end

      run "#{sudo} rm -f /etc/init/#{application}*"

      run "cd #{current_path}; #{sudo} bundle exec foreman export upstart /etc/init -a #{application} -f #{current_path}/config/procfiles/#{stage}.proc -u #{user} -c worker=1"

      # Insert command to start service at boot time NOTE this does not work on the mac version of sed which is not GNU sed
      run "#{sudo} sed -i '1 i start on runlevel [2345]' /etc/init/#{application}.conf"
      run "#{sudo} start #{application}"
    end

    after "deploy:update", "deploy:services:reinstall"
  end

Now I can run cap staging deploy (I’m using capistrano-multistage) and it will stop all my services, setup up the right upstart scripts (in case I have changed the Procfiles) and restart my services

By |August 4th, 2011|Technical|2 Comments