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).

https://gist.github.com/4260448

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)