-
Notifications
You must be signed in to change notification settings - Fork 106
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
(SDK-261) Manage basic bundler operations for module dev #62
Changes from all commits
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 |
---|---|---|
@@ -0,0 +1,139 @@ | ||
require 'bundler' | ||
require 'tty-spinner' | ||
require 'pdk/util' | ||
require 'pdk/cli/exec' | ||
|
||
module PDK | ||
module Util | ||
module Bundler | ||
class BundleHelper; end | ||
|
||
def self.ensure_bundle! | ||
bundle = BundleHelper.new | ||
|
||
if bundle.has_gemfile? | ||
if !bundle.locked? | ||
unless bundle.lock! | ||
raise PDK::CLI::FatalError, _("Unable to resolve Gemfile dependencies.") | ||
end | ||
end | ||
|
||
if !bundle.installed? | ||
unless bundle.install! | ||
raise PDK::CLI::FatalError, _("Unable to install missing Gemfile dependencies.") | ||
end | ||
end | ||
end | ||
end | ||
|
||
class BundleHelper | ||
def has_gemfile? | ||
# return a pure boolean | ||
!!gemfile | ||
end | ||
|
||
def locked? | ||
# return a pure boolean | ||
!!gemfile_lock | ||
end | ||
|
||
def installed? | ||
output_start(_("Checking for missing Gemfile dependencies")) | ||
|
||
result = invoke('check', "--gemfile=#{gemfile}", "--path=#{bundle_cachedir}") | ||
|
||
output_end(:success) | ||
|
||
return result[:exit_code] == 0 | ||
end | ||
|
||
def lock! | ||
output_start(_("Resolving Gemfile dependencies")) | ||
|
||
result = invoke('lock') | ||
|
||
if result[:exit_code] == 0 | ||
output_end(:success) | ||
else | ||
output_end(:failure) | ||
$stderr.puts result[:stdout] | ||
$stderr.puts result[:stderr] | ||
end | ||
|
||
return result[:exit_code] == 0 | ||
end | ||
|
||
def install! | ||
output_start(_("Installing missing Gemfile dependencies")) | ||
|
||
result = invoke('install', "--gemfile=#{gemfile}", "--path=#{bundle_cachedir}") | ||
|
||
if result[:exit_code] == 0 | ||
output_end(:success) | ||
else | ||
output_end(:failure) | ||
$stderr.puts result[:stdout] | ||
$stderr.puts result[:stderr] | ||
end | ||
|
||
return result[:exit_code] == 0 | ||
end | ||
|
||
private | ||
|
||
def invoke(*args) | ||
::Bundler.with_clean_env do | ||
PDK::CLI::Exec.bundle(*args) | ||
end | ||
end | ||
|
||
def find_upwards(target) | ||
previous = nil | ||
current = File.expand_path(Dir.pwd) | ||
|
||
until !File.directory?(current) || current == previous | ||
filename = File.join(current, target) | ||
return filename if File.file?(filename) | ||
current, previous = File.expand_path("..", current), current | ||
end | ||
end | ||
|
||
def gemfile | ||
@gemfile ||= find_upwards('Gemfile') | ||
end | ||
|
||
def gemfile_lock | ||
@gemfile_lock ||= find_upwards('Gemfile.lock') | ||
end | ||
|
||
def bundle_cachedir | ||
@bundle_cachedir ||= File.join(PDK::Util.cachedir, 'bundler') | ||
end | ||
|
||
# These two output_* methods are just a way to not try to do the spinner stuff on Windows for now. | ||
def output_start(message) | ||
if Gem.win_platform? | ||
$stderr.print "#{message}... " | ||
else | ||
@spinner = TTY::Spinner.new("[:spinner] #{message}") | ||
@spinner.auto_spin | ||
end | ||
end | ||
|
||
def output_end(state) | ||
if Gem.win_platform? | ||
$stderr.print (state == :success) ? _("done.\n") : _("FAILURE!\n") | ||
else | ||
if state == :success | ||
@spinner.success | ||
else | ||
@spinner.error | ||
end | ||
|
||
remove_instance_variable(:@spinner) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,8 @@ | ||
require 'spec_helper_acceptance' | ||
|
||
describe 'Basic usage of the CLI' do | ||
context 'when the --help options is used' do | ||
let(:help_output) { shell_ex("#{path_to_pdk} --help") } | ||
|
||
it 'displays help text on stdout' do | ||
expect(help_output.stdout).to match(/NAME.*USAGE.*DESCRIPTION.*COMMANDS.*OPTIONS/m) | ||
end | ||
|
||
it 'has an empty stderr' do | ||
expect(help_output.stderr).to eq('') | ||
end | ||
describe command("#{path_to_pdk} --help") do | ||
its(:stdout) { is_expected.to match(/NAME.*USAGE.*DESCRIPTION.*COMMANDS.*OPTIONS/m) } | ||
its(:stderr) { is_expected.to match(/\A\Z/) } | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
require 'spec_helper' | ||
|
||
RSpec.describe PDK::Util::Bundler do | ||
describe '.ensure_bundle!' do | ||
context 'when there is no Gemfile' do | ||
before(:each) do | ||
allow(File).to receive(:file?).with(/Gemfile$/).and_return(false) | ||
end | ||
|
||
it 'does nothing' do | ||
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. In which situations do you expect this to be the case? 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. Well, technically a puppet module doesn't have to have a Gemfile right? Theoretically somebody could still use 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. Yes, technically no Gemfile is required. Practically, all well-maintained do. The goal is to provide a template so that For less well maintained modules, having a 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 guess we just need to figure out how the most graceful way to handle the lack of a Gemfile is. We can change the method name to something like |
||
expect(PDK::CLI::Exec).to_not receive(:bundle) | ||
|
||
PDK::Util::Bundler.ensure_bundle! | ||
end | ||
end | ||
|
||
context 'when there is no Gemfile.lock' do | ||
before(:each) do | ||
allow(File).to receive(:file?).with(/Gemfile$/).and_return(true) | ||
allow(File).to receive(:file?).with(/Gemfile\.lock$/).and_return(false) | ||
allow(PDK::CLI::Exec).to receive(:bundle).with('check', any_args).and_return({exit_code: 1}) | ||
allow(PDK::CLI::Exec).to receive(:bundle).with('install', any_args).and_return({exit_code: 0}) | ||
end | ||
|
||
it 'generates Gemfile.lock' do | ||
expect(PDK::CLI::Exec).to receive(:bundle).with('lock', any_args).and_return({exit_code: 0}) | ||
|
||
expect { PDK::Util::Bundler.ensure_bundle! }.to output(/resolving gemfile/i).to_stderr | ||
end | ||
end | ||
|
||
context 'when there are missing gems' do | ||
before(:each) do | ||
allow(File).to receive(:file?).with(/Gemfile$/).and_return(true) | ||
allow(File).to receive(:file?).with(/Gemfile\.lock$/).and_return(true) | ||
allow(PDK::CLI::Exec).to receive(:bundle).with('check', any_args).and_return({exit_code: 1}) | ||
end | ||
|
||
it 'installs missing gems' do | ||
expect(PDK::CLI::Exec).to receive(:bundle).with('install', any_args).and_return({exit_code: 0}) | ||
|
||
expect { PDK::Util::Bundler.ensure_bundle! }.to output(/installing missing gemfile/i).to_stderr | ||
end | ||
end | ||
|
||
context 'when there are no missing gems' do | ||
before(:each) do | ||
allow(File).to receive(:file?).with(/Gemfile$/).and_return(true) | ||
allow(File).to receive(:file?).with(/Gemfile\.lock$/).and_return(true) | ||
end | ||
|
||
it 'checks for missing but does not install anything' do | ||
expect(PDK::CLI::Exec).to receive(:bundle).with('check', any_args).and_return({exit_code: 0}) | ||
expect(PDK::CLI::Exec).to_not receive(:bundle).with('install', any_args) | ||
|
||
expect { PDK::Util::Bundler.ensure_bundle! }.to output(/checking for missing/i).to_stderr | ||
end | ||
end | ||
end | ||
end |
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.
note that this was always logging this message even when the vendored bin was being used :)
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.
d'oh