Over a million developers have joined DZone.

Bundler and Cross-Platform Development

DZone's Guide to

Bundler and Cross-Platform Development

· DevOps Zone
Free Resource

Download “The DevOps Journey - From Waterfall to Continuous Delivery” to learn learn about the importance of integrating automated testing into the DevOps workflow, brought to you in partnership with Sauce Labs.

The hazards of cross-platform development

Recently I helped a co-worker with getting Rails, Nginx, and Unicorn up and running in a Linux VM, using Capistrano to deploy the Rails application from the development box. While we got this to work in the end, it was not without pain. You see, we wanted the deployment to work regardless of the development platform.

The problems we ran into all revolved around Bundler, specifically that it wanted to use the entries in the Gemfile.lock file to determine what gems to install on the VM. This isn't a 'problem with Bundler'; it wants to use the Gemfile.lock to install the specific gem versions used during development, which is a desirable thing. The problem is that our stack used gems with native extensions that are different/don't exist across the platforms involved.

As background, here's the Capistrano file we started out with: deploy.rb.

Problem #1: Unicorn isn't available for Windows

Development environment, who cares what we use to handle HTTP right? Just add something like the following to the Gemfile so Unicorn won't install on Windows but will install on the VM and test using WEBrick locally:

platforms :ruby do gem 'unicorn' end 

Wrong. If you don't install Unicorn on the development environment, it won't be added to the Gemfile.lock file and so the server never installs Unicorn since it's only looking at the Gemfile.lock entries.

The only way we were able to work around this was to add the following to the deploy.rb file used by Capistrano:

set :bundle_flags, "--no-deployment --quiet" 

This says it's not a deployment, so install the gems based on the Gemfile rather than Gemfile.lock, and don't return all the output of this operation. Not ideal, as it completely negates Bundlers "I've got a list of all your gem versions used in development" functionality but after searching around I couldn't find a better solution.

Problem #2: .sh files not executable once deployed

This was fairly minor, but still important. The unicorn_init.sh file used to start/stop unicorn was not marked as executable once deployed to the Linux VM, so Unicorn wasn't starting at the end of deployment. We resolved this by adding a "fix permissions" task to the deploy.rb file, and then invoking it after the "deploy:finalize_update" task. Here's the code:

 desc "Fix permission"
task :fix_permissions, :roles => [ :app, :db, :web ] do
 run "chmod +x #{release_path}/config/unicorn_init.sh"

after "deploy:finalize_update", "deploy:fix_permissions"

The real problem: native modules

No, I'm not going on a rant about how native modules are evil or that you should make sure they work on all platforms. But be aware that you're using them and that they may cause problems when someone decides to use your code on a different platform.

Note that this isn't a Ruby/Bundler specific issue, as other languages such as Node.js have similar native code issues. Any time you have to leverage OS or hardware specific functionality, you limit the portability of your code.

Is there a better way?

For working with Bundler, not that I could find. I'd be interested if anyone has recommendations on dealing with the development and deployment of Rails applications in heterogeneous environments.

Discover how to optimize your DevOps workflows with our cloud-based automated testing infrastructure, brought to you in partnership with Sauce Labs


Published at DZone with permission of Brian Swan, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.


Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.


{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}