hobo-inviqa 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. checksums.yaml +15 -0
  2. data/.editorconfig +10 -0
  3. data/Gemfile.lock +19 -4
  4. data/Guardfile +2 -2
  5. data/Hobofile +5 -1
  6. data/README.md +8 -32
  7. data/bin/hobo +12 -18
  8. data/hobo.gemspec +3 -0
  9. data/lib/hobo.rb +8 -1
  10. data/lib/hobo/cli.rb +14 -3
  11. data/lib/hobo/error_handlers/debug.rb +5 -2
  12. data/lib/hobo/error_handlers/exit_code_map.rb +16 -0
  13. data/lib/hobo/error_handlers/friendly.rb +8 -8
  14. data/lib/hobo/errors.rb +11 -1
  15. data/lib/hobo/helper/http_download.rb +41 -0
  16. data/lib/hobo/helper/shell.rb +3 -2
  17. data/lib/hobo/helper/vm_command.rb +235 -14
  18. data/lib/hobo/lib/host_check.rb +20 -6
  19. data/lib/hobo/lib/host_check/deps.rb +22 -4
  20. data/lib/hobo/lib/host_check/git.rb +41 -17
  21. data/lib/hobo/lib/host_check/ruby.rb +30 -20
  22. data/lib/hobo/lib/host_check/vagrant.rb +37 -6
  23. data/lib/hobo/lib/s3sync.rb +22 -44
  24. data/lib/hobo/lib/seed/project.rb +10 -6
  25. data/lib/hobo/patches/slop.rb +21 -2
  26. data/lib/hobo/tasks/assets.rb +12 -15
  27. data/lib/hobo/tasks/config.rb +15 -0
  28. data/lib/hobo/tasks/deps.rb +37 -6
  29. data/lib/hobo/tasks/system.rb +15 -0
  30. data/lib/hobo/tasks/system/completions.rb +76 -0
  31. data/lib/hobo/tasks/tools.rb +10 -6
  32. data/lib/hobo/tasks/vm.rb +64 -11
  33. data/lib/hobo/ui.rb +27 -10
  34. data/lib/hobo/util.rb +36 -2
  35. data/lib/hobo/version.rb +2 -2
  36. data/spec/hobo/asset_applicator_spec.rb +2 -2
  37. data/spec/hobo/cli_spec.rb +40 -24
  38. data/spec/hobo/config/file_spec.rb +1 -3
  39. data/spec/hobo/error_handlers/debug_spec.rb +39 -5
  40. data/spec/hobo/error_handlers/friendly_spec.rb +38 -21
  41. data/spec/hobo/help_formatter_spec.rb +3 -3
  42. data/spec/hobo/helpers/file_locator_spec.rb +2 -2
  43. data/spec/hobo/helpers/shell_spec.rb +2 -2
  44. data/spec/hobo/helpers/vm_command_spec.rb +54 -21
  45. data/spec/hobo/lib/s3sync_spec.rb +6 -3
  46. data/spec/hobo/lib/seed/project_spec.rb +2 -3
  47. data/spec/hobo/lib/seed/replacer_spec.rb +1 -2
  48. data/spec/hobo/lib/seed/seed_spec.rb +2 -3
  49. data/spec/hobo/logging_spec.rb +2 -2
  50. data/spec/hobo/metadata_spec.rb +2 -2
  51. data/spec/hobo/null_spec.rb +2 -2
  52. data/spec/hobo/paths_spec.rb +1 -2
  53. data/spec/hobo/ui_spec.rb +104 -20
  54. data/spec/hobo/util_spec.rb +75 -0
  55. data/spec/spec_helper.rb +1 -0
  56. metadata +55 -46
  57. data/lib/hobo/tasks/host.rb +0 -19
@@ -0,0 +1,15 @@
1
+ desc "Configure hobo"
2
+ task :config do
3
+ config = Hobo.user_config
4
+
5
+ # Not required at present
6
+ # config.full_name = Hobo.ui.ask("Full name", :default => config.full_name).to_s
7
+ # config.email = Hobo.ui.ask("Email", :default => config.email).to_s
8
+
9
+ config[:aws] ||= {}
10
+ config.aws.access_key_id = Hobo.ui.ask("AWS access key ID", :default => config.aws.access_key_id).to_s
11
+ config.aws.secret_access_key = Hobo.ui.ask("AWS secret access key", :default => config.aws.secret_access_key).to_s
12
+
13
+ Hobo::Config::File.save(Hobo.user_config_file, config)
14
+ File.chmod(0600, Hobo.user_config_file)
15
+ end
@@ -21,10 +21,30 @@ namespace :deps do
21
21
  Rake::Task["tools:composer"].invoke
