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