hobo-inviqa 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -0
- data/Gemfile.lock +93 -0
- data/Guardfile +14 -0
- data/Hobofile +34 -0
- data/Rakefile +2 -0
- data/bin/hobo +23 -0
- data/features/deps.feature +43 -0
- data/features/hobo/basic.feature +30 -0
- data/features/hobo/help.feature +12 -0
- data/features/hobo/subcommands.feature +16 -0
- data/features/seed/plant.feature +64 -0
- data/features/step_definitions/seed.rb +11 -0
- data/features/support/env.rb +6 -0
- data/features/vm.feature +0 -0
- data/hobo.gemspec +37 -0
- data/lib/hobo.rb +44 -0
- data/lib/hobo/cli.rb +185 -0
- data/lib/hobo/config/file.rb +21 -0
- data/lib/hobo/error_handlers/debug.rb +9 -0
- data/lib/hobo/error_handlers/friendly.rb +52 -0
- data/lib/hobo/errors.rb +60 -0
- data/lib/hobo/help_formatter.rb +111 -0
- data/lib/hobo/helper/file_locator.rb +39 -0
- data/lib/hobo/helper/shell.rb +59 -0
- data/lib/hobo/lib/seed/project.rb +41 -0
- data/lib/hobo/lib/seed/replacer.rb +57 -0
- data/lib/hobo/lib/seed/seed.rb +43 -0
- data/lib/hobo/metadata.rb +28 -0
- data/lib/hobo/patches/rake.rb +56 -0
- data/lib/hobo/patches/slop.rb +22 -0
- data/lib/hobo/paths.rb +49 -0
- data/lib/hobo/tasks/debug.rb +22 -0
- data/lib/hobo/tasks/deps.rb +45 -0
- data/lib/hobo/tasks/seed.rb +43 -0
- data/lib/hobo/tasks/tools.rb +13 -0
- data/lib/hobo/tasks/vm.rb +49 -0
- data/lib/hobo/ui.rb +96 -0
- data/lib/hobo/util.rb +7 -0
- data/lib/hobo/version.rb +3 -0
- data/spec/hobo/cli_spec.rb +135 -0
- data/spec/hobo/config/file_spec.rb +48 -0
- data/spec/hobo/error_handlers/debug_spec.rb +10 -0
- data/spec/hobo/error_handlers/friendly_spec.rb +81 -0
- data/spec/hobo/error_spec.rb +0 -0
- data/spec/hobo/help_formatter_spec.rb +131 -0
- data/spec/hobo/helpers/file_locator_spec.rb +7 -0
- data/spec/hobo/helpers/shell_spec.rb +7 -0
- data/spec/hobo/lib/seed/project_spec.rb +83 -0
- data/spec/hobo/lib/seed/replacer_spec.rb +47 -0
- data/spec/hobo/lib/seed/seed_spec.rb +95 -0
- data/spec/hobo/metadata_spec.rb +46 -0
- data/spec/hobo/patches/rake_spec.rb +0 -0
- data/spec/hobo/paths_spec.rb +77 -0
- data/spec/hobo/ui_spec.rb +64 -0
- data/spec/spec_helper.rb +6 -0
- metadata +355 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
namespace :tools do
|
2
|
+
task :composer do
|
3
|
+
bin_file = File.join(Hobo.project_bin_path, "composer.phar")
|
4
|
+
unless File.exists?(bin_file)
|
5
|
+
Hobo.ui.success "Getting composer.phar"
|
6
|
+
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
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
desc "VM related commands"
|
2
|
+
project_only
|
3
|
+
namespace :vm do
|
4
|
+
def vagrantfile &block
|
5
|
+
locate("*Vagrantfile", missing: "No Vagrantfile found") do
|
6
|
+
yield
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Start VM"
|
11
|
+
task :start => [ 'deps:gems', 'deps:chef', 'deps:composer', 'vm:up', 'vm:start' ]
|
12
|
+
|
13
|
+
desc "Stop VM"
|
14
|
+
task :stop do
|
15
|
+
vagrantfile do
|
16
|
+
Hobo.ui.title "Stopping VM"
|
17
|
+
bundle_shell "vagrant", "suspend", "--color", realtime: true, indent: 2
|
18
|
+
Hobo.ui.separator
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Rebuild VM"
|
23
|
+
task :rebuild => [ 'vm:destroy', 'vm:start' ]
|
24
|
+
|
25
|
+
desc "Destroy VM"
|
26
|
+
task :destroy do
|
27
|
+
vagrantfile do
|
28
|
+
Hobo.ui.title "Stopping VM"
|
29
|
+
bundle_shell "vagrant", "destroy", "--color", realtime: true, indent: 2
|
30
|
+
Hobo.ui.separator
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
task :up do
|
35
|
+
vagrantfile do
|
36
|
+
Hobo.ui.title "Starting vagrant VM"
|
37
|
+
bundle_shell "vagrant", "up", "--no-provision", "--color", realtime: true, indent: 2
|
38
|
+
Hobo.ui.separator
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
task :provision do
|
43
|
+
vagrantfile do
|
44
|
+
Hobo.ui.title "Provisioning VM"
|
45
|
+
bundle_shell "vagrant", "provision", "--color", realtime: true, indent: 2
|
46
|
+
Hobo.ui.separator
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/hobo/ui.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'highline'
|
2
|
+
|
3
|
+
module Hobo
|
4
|
+
class << self
|
5
|
+
attr_accessor :ui
|
6
|
+
end
|
7
|
+
|
8
|
+
class Ui
|
9
|
+
attr_accessor :interactive
|
10
|
+
|
11
|
+
def initialize out = $stdout, error = $stderr
|
12
|
+
colors = HighLine::ColorScheme.new do |cs|
|
13
|
+
cs[:debug] = [ ]
|
14
|
+
cs[:info] = [ ]
|
15
|
+
cs[:warning] = [ :yellow ]
|
16
|
+
cs[:error] = [ :red ]
|
17
|
+
cs[:success] = [ :green ]
|
18
|
+
cs[:opt] = [ :green ]
|
19
|
+
cs[:command] = [:green ]
|
20
|
+
cs[:special] = [ :blue ]
|
21
|
+
cs[:title] = [ :green ]
|
22
|
+
cs[:help_title] = [ :yellow ]
|
23
|
+
cs[:description] = [ :bold ]
|
24
|
+
end
|
25
|
+
|
26
|
+
HighLine.color_scheme = colors
|
27
|
+
|
28
|
+
@out = ::HighLine.new $stdin, out
|
29
|
+
@error = ::HighLine.new $stdin, error
|
30
|
+
end
|
31
|
+
|
32
|
+
def color_scheme scheme = nil
|
33
|
+
HighLine.color_scheme = scheme if scheme
|
34
|
+
HighLine.color_scheme
|
35
|
+
end
|
36
|
+
|
37
|
+
def ask question, opts = {}
|
38
|
+
unless Hobo.ui.interactive
|
39
|
+
raise Hobo::NonInteractive.new(question) if opts[:default].nil?
|
40
|
+
return opts[:default]
|
41
|
+
end
|
42
|
+
|
43
|
+
question = "#{question} [#{opts[:default]}]" if opts[:default]
|
44
|
+
question += ": "
|
45
|
+
begin
|
46
|
+
answer = @out.ask(question) do |q|
|
47
|
+
q.validate = opts[:validate] if opts[:validate]
|
48
|
+
q.readline
|
49
|
+
end
|
50
|
+
answer.strip.empty? ? opts[:default] : answer.strip
|
51
|
+
rescue EOFError
|
52
|
+
Hobo.ui.info ""
|
53
|
+
""
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def separator
|
58
|
+
info ""
|
59
|
+
end
|
60
|
+
|
61
|
+
def color *args
|
62
|
+
@out.color *args
|
63
|
+
end
|
64
|
+
|
65
|
+
def debug message
|
66
|
+
say @out, message, :debug
|
67
|
+
end
|
68
|
+
|
69
|
+
def info message
|
70
|
+
say @out, message, :info
|
71
|
+
end
|
72
|
+
|
73
|
+
def warning message
|
74
|
+
say @error, message, :warning
|
75
|
+
end
|
76
|
+
|
77
|
+
def error message
|
78
|
+
say @error, message, :error
|
79
|
+
end
|
80
|
+
|
81
|
+
def success message
|
82
|
+
say @out, message, :success
|
83
|
+
end
|
84
|
+
|
85
|
+
def title message
|
86
|
+
say @out, message, :title
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def say channel, message, color
|
92
|
+
return if message.nil?
|
93
|
+
channel.say(color ? channel.color(message, color) : message)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/lib/hobo/util.rb
ADDED
data/lib/hobo/version.rb
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
require 'hobo/metadata'
|
4
|
+
require 'hobo/patches/rake'
|
5
|
+
require 'hobo/patches/slop'
|
6
|
+
|
7
|
+
require 'hobo/errors'
|
8
|
+
require 'hobo/cli'
|
9
|
+
|
10
|
+
|
11
|
+
describe Hobo::Cli do
|
12
|
+
cli = nil
|
13
|
+
help = nil
|
14
|
+
|
15
|
+
before do
|
16
|
+
Rake::Task.tasks.each do |task|
|
17
|
+
task.clear
|
18
|
+
end
|
19
|
+
Hobo.ui = double(Hobo::Ui).as_null_object
|
20
|
+
help = double(Hobo::HelpFormatter).as_null_object
|
21
|
+
cli = Hobo::Cli.new help: help
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "hobofile" do
|
25
|
+
it "should load the hobofile if present" do
|
26
|
+
cli.start []
|
27
|
+
Rake::Task["test:non-interactive"].should_not be nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "command mapping" do
|
32
|
+
it "should set command map on help formatter" do
|
33
|
+
help.should_recieve('command_map=')
|
34
|
+
cli.start ["test", "subcommand"]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "metadata" do
|
39
|
+
it "should propagate description metadata" do
|
40
|
+
map = nil
|
41
|
+
allow(help).to receive("command_map=") { |i| map = i }
|
42
|
+
cli.start []
|
43
|
+
map["test:metadata"].description.should match "description"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should propagate long description metadata" do
|
47
|
+
map = nil
|
48
|
+
allow(help).to receive("command_map=") { |i| map = i }
|
49
|
+
cli.start []
|
50
|
+
map["test:metadata"].long_description.should match "long description"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should propagate arg list metadata" do
|
54
|
+
map = nil
|
55
|
+
allow(help).to receive("command_map=") { |i| map = i }
|
56
|
+
cli.start []
|
57
|
+
expect(map["test:metadata"].arg_list).to eq [ :arg ]
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should propagate option metadata" do
|
61
|
+
map = nil
|
62
|
+
allow(help).to receive("command_map=") { |i| map = i }
|
63
|
+
cli.start []
|
64
|
+
map["test:metadata"].options.length.should be 2
|
65
|
+
expect(map["test:metadata"].options.map(&:short)).to eq [ 'o', 'h' ]
|
66
|
+
expect(map["test:metadata"].options.map(&:long)).to eq [ 'option', 'help' ]
|
67
|
+
expect(map["test:metadata"].options.map(&:description)).to eq [ 'Option description', 'Display help' ]
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should propagate hidden metadata" do
|
71
|
+
map = nil
|
72
|
+
allow(help).to receive("command_map=") { |i| map = i }
|
73
|
+
cli.start []
|
74
|
+
map["test:metadata"].hidden.should be true
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "global options" do
|
79
|
+
it "should set non-interactive mode in ui if --non-interactive" do
|
80
|
+
Hobo.ui.should_receive('interactive=').with(false)
|
81
|
+
cli.start(['--non-interactive'])
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "invocation" do
|
86
|
+
it "should show help if no args or opts passed" do
|
87
|
+
help.should_receive(:help)
|
88
|
+
cli.start([])
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should show help for --help" do
|
92
|
+
help.should_receive(:help)
|
93
|
+
cli.start ["--help"]
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should execute a top level command" do
|
97
|
+
Hobo.ui.should_recieve(:info).with("top level")
|
98
|
+
cli.start ["top-level"]
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should execute a subcommand" do
|
102
|
+
Hobo.ui.should_recieve(:info).with("Subcommand test")
|
103
|
+
cli.start ["test", "subcommand"]
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should show help for a namespace" do
|
107
|
+
help.should_receive(:help).with(all: nil, target: "test")
|
108
|
+
cli.start ["test"]
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should show command help for --help" do
|
112
|
+
help.should_receive(:help).with(all: nil, target: "test:subcommand")
|
113
|
+
cli.start ["test", "subcommand", "--help"]
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should propagate --all option to help" do
|
117
|
+
help.should_receive(:help).with(all: true, target: "test")
|
118
|
+
cli.start ["test", "--all"]
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should propagate command opts to command" do
|
122
|
+
Hobo.ui.should_receive(:info).with("1234")
|
123
|
+
cli.start ["test", "option-test", "--testing=1234"]
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should propagate arguments to command" do
|
127
|
+
Hobo.ui.should_receive(:info).with("1234")
|
128
|
+
cli.start ["test", "argument-test", "1234"]
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should raise an exception if not enough arguments were passed" do
|
132
|
+
expect { cli.start(["test", "metadata"]) }.to raise_error Hobo::MissingArgumentsError
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'hobo/paths'
|
3
|
+
require 'hobo/config/file'
|
4
|
+
|
5
|
+
describe Hobo::Config::File do
|
6
|
+
before do
|
7
|
+
Hobo.project_path = nil
|
8
|
+
FakeFS.activate!
|
9
|
+
end
|
10
|
+
|
11
|
+
after do
|
12
|
+
FakeFS::FileSystem.clear
|
13
|
+
FakeFS.deactivate!
|
14
|
+
end
|
15
|
+
|
16
|
+
def fake_config
|
17
|
+
{
|
18
|
+
:string => "string",
|
19
|
+
:integer => 0,
|
20
|
+
:boolean => true,
|
21
|
+
:hash => { :test => true },
|
22
|
+
:array => [ 1 ]
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "save" do
|
27
|
+
it "should save config hash to specified file" do
|
28
|
+
Hobo::Config::File.save "test.yaml", fake_config
|
29
|
+
File.read("test.yaml").should match /string: string/
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "load" do
|
34
|
+
it "should load config hash from file" do
|
35
|
+
Hobo::Config::File.save "test.yaml", fake_config
|
36
|
+
fake_config().should eq Hobo::Config::File.load("test.yaml")
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should return empty hash if file does not exist" do
|
40
|
+
Hobo::Config::File.load("test.yaml").should eq({})
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should raise error if file can't be parsed" do
|
44
|
+
File.write("test.yaml", "##Invalid yaml file")
|
45
|
+
expect { Hobo::Config::File.load("test.yaml") }.to raise_error(RuntimeError, "Invalid hobo configuration (test.yaml)")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'hobo/error_handlers/debug'
|
2
|
+
|
3
|
+
describe Hobo::ErrorHandlers::Debug do
|
4
|
+
describe "handle" do
|
5
|
+
it "should re-raise the error" do
|
6
|
+
exception = Exception.new
|
7
|
+
expect { Hobo::ErrorHandlers::Debug.new.handle(exception) }.to raise_error exception
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'hobo/error_handlers/friendly'
|
2
|
+
require 'hobo/ui'
|
3
|
+
|
4
|
+
describe Hobo::ErrorHandlers::Friendly do
|
5
|
+
before do
|
6
|
+
Hobo.ui = double(Hobo::Ui.new).as_null_object
|
7
|
+
FakeFS.activate!
|
8
|
+
FileUtils.mkdir '/tmp'
|
9
|
+
end
|
10
|
+
|
11
|
+
after do
|
12
|
+
FakeFS::FileSystem.clear
|
13
|
+
FakeFS.deactivate!
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "handle" do
|
17
|
+
it "should display specialized error for Interrupt" do
|
18
|
+
error = Interrupt.new
|
19
|
+
Hobo.ui.should_receive(:warning).with(/Caught Interrupt/)
|
20
|
+
Hobo::ErrorHandlers::Friendly.new.handle(error)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should display specialized error for an external command error" do
|
24
|
+
File.write("temp_log", "command output")
|
25
|
+
output = Struct.new(:path).new
|
26
|
+
output.path = "temp_log"
|
27
|
+
error = Hobo::ExternalCommandError.new("command", 128, output)
|
28
|
+
Hobo.ui.should_receive(:error).with(/The following external command appears to have failed \(exit status 128\)/)
|
29
|
+
Hobo::ErrorHandlers::Friendly.new.handle(error)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should write command output to /tmp/hobo_error.log for external command error" do
|
33
|
+
File.write("temp_log", "command output")
|
34
|
+
output = Struct.new(:path).new
|
35
|
+
output.path = "temp_log"
|
36
|
+
error = Hobo::ExternalCommandError.new("command", 128, output)
|
37
|
+
Hobo::ErrorHandlers::Friendly.new.handle(error)
|
38
|
+
File.read(File.join(Dir.tmpdir, 'hobo_error.log')).should match "command output"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should display specialized error for invalid command or opt error" do
|
42
|
+
error = Hobo::InvalidCommandOrOpt.new("command")
|
43
|
+
Hobo.ui.should_receive(:error).with(/Invalid command or option specified: 'command'/)
|
44
|
+
Hobo::ErrorHandlers::Friendly.new.handle(error)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should display specialized error for missing argument error" do
|
48
|
+
error = Hobo::MissingArgumentsError.new("command", ["arg1"])
|
49
|
+
Hobo.ui.should_receive(:error).with(/Not enough arguments for command/)
|
50
|
+
Hobo::ErrorHandlers::Friendly.new.handle(error)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should display specialized error for user error" do
|
54
|
+
error = Hobo::UserError.new("user error")
|
55
|
+
Hobo.ui.should_receive(:error).with(/user error/)
|
56
|
+
Hobo::ErrorHandlers::Friendly.new.handle(error)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should display generic error for other exception" do
|
60
|
+
error = nil
|
61
|
+
begin
|
62
|
+
raise Exception.new("general error")
|
63
|
+
rescue Exception => error
|
64
|
+
end
|
65
|
+
|
66
|
+
Hobo.ui.should_receive(:error).with(/An unexpected error has occured/)
|
67
|
+
Hobo::ErrorHandlers::Friendly.new.handle(error)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should write error backtrace to /tmp/hobo_error.log for other exception" do
|
71
|
+
error = nil
|
72
|
+
begin
|
73
|
+
raise Exception.new("general error")
|
74
|
+
rescue Exception => error
|
75
|
+
end
|
76
|
+
|
77
|
+
Hobo::ErrorHandlers::Friendly.new.handle(error)
|
78
|
+
File.read(File.join(Dir.tmpdir, 'hobo_error.log')).should match /\(Exception\) general error/
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|