hobo-inviqa 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.editorconfig +10 -0
- data/Gemfile.lock +19 -4
- data/Guardfile +2 -2
- data/Hobofile +5 -1
- data/README.md +8 -32
- data/bin/hobo +12 -18
- data/hobo.gemspec +3 -0
- data/lib/hobo.rb +8 -1
- data/lib/hobo/cli.rb +14 -3
- data/lib/hobo/error_handlers/debug.rb +5 -2
- data/lib/hobo/error_handlers/exit_code_map.rb +16 -0
- data/lib/hobo/error_handlers/friendly.rb +8 -8
- data/lib/hobo/errors.rb +11 -1
- data/lib/hobo/helper/http_download.rb +41 -0
- data/lib/hobo/helper/shell.rb +3 -2
- data/lib/hobo/helper/vm_command.rb +235 -14
- data/lib/hobo/lib/host_check.rb +20 -6
- data/lib/hobo/lib/host_check/deps.rb +22 -4
- data/lib/hobo/lib/host_check/git.rb +41 -17
- data/lib/hobo/lib/host_check/ruby.rb +30 -20
- data/lib/hobo/lib/host_check/vagrant.rb +37 -6
- data/lib/hobo/lib/s3sync.rb +22 -44
- data/lib/hobo/lib/seed/project.rb +10 -6
- data/lib/hobo/patches/slop.rb +21 -2
- data/lib/hobo/tasks/assets.rb +12 -15
- data/lib/hobo/tasks/config.rb +15 -0
- data/lib/hobo/tasks/deps.rb +37 -6
- data/lib/hobo/tasks/system.rb +15 -0
- data/lib/hobo/tasks/system/completions.rb +76 -0
- data/lib/hobo/tasks/tools.rb +10 -6
- data/lib/hobo/tasks/vm.rb +64 -11
- data/lib/hobo/ui.rb +27 -10
- data/lib/hobo/util.rb +36 -2
- data/lib/hobo/version.rb +2 -2
- data/spec/hobo/asset_applicator_spec.rb +2 -2
- data/spec/hobo/cli_spec.rb +40 -24
- data/spec/hobo/config/file_spec.rb +1 -3
- data/spec/hobo/error_handlers/debug_spec.rb +39 -5
- data/spec/hobo/error_handlers/friendly_spec.rb +38 -21
- data/spec/hobo/help_formatter_spec.rb +3 -3
- data/spec/hobo/helpers/file_locator_spec.rb +2 -2
- data/spec/hobo/helpers/shell_spec.rb +2 -2
- data/spec/hobo/helpers/vm_command_spec.rb +54 -21
- data/spec/hobo/lib/s3sync_spec.rb +6 -3
- data/spec/hobo/lib/seed/project_spec.rb +2 -3
- data/spec/hobo/lib/seed/replacer_spec.rb +1 -2
- data/spec/hobo/lib/seed/seed_spec.rb +2 -3
- data/spec/hobo/logging_spec.rb +2 -2
- data/spec/hobo/metadata_spec.rb +2 -2
- data/spec/hobo/null_spec.rb +2 -2
- data/spec/hobo/paths_spec.rb +1 -2
- data/spec/hobo/ui_spec.rb +104 -20
- data/spec/hobo/util_spec.rb +75 -0
- data/spec/spec_helper.rb +1 -0
- metadata +55 -46
- 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
|
data/lib/hobo/tasks/deps.rb
CHANGED
@@ -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
|
-
|
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
|
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
|
data/lib/hobo/tasks/tools.rb
CHANGED
@@ -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
|
9
|
+
Hobo.ui.success "Getting composer"
|
6
10
|
FileUtils.mkdir_p File.dirname(bin_file)
|
7
|
-
|
8
|
-
|
9
|
-
|
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', '
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
59
|
-
|
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
|
-
|
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
|
27
|
+
def initialize input = $stdin, output = $stdout, error = $stderr
|
26
28
|
HighLine.color_scheme = HighLine::ColorScheme.new COLORS
|
27
|
-
@
|
28
|
-
@
|
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
|
-
|
43
|
-
|
44
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|