-
Notifications
You must be signed in to change notification settings - Fork 0
Add BUNDLE_GEMFILE-aware dual-boot support (rebased on v359) #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: sync_v359
Are you sure you want to change the base?
Changes from all commits
a034ccb
48f1020
d18d949
535bb1f
f8b404f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,10 +17,14 @@ | |
| begin | ||
| app_path = Pathname(ARGV[0]) | ||
| cache_path = Pathname(ARGV[1]) | ||
| gemfile_lock = LanguagePack.gemfile_lock(app_path: app_path) | ||
| Dir.chdir(app_path) | ||
|
|
||
| # Load user config vars from the env dir before we touch the Gemfile so that | ||
| # BUNDLE_GEMFILE (set as a Heroku config var) can steer which lockfile we | ||
| # read. Without this, gemfile_lock would always read Gemfile.lock regardless | ||
| # of the user's BUNDLE_GEMFILE setting. | ||
| LanguagePack::ShellHelpers.initialize_env(ARGV[2]) | ||
| gemfile_lock = LanguagePack.gemfile_lock(app_path: app_path) | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Heroku passes user config vars to buildpacks via a directory of files (one file per var), not as actual ENV entries. The path to that dir is ARGV[2] in ruby_compile.rb. Sequence before our fix: gemfile_lock = LanguagePack.gemfile_lock(...) # reads ENV["BUNDLE_GEMFILE"] → ""
Dir.chdir(app_path)
LanguagePack::ShellHelpers.initialize_env(...) # now user_env_hash["BUNDLE_GEMFILE"] = "Gemfile.next"
ENV["BUNDLE_GEMFILE"] # empty, Heroku doesn't set it in ENV
|| LanguagePack::ShellHelpers.user_env_hash[..] # empty too, initialize_env hasn't run yet
|| "Gemfile" # falls through to defaultSo it picked After moving the line below initialize_env, user_env_hash is populated first, gemfile_name resolves to |
||
| LanguagePack.call( | ||
| app_path: app_path, | ||
| cache_path: cache_path, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,7 +19,7 @@ class LanguagePack::Ruby < LanguagePack::Base | |
| # detects if this is a valid Ruby app | ||
| # @return [Boolean] true if it's a Ruby app | ||
| def self.use?(bundler: nil) | ||
| File.exist?("Gemfile") | ||
| File.exist?(LanguagePack.gemfile_name) | ||
| end | ||
|
|
||
| def initialize(...) | ||
|
|
@@ -306,6 +306,7 @@ def self.setup_language_pack_environment(app_path:, ruby_version:, bundle_defaul | |
| ENV["BUNDLE_PATH"] = "vendor/bundle" | ||
| ENV["BUNDLE_BIN"] = "vendor/bundle/bin" | ||
| ENV["BUNDLE_DEPLOYMENT"] = "1" | ||
| ENV["BUNDLE_GEMFILE"] = app_path.join(LanguagePack.gemfile_name).to_s | ||
| end | ||
|
|
||
| # Sets up the environment variables for subsequent processes run by | ||
|
|
@@ -331,6 +332,7 @@ def setup_export(app_path:, ruby_version:, default_config_vars:) | |
| set_export_default "BUNDLE_WITHOUT", ENV["BUNDLE_WITHOUT"] | ||
| set_export_default "BUNDLE_BIN", ENV["BUNDLE_BIN"] | ||
| set_export_default "BUNDLE_DEPLOYMENT", ENV["BUNDLE_DEPLOYMENT"] # Unset on windows since we delete the Gemfile.lock | ||
| set_export_default "BUNDLE_GEMFILE", ENV["BUNDLE_GEMFILE"] | ||
| default_config_vars.each do |key, value| | ||
| set_export_default key, value | ||
| end | ||
|
|
@@ -375,6 +377,7 @@ def setup_profiled(ruby_layer_path:, gem_layer_path:, ruby_version:, default_con | |
| set_env_default "BUNDLE_WITHOUT", ENV["BUNDLE_WITHOUT"] | ||
| set_env_default "BUNDLE_BIN", ENV["BUNDLE_BIN"] | ||
| set_env_default "BUNDLE_DEPLOYMENT", ENV["BUNDLE_DEPLOYMENT"] if ENV["BUNDLE_DEPLOYMENT"] # Unset on windows since we delete the Gemfile.lock | ||
| set_env_override "BUNDLE_GEMFILE", LanguagePack.gemfile_name | ||
| end | ||
|
|
||
| def warn_outdated_ruby | ||
|
|
@@ -617,7 +620,29 @@ def self.remove_vendor_bundle(app_path:) | |
| end | ||
|
|
||
| # runs bundler to install the dependencies | ||
| # If the active Gemfile (typically Gemfile.next in dual-boot setups) is a | ||
| # symlink, materialize it as a real file so that `File.basename(__FILE__)` | ||
| # inside the Gemfile resolves to the symlink name regardless of how the | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure why this is needed, we always use a symlink when dual booting and it has worked for every version of Bundler since forever, we had never had issues with this approach and this same buildpack also worked in many cases before I don't understand why this is needed, what is the issue this is solving? |
||
| # active Bundler version handles symlinks. The repo keeps the symlink for | ||
| # the developer workflow; the buildpack only rewrites the working copy for | ||
| # the duration of this build. | ||
| def self.materialize_gemfile_symlink(app_path:, io:) | ||
| gemfile = app_path.join(LanguagePack.gemfile_name) | ||
| return unless gemfile.symlink? | ||
|
|
||
| target = File.readlink(gemfile.to_s) | ||
| target_path = gemfile.dirname.join(target) | ||
| return unless target_path.exist? | ||
|
|
||
| io.topic("Materializing #{LanguagePack.gemfile_name} symlink -> #{target}") | ||
| contents = target_path.read | ||
| gemfile.delete | ||
| gemfile.write(contents) | ||
| end | ||
|
|
||
| def self.build_bundler(app_path:, io:, bundler_cache:, bundler_version:, bundler_output:, ruby_version:) | ||
| materialize_gemfile_symlink(app_path: app_path, io: io) | ||
|
|
||
| if app_path.join(".bundle/config").exist? | ||
| warn(<<~WARNING, inline: true) | ||
| You have the `.bundle/config` file checked into your repository | ||
|
|
@@ -640,7 +665,7 @@ def self.build_bundler(app_path:, io:, bundler_cache:, bundler_version:, bundler | |
| io.topic("Installing dependencies using bundler #{bundler_version}") | ||
| env_vars = {} | ||
|
|
||
| env_vars["BUNDLE_GEMFILE"] = app_path.join("Gemfile").to_s | ||
| env_vars["BUNDLE_GEMFILE"] = app_path.join(LanguagePack.gemfile_name).to_s | ||
| env_vars["BUNDLE_CONFIG"] = app_path.join(".bundle/config").to_s | ||
| env_vars["NOKOGIRI_USE_SYSTEM_LIBRARIES"] = "true" | ||
| env_vars["BUNDLE_DISABLE_VERSION_CHECK"] = "true" | ||
|
|
@@ -709,11 +734,13 @@ def rake | |
| end | ||
|
|
||
| def rake_env | ||
| if database_url | ||
| base = if database_url | ||
| {"DATABASE_URL" => database_url} | ||
| else | ||
| {} | ||
| end.merge(user_env_hash) | ||
| end | ||
| base["BUNDLE_GEMFILE"] = app_path.join(LanguagePack.gemfile_name).to_s | ||
| base.merge(user_env_hash) | ||
| end | ||
|
|
||
| def database_url | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stop it failing in our fork.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could just remove this
integration-testsection in our fork instead of disabling it with a conditional