22
22
  Hobo.ui.title "Installing composer dependencies"
23
23
  Dir.chdir Hobo.project_path do
24
- shell "php", File.join(Hobo.project_bin_path, 'composer.phar'), "install", "--ansi", realtime: true, indent: 2
24
+ ansi = Hobo.ui.supports_color? ? '--ansi' : ''
25
+ args = [ "php bin/composer.phar install #{ansi} --prefer-dist", { realtime: true, indent: 2 } ]
26
+ complete = false
27
+
28
+ check = Hobo::Lib::HostCheck.check(:filter => /php_present/)
29
+
30
+ if check["Php present"] == :ok
31
+ begin
32
+ shell *args
33
+ complete = true
34
+ rescue Hobo::ExternalCommandError
35
+ Hobo.ui.warning "Installing composer dependencies locally failed!"
36
+ end
37
+ end
38
+
39
+ if !complete
40
+ vm_shell *args
41
+ end
42
+
43
+ Hobo.ui.success "Composer dependencies installed"
25
44
  end
45
+
46
+ Hobo.ui.separator
26
47
  end
27
- Hobo.ui.separator
28
48
  end
29
49
 
30
50
  desc "Install vagrant plugins"
@@ -32,9 +52,11 @@ namespace :deps do
32
52
  plugins = shell "vagrant plugin list", :capture => true
33
53
  locate "*Vagrantfile" do
34
54
  File.read("Vagrantfile").split("\n").each do |line|
55
+ next if line.match /^\s*#/
35
56
  next unless line.match /Vagrant\.require_plugin (.*)/
