Bundler 2.2.3+ and deployment of Ruby apps

prathamesh

Prathamesh Sonpatki

Posted on April 20, 2021

Bundler 2.2.3+ and deployment of Ruby apps

While deploying a new Rails 6.1.3.1 application built with Bundler 2.2.16 on Heroku, I ran into this error in Heroku build log.

-----> Ruby app detected
-----> Installing bundler 2.2.15
-----> Removing BUNDLED WITH version in the Gemfile.lock
-----> Compiling Ruby/Rails
-----> Using Ruby version: ruby-3.0.1
-----> Installing dependencies using bundler 2.2.15
       Running: BUNDLE_WITHOUT='development:test' BUNDLE_PATH=vendor/bundle BUNDLE_BIN=vendor/bundle/bin BUNDLE_DEPLOYMENT=1 bundle install -j4
       Your bundle only supports platforms ["x86_64-darwin-20"] but your local platform
       is x86_64-linux. Add the current platform to the lockfile with `bundle lock
       --add-platform x86_64-linux` and try again.
       Bundler Output: Your bundle only supports platforms ["x86_64-darwin-20"] but your local platform
       is x86_64-linux. Add the current platform to the lockfile with `bundle lock
       --add-platform x86_64-linux` and try again.
 !
 ! Failed to install gems via Bundler.
 !
 ! Push rejected, failed to compile Ruby app.
 ! Push failed
Enter fullscreen mode Exit fullscreen mode

If you are using Bundler 1.x you will not run into this error. It only happens with Bundler 2.2.3 and above. My bundler version is 2.2.16.

The app was built on Mac OS X. The Gemfile.lock contained following line.

PLATFORMS
  x86_64-darwin-20
Enter fullscreen mode Exit fullscreen mode

As per the warning it seems that my Gemfile was generated for Mac OS X but I am deploying to Linux and it was raising a flag. Kudos to Heroku buildpack to raise a user friendly error message!

A lot of gems such as nokogiri ship platform specific releases. In previous versions of Bundler, the approach for detecting the platform specific version was error-prone as per this comment. To mitigate such errors, bundler now sets up Gemfile.lock for the platform on which it was generated.

When deploying to Heroku, the Heroku Ruby buildpack runs bundle install in deployment mode. It expects that Gemfile.lock to be frozen and already compatible with the platform on which it is being run. In our case, the Gemfile.lock is not compatible with the platform on which Heroku is deploying which is Linux and the platform on which it was generated which is Mac.

If we do not use the deployment mode, then bundler will resolve the gems in real time with current platform and this problem will not happen.

Though you should not do this as dev-prod parity breaks down and in production, bundler may resolve to the gems which you have not tested in development or test mode.

To fix this, as the warning recommended, I added linux platform using following command.

bundle lock --add-platform x86_64-linux
Enter fullscreen mode Exit fullscreen mode

This generated following diff in Gemfile.lock.

diff --git a/Gemfile.lock b/Gemfile.lock
index 9f4c3ad..ab20d37 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -102,6 +102,8 @@ GEM
     nio4r (2.5.7)
     nokogiri (1.11.3-x86_64-darwin)
       racc (~> 1.4)
+ nokogiri (1.11.3-x86_64-linux)
+ racc (~> 1.4)
     pg (1.2.3)
     public_suffix (4.0.6)
     puma (5.2.2)
@@ -198,6 +200,7 @@ GEM

 PLATFORMS
   x86_64-darwin-20
+ x86_64-linux
Enter fullscreen mode Exit fullscreen mode

After pushing this change to Heroku, the deployment went through.

Non-Heroku deployments

This is not specific to deployments on Heroku only. It can be seen in any other deployment platform as well where we are deploying to Linux and developing on Mac. The fix is same, add the platform to Gemfile.lock and redeploy.


💖 💪 🙅 🚩
prathamesh
Prathamesh Sonpatki

Posted on April 20, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related