diff --git a/lib/pdk/util/bundler.rb b/lib/pdk/util/bundler.rb index 3af75fd08..63a80d577 100644 --- a/lib/pdk/util/bundler.rb +++ b/lib/pdk/util/bundler.rb @@ -1,4 +1,5 @@ require 'bundler' +require 'fileutils' require 'tty-spinner' require 'pdk/util' require 'pdk/cli/exec' @@ -22,8 +23,20 @@ def self.ensure_bundle! end unless bundle.locked? - unless bundle.lock! - raise PDK::CLI::FatalError, _('Unable to resolve Gemfile dependencies.') + if PDK::Util.package_install? + # In packaged installs, try to use vendored Gemfile.lock as a starting point. + # The 'bundle install' below will pick up any new dependencies. + vendored_gemfile_lock = File.join(PDK::Util.package_cachedir, 'Gemfile.lock') + + if File.exist?(vendored_gemfile_lock) + PDK.logger.debug(_("No Gemfile.lock found in module, using vendored Gemfile.lock from '%{source}'") % { source: vendored_gemfile_lock }) + FileUtils.cp(vendored_gemfile_lock, File.join(PDK::Util.module_root, 'Gemfile.lock')) + end + else + # In non-packaged installs, just let bundler resolve deps as normal. + unless bundle.lock! + raise PDK::CLI::FatalError, _('Unable to resolve Gemfile dependencies.') + end end end diff --git a/package-testing/tests/validate_a_new_module.rb b/package-testing/tests/validate_a_new_module.rb index 51e52bdcd..e0c8c02f1 100644 --- a/package-testing/tests/validate_a_new_module.rb +++ b/package-testing/tests/validate_a_new_module.rb @@ -12,9 +12,12 @@ end step 'Validate the module' do - on(workstation, "cd #{module_name} && #{pdk_command(workstation, 'validate')}", accept_all_exit_codes: true) do |outcome| + on(workstation, "cd #{module_name} && #{pdk_command(workstation, 'validate --debug')}", accept_all_exit_codes: true) do |outcome| assert_equal(0, outcome.exit_code, "Validate on a new module should return 0. stderr was: #{outcome.stderr}") + + assert_match(%r{using vendored gemfile\.lock}i, outcome.stdout, 'pdk should use vendored Gemfile.lock') + on(workstation, "test -f #{module_name}/Gemfile.lock", accept_all_exit_codes: true) do |lock_check_outcome| assert_equal(0, lock_check_outcome.exit_code, 'pdk validate should have caused a Gemfile.lock file to be created') end diff --git a/spec/unit/pdk/util/bundler_spec.rb b/spec/unit/pdk/util/bundler_spec.rb index 71cdf5f00..7d1096370 100644 --- a/spec/unit/pdk/util/bundler_spec.rb +++ b/spec/unit/pdk/util/bundler_spec.rb @@ -53,6 +53,8 @@ def bundle_regex context 'when there is no Gemfile.lock' do before(:each) do + allow(described_class).to receive(:already_bundled?).and_return(false) + allow(File).to receive(:file?).with(%r{Gemfile$}).and_return(true) allow(File).to receive(:file?).with(%r{Gemfile\.lock$}).and_return(false) @@ -62,6 +64,24 @@ def bundle_regex allow_command([bundle_regex, 'install', any_args]) end + context 'when part of a packaged installation' do + before(:each) do + allow(PDK::Util).to receive(:package_install?).and_return(true) + allow(File).to receive(:file?).with(%r{PDK_VERSION}).and_return(true) + allow(File).to receive(:exist?).with(bundle_regex).and_return(true) + end + + it 'copies a Gemfile.lock from vendored location' do + allow(PDK::Util).to receive(:package_cachedir).and_return('/package/cachedir') + allow(File).to receive(:exist?).with('/package/cachedir/Gemfile.lock').and_return(true) + + expect(logger).to receive(:debug).with(%r{using vendored gemfile\.lock}i) + expect(FileUtils).to receive(:cp).with('/package/cachedir/Gemfile.lock', %r{Gemfile\.lock$}) + + described_class.ensure_bundle! + end + end + it 'generates Gemfile.lock' do expect_command([bundle_regex, 'lock', any_args], nil, %r{resolving gemfile}i)