Preserve Bundle configuration during app generation (#34755)

When generating a new rails application (rails new) using a custom template that
includes gems from an authenticated source, the user has to provide credentials to
bundler.

One way to do this is by exporting environment variables, for example:

export BUNDLE_GITHUB__COM=user:pass: provides credentials for bundler to fetch
gems from github.com.

The problem this PR addresses is that we are currently scrubs all /BUNDLE_.*/
environment variables by wrapping our system calls in Bundler.with_clean_env.

We do this because we don't want our commands executed against the generated project
to use the generator's bundler environment (e.g. our gems): the generated project should
use it's own configuration.

The problem with Bundler.with_clean_env is that, on top of restoring environment
variables to their original state, it also scrubs any /BUNDLE_.*/ variables, which is harmful for authenticated gem sources.

This PR replaces Bundler.with_clean_env with Bundler.with_original_env, which only
restores environment variables to their initial state, without additional scrubbing.
This commit is contained in:
Marco Costa 2019-01-08 17:52:06 -05:00 committed by Yuji Yaginuma
parent 80c7038bbc
commit d79366b4c9
3 changed files with 33 additions and 9 deletions

View File

@ -1,3 +1,7 @@
* Use original `bundler` environment variables during the process of generating a new rails project.
*Marco Costa*
* Send Active Storage analysis and purge jobs to dedicated queues by default.
Analysis jobs now use the `:active_storage_analysis` queue, and purge jobs

View File

@ -388,19 +388,21 @@ module Rails
# its own vendored Thor, which could be a different version. Running both
# things in the same process is a recipe for a night with paracetamol.
#
# We unset temporary bundler variables to load proper bundler and Gemfile.
#
# Thanks to James Tucker for the Gem tricks involved in this call.
_bundle_command = Gem.bin_path("bundler", "bundle")
require "bundler"
Bundler.with_clean_env do
full_command = %Q["#{Gem.ruby}" "#{_bundle_command}" #{command}]
if options[:quiet]
system(env, full_command, out: File::NULL)
else
system(env, full_command)
end
Bundler.with_original_env do
exec_bundle_command(_bundle_command, command, env)
end
end
def exec_bundle_command(bundle_command, command, env)
full_command = %Q["#{Gem.ruby}" "#{bundle_command}" #{command}]
if options[:quiet]
system(env, full_command, out: File::NULL)
else
system(env, full_command)
end
end

View File

@ -773,6 +773,24 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_bundler_command_called("install")
end
def test_generation_use_original_bundle_environment
generator([destination_root], skip_webpack_install: true)
mock_original_env = -> do
{ "BUNDLE_RUBYONRAILS__ORG" => "user:pass" }
end
ensure_environment_is_set = -> *_args do
assert_equal "user:pass", ENV["BUNDLE_RUBYONRAILS__ORG"]
end
Bundler.stub :original_env, mock_original_env do
generator.stub :exec_bundle_command, ensure_environment_is_set do
quietly { generator.invoke_all }
end
end
end
def test_dev_option
generator([destination_root], dev: true, skip_webpack_install: true)