Dynamically deploy feature branch of Rails app using Cap multi-stage

So I periodically have a feature branch of my Rails app that I need to demo to internal stakeholders.  I deploy with apache and passenger.

I started out manually setting up a Passenger deploy of a copy checked out to the feature branch. But that was silly.

Then I used the capistrano built-in multi-stage support to make a `demo` stage, kind of like a ‘staging’ stage.  And I’d hard-code what feature branch I wanted the demo stage to checkout. It was a bit annoying to have to go change the cap ‘branch’ variable in the ‘demo’ stage… until I needed two or three seperate feature demos going at once.

Then I realized, wait, can’t I have cap automate this too? Yep, I can.

So I’ve (ab)used the cap ‘multi-stage’ function to make a `feature_demo` stage that dynamically deploys whatever the *current checked out branch* on disk to my demo server at `/opt/features/name_of_branch`, and sets up the apache passenger config for that new location, making it available at a SubURI on demo server /name_of_branch (and precompiling assets correctly for that SubURI!).

It deploys using a Rails ‘environment’ called ‘demo’, which I created in my app. The ‘demo’ environment is config’s basically the same as production (I just copied config/environments/production.rb to config/environments/demo.rb), but has different database.yml connection info, and different connection info to other remote services my particular app uses — don’t want the feature demos using production db and such.

If it’s the first time that name_of_feature is being deployed, I need to manually restart apache on demo server, but other than that, it takes care of it.

It’s a bit hacky in some ways, but it works. It does require the cap deploy user to have permission to write apache configs in /etc/httpd/conf.d, and aliases in webroot, etc., to set up a new app for passenger.

I’ll show you my code so you can copy and paste it and use it if you want.  One could hypothetically refactor and abstract this into a reusable recipe that’s in a gem, where people just over-rode the particular cap deploy config they needed to — but in my experience so far, writing generalizable reusable cap recipes like this ends up being really confusing and difficult to maintain, so I’m not going to do that (just yet anyway).


Oops, the self-documenting header comments are a bit hard to read in that sourcecode gist. Here they are:

An experiment for a capistrano ‘stage’ that can actually be used to
deploy multiple feature branches at once.

Any of them will get deployed to blacklight.mse.jhu.edu, our current
BL dev/demo machine.

Name of feature branch will be taken from current git checkout.

Will be deployed to /opt/catalyst_feature_demos/name_of_feature, from
git branch name_of_feature, AND an httpd conf will be created telling
passenger to deploy that app, woo.

cap feature_demo deploy

You WILL need to manually restart apache if this is the first time
you’ve deployed that feature demo.

If you want to deploy a different branch than your current checkout:

cap feature_demo deploy -S branch=some_branch

If you want to reference the deployed feature by something other than
branch name:

cap feature_demo deploy -S feature=something_else

feature name is used for directory path of checkout, Apache
subUri, etc. shouldn’t have spaces, should be a nice token.

If you are done with a feature demo and want to wipe it from disk etc,

cap feature_demo deploy:cleanup_feature_demo

(Have to use `feature` or `branch` args matching how you created it)

About these ads
This entry was posted in General. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s