Skip to content

Commit 6ebd76c

Browse files
authored
Raise an explicit error message for Bundler 1.x (heroku#1561)
With the Ruby 3.3.7 default, bundler 1.x no longer works on Heroku with the Ruby buildpack. Here's the details of what's causing the error: The Ruby buildpack uses Ruby code to inspect the application at build time to know what dependencies and versions to install. The version of Ruby that the buildpack uses is tied to the default Ruby version. Recently this version was changed to Ruby 3.3.7 https://devcenter.heroku.com/changelog-items/3167. The Ruby buildpack runs `bundle platform --ruby` in order to determine what Ruby version the application needs. This invokes bundler using the current Ruby version (3.3.7). However, bundler is using a method that was deprecated and removed in Ruby 3.2 https://ruby-doc.org/stdlib-2.7.1/libdoc/pathname/rdoc/Pathname.html#method-i-untaint. Because this method does not exist in Ruby 3.3 the bundler code cannot execute and fails with an error message: ``` remote: ! There was an error parsing your Gemfile, we cannot continue remote: ! /tmp/d20250319-150-o0ictl/bundler-1.17.3/gems/bundler-1.17.3/lib/bundler/shared_helpers.rb:29:in `root': undefined method `untaint' for an instance of Pathname (NoMethodError) remote: ! remote: ! Pathname.new(gemfile).untaint.expand_path.parent remote: ! ^^^^^^^^ remote: ! from /tmp/d20250319-150-o0ictl/bundler-1.17.3/gems/bundler-1.17.3/lib/bundler.rb:234:in `root' remote: ! from /tmp/d20250319-150-o0ictl/bundler-1.17.3/gems/bundler-1.17.3/lib/bundler.rb:246:in `app_config_path' remote: ! from /tmp/d20250319-150-o0ictl/bundler-1.17.3/gems/bundler-1.17.3/lib/bundler.rb:273:in `settings' remote: ! from /tmp/d20250319-150-o0ictl/bundler-1.17.3/gems/bundler-1.17.3/lib/bundler/feature_flag.rb:21:in `block in settings_method' remote: ! from /tmp/d20250319-150-o0ictl/bundler-1.17.3/gems/bundler-1.17.3/lib/bundler/cli.rb:97:in `<class:CLI>' remote: ! from /tmp/d20250319-150-o0ictl/bundler-1.17.3/gems/bundler-1.17.3/lib/bundler/cli.rb:7:in `<module:Bundler>' remote: ! from /tmp/d20250319-150-o0ictl/bundler-1.17.3/gems/bundler-1.17.3/lib/bundler/cli.rb:6:in `<top (required)>' remote: ! from <internal:/tmp/tmp.CMaelujSAR/lib/ruby/3.3.0/rubygems/core_ext/kernel_require.rb>:136:in `require' remote: ! from <internal:/tmp/tmp.CMaelujSAR/lib/ruby/3.3.0/rubygems/core_ext/kernel_require.rb>:136:in `require' remote: ! from /tmp/tmp.CMaelujSAR/lib/ruby/gems/3.3.0/gems/bundler-2.5.22/exe/bundle:21:in `block in <top (required)>' remote: ! from /tmp/d20250319-150-o0ictl/bundler-1.17.3/gems/bundler-1.17.3/lib/bundler/friendly_errors.rb:124:in `with_friendly_errors' remote: ! from /tmp/tmp.CMaelujSAR/lib/ruby/gems/3.3.0/gems/bundler-2.5.22/exe/bundle:20:in `<top (required)>' remote: ! from /tmp/d20250319-150-o0ictl/bundler-1.17.3/bin/bundle:23:in `load' remote: ! from /tmp/d20250319-150-o0ictl/bundler-1.17.3/bin/bundle:23:in `<main>' ``` Bundler `1.17.3` was last released on December 27, 2018, and is no longer supported by bundler/rubygems core, so it has not been patched to remove this deprecated method. You can fix this issue by upgrading your application to bundler 2.3.x. I suggest `2.3.27`. Run: ``` $ gem install bundler -v 2.3.27 $ bundle update --bundler ``` Verify that the correct version is listed in the Gemfile.lock: ``` $ cat Gemfile.lock | grep "BUNDLED WITH" -A2 BUNDLED WITH 2.3.27 ``` And check the results into git: ``` $ git add Gemfile.lock $ git commit -m "Update bundler version to 2.3.x" ``` Then deploy. Bundler 2.3.x supports Ruby >= 2.3.0 so it should work for your application. If you're using an older version of Rails that's locked to an older version of bundler, you can work around this with Rails LTS. That information and other upgrade suggestions are here https://www.reddit.com/r/Heroku/comments/1ij7b89/upgrading_ruby_versions_to_run_on_heroku24/. ## Additional concerns Beyond `bundle platform --ruby` the buildpack also requires bundler internals to parse and load the Gemfile.lock. This strategy only works if the version of Ruby we're using for the buildpack is capable of running that version of bundler. Previously we only supported one version of bundler, but now that we support multiple, the Ruby version must be capable of running them all. We can move away from `bundle platform --ruby` by parsing the `Gemfile.lock` manually (this is what the CNB does) we can move away from requiring an arbitrary bundler version by listing out gems after they're installed via `gem list` or `bundle list`. However these are two relatively large behavior changes. It's still possible to temporarily use bundler 1.17.3 on the platform by using an older buildpack version https://devcenter.heroku.com/articles/bundler-version#using-an-older-version-of-bundler. However this should only be considered a temporary fix and not a long term one.
1 parent 9bd2f0e commit 6ebd76c

3 files changed

Lines changed: 21 additions & 15 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
## [Unreleased]
44

5+
- Explicit error message raised with upgrade instructions for applications specifying bundler `1.x` in the Gemfile.lock (https://github.com/heroku/heroku-buildpack-ruby/pull/1561)
56

67
## [v294] - 2025-03-19
78

89
- Default Ruby version is now 3.3.7 (https://github.com/heroku/heroku-buildpack-ruby/pull/1534)
910
- Default bundler version (when no version present in the `Gemfile.lock`) is now bundler `2.3.x` which is currently `2.3.25` (https://github.com/heroku/heroku-buildpack-ruby/pull/1534)
11+
- Bundler 1.x will no longer work with the Ruby buildpack (https://github.com/heroku/heroku-buildpack-ruby/pull/1534)
1012

1113
## [v293] - 2025-02-15
1214

lib/language_pack/helpers/bundler_wrapper.rb

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ class LanguagePack::Helpers::BundlerWrapper
3636
include LanguagePack::ShellHelpers
3737

3838
BLESSED_BUNDLER_VERSIONS = {}
39-
BLESSED_BUNDLER_VERSIONS["1"] = "1.17.3"
4039
# Heroku-20's oldest Ruby verison is 2.5.x which doesn't work with bundler 2.4
4140
BLESSED_BUNDLER_VERSIONS["2.3"] = "2.3.25"
4241
BLESSED_BUNDLER_VERSIONS["2.4"] = "2.4.22"
@@ -48,7 +47,22 @@ class LanguagePack::Helpers::BundlerWrapper
4847
# Convert arbitrary `<Major>.<Minor>.x` versions
4948
BLESSED_BUNDLER_VERSIONS.default_proc = Proc.new do |hash, key|
5049
if Gem::Version.new(key).segments.first == 1
51-
hash["1"]
50+
raise BuildpackError.new(<<~EOF)
51+
Cannot install bundler 1.17.3
52+
53+
Your application requested bundler `#{key}` in the `Gemfile.lock`
54+
which resolved to `1.17.3`. This version no longer works on
55+
Heroku. Please upgrade to bundler `2.3.x` or higher:
56+
57+
```
58+
$ gem install bundler -v #{hash["2.3"]}
59+
$ bundle update --bundler
60+
$ git add Gemfile.lock
61+
$ git commit -m "Updated bundler version"
62+
```
63+
64+
https://devcenter.heroku.com/changelog-items/3166
65+
EOF
5266
elsif Gem::Version::new(key).segments.first == 2
5367
if Gem::Version.new(key) > Gem::Version.new("2.6")
5468
hash["2.6"]

spec/helpers/bundler_wrapper_spec.rb

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
describe "Bundler version detection" do
1616
it "supports minor versions" do
1717
wrapper_klass = LanguagePack::Helpers::BundlerWrapper
18-
version = wrapper_klass.detect_bundler_version(contents: "BUNDLED WITH\n 1.17.3")
19-
expect(wrapper_klass::BLESSED_BUNDLER_VERSIONS.key?("1")).to be_truthy
20-
expect(version).to eq(wrapper_klass::BLESSED_BUNDLER_VERSIONS["1"])
18+
expect {
19+
wrapper_klass.detect_bundler_version(contents: "BUNDLED WITH\n 1.17.3")
20+
}.to raise_error(BuildpackError)
2121

2222
version = wrapper_klass.detect_bundler_version(contents: "BUNDLED WITH\n 2.2.7")
2323
expect(wrapper_klass::BLESSED_BUNDLER_VERSIONS.key?("2.3")).to be_truthy
@@ -59,16 +59,6 @@
5959
expect(bundler.supports_multiple_platforms?).to be_truthy
6060
end
6161
end
62-
63-
it "reports false on bundler prior to 2.2" do
64-
Dir.mktmpdir do |dir|
65-
gemfile = Pathname(dir).join("Gemfile")
66-
lockfile = Pathname(dir).join("Gemfile.lock").tap {|p| p.write("BUNDLED WITH\n 1.15.2") }
67-
68-
bundler = LanguagePack::Helpers::BundlerWrapper.new(gemfile_path: gemfile)
69-
expect(bundler.supports_multiple_platforms?).to be_falsey
70-
end
71-
end
7262
end
7363

7464
describe "BundlerWrapper mutates rubyopt" do

0 commit comments

Comments
 (0)