I’m in the final stages of upgrading my Rails 2.3 app to Rails 3.2. In this stage, I’ve also upgraded from Ruby 1.8.7 to 1.9.3. That’s meant a new version of the capistrano gem, and the inclusion of require ‘bundler/capistrano’ in deploy.rb.
cap deploy currently executes fine until it gets to a step where it’s trying to run bundle install on the production (ubuntu 12.04) server. There it gives the error message “Cannot write a changed lockfile while frozen.”
Googling this error leads to a few SO threads and some issue reports for bundler that point to a problem with Gemfile.lock being created on a Windows machine (with mingw-platform gems) and then being deployed on a unix machine. That would appear to apply to me. Some workarounds using the :platform option are mentioned, but they don’t seem to solve my issue. I have the latest version of bundler installed on both machines (1.3.5) and my Gemfile simply says gem ‘bundler’ with no version number specified.
Prior to this point, I haven’t had a capistrano recipe in place to run bundle install. Instead, I’ve simply manually installed new gems as needed on the production server when deploy error messages mentioned missing gems. Now that capistrano is trying to run bundle install, the problems have arisen.
Any help would be greatly appreciated. I basically can’t deploy any changes to my app as things stand.
This is a tricky problem. I’ve never used capistrano before, but I have had similar difficulties in the past when trying to deploy to a different OS. I believe that capistrano uses the --deployment flag when bundling. See the docs. You need the gems for both OS’s to be listed in the Gemfile.lock, but you don’t actually want them both required in all environments.
There is a long-standing bundler issue about this very thing. There’s some sample code in the bundler wiki that will put everything into Gemfile.lock but will only require those gems on the appropriate platform. This may do the trick for you, or it may not. If the gem in question is unable to install (or no-op) on all platforms then bundle install will fail. Either way, it’s not what I would call an optimal solution.
Which gems are giving you trouble? Do you absolutely have to have them in your production environment? Could you isolate them to your dev, test, or assets groups (precompiling assets and not requiring that group at runtime in production)? If so, I think you could use bundle package alsong with bundle install --deployment --without development test assets to successfully bundle in production.
Failing all of this, there’s always the option of using Vagrant to keep your local development environment in step with production. I know that several people here are happy Vagrant users.
This looks like hugely helpful advice. I’ll work through the links you provided and see if I can live without the platform-specific gems. One thing I haven’t tried yet is seeing if cloning the repository on my mac and trying to deploy from there might solve the problem. I’ll see if that makes a difference and update the post.