March 10, 2009 by Morten Bagai
Gem installation and management has always been pain when the time comes to deploy an app. Rails 2.1 made good progress in this area with gem dependency specifications, allowing you to vendor required gems with a of set rake commands. That’s the method we’ve been recommending for Heroku apps until now, but it does leave important problems unsolved.
First, a substantial limitation of the vendoring method is that it only works with pure Ruby gems. Many apps depend on gems with native extensions that need to be compiled on the deployment target. It’s no good compiling a gem on your Mac laptop and trying to deploy the resulting binary to a Linux host.
Then there’s the issue of adding extra bulk to your code repo by checking in vendored gems. Bulkier repos cause slower deploys, and slower usually equates to fewer. From a process perspective, the net result is decreasing the agility of your codebase. And in a cloud computing environment, these translate to direct scalability consequences: big repos don’t scale as fast as lean ones.
A next-generation web host should have a next-generation solution to this problem. Today we’re excited to introduce just such a solution: gem manifests, the new standard for gem installation and dependency management on Heroku!
Here’s the skinny: add a file named “.gems” (this is your gem manifest) to the root of your app. Here you can list your gems in a format identical to what you would pass to “gem install” on the command line:
hpricot --version '>= 0.2' --source code.whytheluckystiff.net dm-core --version 0.9.10
Commit the file, git push to Heroku, and watch as your gems are fetched and installed. For Hpricot, native extensions are compiled before your very eyes!
$ git add .gems $ git commit -m "added gem manifest" $ git push heroku master Counting objects: 4, done. Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 356 bytes, done. Total 3 (delta 1), reused 0 (delta 0) -----> Heroku receiving push -----> Installing gem hpricot >= 0.2 from http://code.whytheluckystiff.net Building native extensions. This could take a while... Successfully installed hpricot-0.6 1 gem installed -----> Installing gem dm-core 0.9.10 from http://gems.rubyforge.org Successfully installed addressable-2.0.2 Successfully installed extlib-0.9.10 Successfully installed data_objects-0.9.11 Successfully installed dm-core-0.9.10 4 gems installed -----> Verifying repository integrity... done, looks like a Rails app. Compiled slug size is 4.3MB -----> Launching.............. done App deployed to Heroku To email@example.com:vivid-moon-60.git 91425e3..fe10e87 master -> master
As you can see, this gem manifest is lightweight, framework-agnostic (works great with Sinatra), and won’t add any weight to your repo since installation is done in the cloud. Your gems are automatically in the require path, so you can pull them into your app easy-as-pie. Finally, gems are only compiled when the manifest changes, so subsequent deploys will be fast as ever.
Check out the docs, take it for a test-drive, and tell us what you think.