36
57
  plugin = $1.gsub(/['"]*/, '')
37
58
  next if plugins.include? "#{plugin} "
59
+
38
60
  Hobo.ui.title "Installing vagrant plugin: #{plugin}"
39
61
  bundle_shell "vagrant", "plugin", "install", plugin, :realtime => true, :indent => 2
40
62
  Hobo.ui.separator
@@ -45,13 +67,22 @@ namespace :deps do
45
67
  desc "Install chef dependencies"
46
68
  task :chef => [ "deps:gems" ] do
47
69
  locate "*Cheffile" do
48
- Hobo.ui.title "Installing chef dependencies"
70
+ Hobo.ui.title "Installing chef dependencies via librarian"
49
71
  Bundler.with_clean_env do
50
- bundle_shell "librarian-chef", "install", "--verbose", realtime: true, indent: 2 do |line|
51
- line =~ /Installing.*</ ? line : nil
72
+ bundle_shell "librarian-chef", "install", "--verbose", :realtime => true, :indent => 2 do |line|
73
+ line =~ /Installing.*</ ? line.strip + "\n" : nil
52
74
  end
53
75
  end
54
76
  Hobo.ui.separator
55
77
  end
78
+
79
+ locate "*Berksfile" do
80
+ Hobo.ui.title "Installing chef dependencies via berkshelf"
81
+ Bundler.with_clean_env do
82
+ bundle_shell "berks", "install", :realtime => true, :indent => 2
83
+ bundle_shell "berks", "install", "--path", "cookbooks"
84
+ end
85
+ Hobo.ui.separator
86
+ end
56
87
  end
57
- end
88
+ end
@@ -0,0 +1,15 @@
1
+ desc "System configuration related commands"
2
+ namespace :system do
3
+
4
+ desc "Check system configuration for potential problems"
5
+ task :check do
6
+ Hobo::Lib::HostCheck.check.each do |k,v|
7
+ if v == :ok
8
+ Hobo.ui.success "#{k}: OK"
9
+ else
10
+ Hobo.ui.error "#{k}: FAILED\n"
11
+ Hobo.ui.warning v.advice.gsub(/^/, ' ')
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,76 @@
1
+ desc "System configuration related commands"
2
+ namespace :system do
3
+
4
+ desc "Shell completion related commands"
5
+ namespace :completions do
6
+
7
+ desc "Install shell completion helpers"
8
+ option '-f', '--fish', 'Install completions for FISH'
9
+ option '-b', '--bash', 'Install completions for Bash'
10
+ option '-z', '--zsh', 'Install completions for ZSH'
11
+ task "install" do |task|
12
+ if task.opts[:fish]
13
+ script = <<-EOF
14
+ function __hobo_completion -d "Create hobo completions"
15
+ set -l cache_dir "/tmp/fish_hobo_completion_cache"
16
+ mkdir -p $cache_dir
17
+ set -l hashed_pwd (ruby -r 'digest' -e 'puts Digest::MD5.hexdigest(`pwd`)')
18
+ set -l hobo_cache_file "$cache_dir/$hashed_pwd"
19
+
20
+ if not test -f "$hobo_cache_file"
21
+ hobo system completions fish > "$hobo_cache_file"
22
+ end
23
+
24
+ cat "$hobo_cache_file"
25
+ end
26
+
27
+ function __hobo_scope_test -d "Hobo scoped completion test"
28
+ set cmd (commandline -opc)
29
+ if [ "$cmd" = "$argv" ]
30
+ return 0
31
+ end
32
+ return 1
33
+ end
34
+
35
+ eval (__hobo_completion)
36
+ EOF
37
+ target = File.join(ENV['HOME'], '.config/fish/completions/hobo.fish')
38
+ FileUtils.mkdir_p(File.dirname(target))
39
+ File.write(target, script)
40
+ end
41
+
42
+ if task.opts[:bash]
43
+ raise "Bash completions not yet implemented"
44
+ end
45
+
46
+ if task.opts[:zsh]
47
+ raise "ZSH completions not yet implemented"
48
+ end
49
+ end
50
+
51
+ desc "Display FISH shell completion commands"
52
+ task :fish do
53
+ Hobo.cli.slop.options.each do |option|
54
+ short = option.short.nil? ? '' : "-s #{option.short}"
55
+ long = option.long.nil? ? '' : "-l #{option.long}"
56
+ arg = option.config[:argument] ? '' : '-x'
57
+ puts "complete #{arg} -c hobo #{short} #{long} --description '#{option.description}';"
58
+ end
59
+
60
+ map = Hobo.cli.help_formatter.command_map
61
+ map.each do |k, v|
62
+ next if v.description.nil? || v.description.empty?
63
+ k = k.split(':')
64
+ k.unshift 'hobo'
65
+ c = k.pop
66
+ puts "complete -x -c hobo -n '__hobo_scope_test #{k.join(' ')}' -a #{c} --description '#{v.description}';"
67
+ v.options.each do |option|
68
+ short = option.short.nil? ? '' : "-s #{option.short}"
69
+ long = option.long.nil? ? '' : "-l #{option.long}"
70
+ arg = option.config[:argument] ? '' : '-x'
71
+ puts "complete #{arg} -c hobo -n '__hobo_scope_test #{k.concat([c]).join(' ')}' #{short} #{long} --description '#{option.description}';"
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -1,13 +1,17 @@
1
+ desc "Tasks to retrieve common tools"
2
+ hidden
1
3
  namespace :tools do
4
+
5
+ desc "Fetch composer"
2
6
  task :composer do
3
7
  bin_file = File.join(Hobo.project_bin_path, "composer.phar")
4
8
  unless File.exists?(bin_file)
5
- Hobo.ui.success "Getting composer.phar"
9
+ Hobo.ui.success "Getting composer"
6
10
  FileUtils.mkdir_p File.dirname(bin_file)
7
- Dir.chdir File.dirname(bin_file) do
8
- shell "php", "-r", "eval('?>'.file_get_contents('https://getcomposer.org/installer'));", realtime: true, indent: 2
9
- end
10
- Hobo.ui.separator
11
+ vm_shell "cd bin && php -r \"readfile('https://getcomposer.org/installer');\" | php", :realtime => true, :indent => 2
12
+ else
13
+ Hobo.ui.success "Composer already available in bin/composer.phar"
11
14
  end
15
+ Hobo.ui.separator
12
16
  end
13
- end
17
+ end
data/lib/hobo/tasks/vm.rb CHANGED
@@ -7,14 +7,43 @@ namespace :vm do
7
7
  end
8
8
  end
9
9
 
10
+ def vagrant_exec *args
11
+ opts = { :realtime => true, :indent => 2 }
12
+ color = Hobo.ui.supports_color? ? '--color' : '--no-color'
13
+
14
+ if OS.windows?
15
+ opts[:env] = { 'VAGRANT_HOME' => windows_short(dir) } if ENV['HOME'].match(/\s+/) && !ENV['VAGRANT_HOME']
16
+ end
17
+
18
+ args.unshift 'vagrant'
19
+ args.push color
20
+ args.push opts
21
+
22
+ bundle_shell *args
23
+ end
24
+
25
+ def windows_short dir
26
+ segments = dir.gsub(/\\/, '/').split('/')
27
+ segments.map do |segment|
28
+ if segment.match /\s+/
29
+ # This may fail in some edge cases but better than naught
30
+ # See the following link for the correct solution
31
+ # http://stackoverflow.com/questions/10224572/convert-long-filename-to-short-filename-8-3
32
+ segment.upcase.gsub(/\s+/, '')[0...6] + '~1'
33
+ else
34
+ segment
35
+ end
36
+ end.join('/')
37
+ end
38
+
10
39
  desc "Start & provision VM"
11
- task :up => [ 'deps:chef', 'deps:composer', 'assets:download', 'vm:start', 'vm:provision', 'assets:apply' ]
40
+ task :up => [ 'deps:chef', 'assets:download', 'vm:start', 'vm:provision', 'deps:composer', 'assets:apply' ]
12
41
 
13
42
  desc "Stop VM"
14
43
  task :stop => [ "deps:gems" ] do
15
44
  vagrantfile do
16
45
  Hobo.ui.title "Stopping VM"
17
- bundle_shell "vagrant", "suspend", "--color", realtime: true, indent: 2
46
+ vagrant_exec 'suspend'
18
47
  Hobo.ui.separator
19
48
  end
20
49
  end
@@ -26,7 +55,7 @@ namespace :vm do
26
55
  task :destroy => [ "deps:gems" ] do
27
56
  vagrantfile do
28
57
  Hobo.ui.title "Destroying VM"
29
- bundle_shell "vagrant", "destroy", "--force", "--color", realtime: true, indent: 2
58
+ vagrant_exec 'destroy', '--force'
30
59
  Hobo.ui.separator
31
60
  end
32
61
  end
@@ -35,7 +64,7 @@ namespace :vm do
35
64
  task :start => [ "deps:gems", "deps:vagrant_plugins" ] do
36
65
  vagrantfile do
37
66
  Hobo.ui.title "Starting vagrant VM"
38
- bundle_shell "vagrant", "up", "--no-provision", "--color", realtime: true, indent: 2
67
+ vagrant_exec 'up', '--no-provision'
39
68
  Hobo.ui.separator
40
69
  end
41
70
  end
@@ -44,23 +73,47 @@ namespace :vm do
44
73
  task :provision => [ "deps:gems" ] do
45
74
  vagrantfile do
46
75
  Hobo.ui.title "Provisioning VM"
47
- bundle_shell "vagrant", "provision", "--color", realtime: true, indent: 2
76
+ vagrant_exec 'provision'
48
77
  Hobo.ui.separator
49
78
  end
50
79
  end
51
80
 
52
81
  desc "Open an SSH connection"
53
- task :ssh do
54
- exec vm_command
82
+ task :ssh do |task|
83
+ execute = task.opts[:_unparsed]
84
+ opts = { :psuedo_tty => STDIN.tty? }
85
+
86
+ Hobo.ui.success "Determining VM connection details..." if STDOUT.tty?
87
+ command = execute.empty? ? vm_command(nil, opts) : vm_command(execute, opts)
88
+ Hobo.logger.debug "vm:ssh: #{command}"
89
+
90
+ Hobo.ui.success "Connecting..." if STDOUT.tty?
91
+ exec command
55
92
  end
56
93
 
57
94
  desc "Open a MySQL cli connection"
58
- task :mysql do
59
- exec vm_mysql
95
+ option '-D=', '--db=', 'Database'
96
+ task :mysql do |task|
97
+ opts = { :psuedo_tty => STDIN.tty? }
98
+ opts[:db] = task.opts[:db] if task.opts[:db]
99
+
100
+ Hobo.ui.success "Determining VM connection details..." if STDOUT.tty?
101
+ command = vm_mysql(opts)
102
+ Hobo.logger.debug "vm:mysql: #{command}"
103
+
104
+ Hobo.ui.success "Connecting..." if STDOUT.tty?
105
+ exec command
60
106
  end
61
107
 
62
108
  desc "Open a Redis cli connection"
63
109
  task :redis do
64
- exec vm_command "redis-cli"
110
+ opts = { :psuedo_tty => STDIN.tty? }
111
+
112
+ Hobo.ui.success "Determining VM connection details..." if STDOUT.tty?
113
+ command = vm_command("redis-cli", opts)
114
+ Hobo.logger.debug "vm:redis: #{command}"
115
+
116
+ Hobo.ui.success "Connecting..." if STDOUT.tty?
117
+ exec command
65
118
  end
66
- end
119
+ end
data/lib/hobo/ui.rb CHANGED
@@ -6,6 +6,8 @@ module Hobo
6
6
  end
7
7
 
8
8
  class Ui
9
+ include Hobo::Logging
10
+
9
11
  attr_accessor :interactive
10
12
 
11
13
  COLORS = {
@@ -22,10 +24,12 @@ module Hobo
22
24
  :description => [:bold]
23
25
  }
24
26
 
25
- def initialize out = $stdout, error = $stderr
27
+ def initialize input = $stdin, output = $stdout, error = $stderr
26
28
  HighLine.color_scheme = HighLine::ColorScheme.new COLORS
27
- @out = ::HighLine.new $stdin, out
28
- @error = ::HighLine.new $stdin, error
29
+ @output_io = output
30
+ @out = ::HighLine.new input, output
31
+ @error = ::HighLine.new input, error
32
+ use_color supports_color?
29
33
  end
30
34
 
31
35
  def color_scheme scheme = nil
@@ -33,15 +37,25 @@ module Hobo
33
37
  HighLine.color_scheme
34
38
  end
35
39
 
40
+ def supports_color?
41
+ return @output_io.tty? unless OS.windows?
42
+ return (ENV['ANSICON'] || ENV['TERM'] == 'xterm') && @output_io.tty? # ANSICON or MinTTY && output is TTY
43
+ end
44
+
36
45
  def use_color opt = nil
37
46
  HighLine.use_color = opt unless opt.nil?
38
47
  HighLine.use_color?
39
48
  end
40
49
 
41
50
  def ask question, opts = {}
42
- unless Hobo.ui.interactive
43
- raise Hobo::NonInteractive.new(question) if opts[:default].nil?
44
- return opts[:default]
51
+ opts = {
52
+ :validate => nil,
53
+ :default => nil
54
+ }.merge(opts)
55
+
56
+ unless @interactive
57
+ raise Hobo::NonInteractiveError.new(question) if opts[:default].nil?
58
+ return opts[:default].to_s
45
59
  end
46
60
 
47
61
  question = "#{question} [#{opts[:default]}]" if opts[:default]
@@ -51,7 +65,8 @@ module Hobo
51
65
  q.validate = opts[:validate] if opts[:validate]
52
66
  q.readline
53
67
  end
54
- answer.strip.empty? ? opts[:default] : answer.strip
68
+ answer = answer.to_s
69
+ answer.strip.empty? ? opts[:default].to_s : answer.strip
55
70
  rescue EOFError
56
71
  Hobo.ui.info ""
57
72
  ""
@@ -65,7 +80,7 @@ module Hobo
65
80
  end
66
81
 
67
82
  def separator
68
- info ""
83
+ info(supports_color? ? "" : "\n")
69
84
  end
70
85
 
71
86
  def color *args
@@ -100,7 +115,9 @@ module Hobo
100
115
 
101
116
  def say channel, message, color
102
117
  return if message.nil?
103
- channel.say(color ? channel.color(message, color) : message)
118
+ message = color ? channel.color(message, color) : message
119
+ channel.say(message) unless logger.level <= Logger::DEBUG
120
+ logger.debug(message)
104
121
  end
105
122
  end
106
- end
123
+ end
data/lib/hobo/util.rb CHANGED
@@ -1,7 +1,41 @@
1
+ require 'ruby-progressbar'
2
+
1
3
  module Hobo
2
4
  class << self
5
+
6
+ attr_accessor :project_bar_cache
7
+
3
8
  def in_project?
4
- !Hobo.project_path.nil?
9
+ !!Hobo.project_path
10
+ end
11
+
12
+ def progress file, increment, total, type, opts = {}
13
+ opts = {
14
+ :title => File.basename(file),
15
+ :total => total,
16
+ :format => "%t [%B] %p%% %e"
17
+ }.merge(opts)
18
+
19
+ # Hack to stop newline spam on windows
20
+ opts[:length] = 79 if Gem::win_platform?
21
+
22
+ @progress_bar_cache ||= {}
23
+
24
+ if type == :reset
25
+ type = :update
26
+ @progress_bar_cache.delete file
27
+ end
28
+
29
+ @progress_bar_cache[file] ||= ProgressBar.create(opts)
30
+
31
+ case type
32
+ when :update
33
+ @progress_bar_cache[file].progress += increment
34
+ when :finished
35
+ @progress_bar_cache[file].finish
36
+ end
37
+
38
+ return @progress_bar_cache[file]
5
39
  end
6
40
  end
7
- end
41
+ end