hem 1.0.1.beta1
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.
- checksums.yaml +7 -0
- data/.editorconfig +10 -0
- data/.gitignore +3 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +125 -0
- data/DoD.md +5 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +71 -0
- data/Guardfile +14 -0
- data/Hemfile +43 -0
- data/LICENSE +21 -0
- data/README.md +42 -0
- data/Rakefile +23 -0
- data/bin/hem +64 -0
- data/features/deps.feature +43 -0
- data/features/hem/basic.feature +43 -0
- data/features/hem/help.feature +16 -0
- data/features/hem/subcommands.feature +15 -0
- data/features/seed/plant.feature +64 -0
- data/features/step_definitions/env.rb +6 -0
- data/features/step_definitions/seed.rb +11 -0
- data/features/support/env.rb +6 -0
- data/hem.gemspec +47 -0
- data/lib/hem/asset_applicator.rb +33 -0
- data/lib/hem/asset_applicators/files.rb +5 -0
- data/lib/hem/asset_applicators/sqldump.rb +38 -0
- data/lib/hem/cli.rb +252 -0
- data/lib/hem/config/file.rb +22 -0
- data/lib/hem/config.rb +5 -0
- data/lib/hem/error_handlers/debug.rb +12 -0
- data/lib/hem/error_handlers/exit_code_map.rb +17 -0
- data/lib/hem/error_handlers/friendly.rb +58 -0
- data/lib/hem/errors.rb +89 -0
- data/lib/hem/help_formatter.rb +118 -0
- data/lib/hem/helper/file_locator.rb +44 -0
- data/lib/hem/helper/github.rb +10 -0
- data/lib/hem/helper/http_download.rb +41 -0
- data/lib/hem/helper/shell.rb +101 -0
- data/lib/hem/helper/vm_command.rb +30 -0
- data/lib/hem/lib/github/api.rb +48 -0
- data/lib/hem/lib/github/client.rb +52 -0
- data/lib/hem/lib/host_check/deps.rb +39 -0
- data/lib/hem/lib/host_check/git.rb +76 -0
- data/lib/hem/lib/host_check/ruby.rb +53 -0
- data/lib/hem/lib/host_check/vagrant.rb +45 -0
- data/lib/hem/lib/host_check.rb +34 -0
- data/lib/hem/lib/s3/local/file.rb +40 -0
- data/lib/hem/lib/s3/local/iohandler.rb +36 -0
- data/lib/hem/lib/s3/remote/file.rb +57 -0
- data/lib/hem/lib/s3/remote/iohandler.rb +38 -0
- data/lib/hem/lib/s3/sync.rb +134 -0
- data/lib/hem/lib/seed/project.rb +71 -0
- data/lib/hem/lib/seed/replacer.rb +56 -0
- data/lib/hem/lib/seed/seed.rb +111 -0
- data/lib/hem/lib/self_signed_cert_generator.rb +38 -0
- data/lib/hem/lib/vm/command.rb +131 -0
- data/lib/hem/lib/vm/inspector.rb +73 -0
- data/lib/hem/logging.rb +20 -0
- data/lib/hem/metadata.rb +42 -0
- data/lib/hem/null.rb +31 -0
- data/lib/hem/patches/deepstruct.rb +21 -0
- data/lib/hem/patches/rake.rb +101 -0
- data/lib/hem/patches/rubygems.rb +6 -0
- data/lib/hem/patches/slop.rb +69 -0
- data/lib/hem/paths.rb +96 -0
- data/lib/hem/tasks/assets.rb +92 -0
- data/lib/hem/tasks/config.rb +15 -0
- data/lib/hem/tasks/deps.rb +103 -0
- data/lib/hem/tasks/exec.rb +3 -0
- data/lib/hem/tasks/magento.rb +281 -0
- data/lib/hem/tasks/ops.rb +6 -0
- data/lib/hem/tasks/pr.rb +45 -0
- data/lib/hem/tasks/seed.rb +61 -0
- data/lib/hem/tasks/self.rb +45 -0
- data/lib/hem/tasks/shell_init.rb +25 -0
- data/lib/hem/tasks/system/completions.rb +76 -0
- data/lib/hem/tasks/system.rb +18 -0
- data/lib/hem/tasks/tools.rb +17 -0
- data/lib/hem/tasks/vm.rb +140 -0
- data/lib/hem/ui.rb +182 -0
- data/lib/hem/util.rb +76 -0
- data/lib/hem/version.rb +3 -0
- data/lib/hem.rb +72 -0
- data/lib/hobo/tasks/magento.rb +3 -0
- data/spec/hem/asset_applicator_spec.rb +30 -0
- data/spec/hem/cli_spec.rb +166 -0
- data/spec/hem/config/file_spec.rb +55 -0
- data/spec/hem/error_handlers/debug_spec.rb +43 -0
- data/spec/hem/error_handlers/friendly_spec.rb +97 -0
- data/spec/hem/error_spec.rb +0 -0
- data/spec/hem/help_formatter_spec.rb +162 -0
- data/spec/hem/helpers/file_locator_spec.rb +11 -0
- data/spec/hem/helpers/github_spec.rb +31 -0
- data/spec/hem/helpers/shell_spec.rb +22 -0
- data/spec/hem/helpers/vm_command_spec.rb +96 -0
- data/spec/hem/lib/github/api_spec.rb +92 -0
- data/spec/hem/lib/s3/sync_spec.rb +16 -0
- data/spec/hem/lib/seed/project_spec.rb +80 -0
- data/spec/hem/lib/seed/replacer_spec.rb +45 -0
- data/spec/hem/lib/seed/seed_spec.rb +127 -0
- data/spec/hem/logging_spec.rb +27 -0
- data/spec/hem/metadata_spec.rb +55 -0
- data/spec/hem/null_spec.rb +30 -0
- data/spec/hem/patches/rake_spec.rb +230 -0
- data/spec/hem/paths_spec.rb +75 -0
- data/spec/hem/ui_spec.rb +189 -0
- data/spec/hem/util_spec.rb +74 -0
- data/spec/spec_helper.rb +12 -0
- data/ssl/ca-bundle-s3.crt +3554 -0
- data/test_files/vagrant_fail/vagrant +2 -0
- metadata +339 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
module Hem
|
|
2
|
+
class HelpFormatter
|
|
3
|
+
attr_accessor :command_map
|
|
4
|
+
ALIGN_PAD = 4
|
|
5
|
+
|
|
6
|
+
def initialize global
|
|
7
|
+
@global = global
|
|
8
|
+
@command_map = {}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def help opts = {}
|
|
12
|
+
target = opts[:target] || nil
|
|
13
|
+
output = [""]
|
|
14
|
+
|
|
15
|
+
command = @command_map[target]
|
|
16
|
+
|
|
17
|
+
if !command
|
|
18
|
+
command_opts = []
|
|
19
|
+
commands = commands_for(@global, opts)
|
|
20
|
+
command = @global
|
|
21
|
+
else
|
|
22
|
+
command_opts = options_for(command)
|
|
23
|
+
commands = commands_for(command, opts)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
global_opts = options_for(@global)
|
|
27
|
+
|
|
28
|
+
align_to = longest([global_opts, command_opts, commands]) + ALIGN_PAD
|
|
29
|
+
|
|
30
|
+
if command != @global
|
|
31
|
+
description = [ command.long_description, command.description ].compact.first
|
|
32
|
+
output.push Hem.ui.color("#{description}\n", :description) if description
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
output.push section("Usage", [usage(command, target)])
|
|
36
|
+
output.push section("Global options", global_opts, align_to)
|
|
37
|
+
output.push section("Command options", command_opts, align_to)
|
|
38
|
+
output.push section("Commands", commands, align_to)
|
|
39
|
+
|
|
40
|
+
return output.compact.join("\n")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def longest inputs
|
|
46
|
+
inputs.map do |input|
|
|
47
|
+
next unless input.is_a? Array
|
|
48
|
+
if input.size == 0
|
|
49
|
+
0
|
|
50
|
+
else
|
|
51
|
+
input.map(&:first).map(&:size).max
|
|
52
|
+
end
|
|
53
|
+
end.compact.max
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def options_for source
|
|
57
|
+
heads = source.options.reject(&:tail?)
|
|
58
|
+
tails = (source.options - heads)
|
|
59
|
+
|
|
60
|
+
(heads + tails).map do |opt|
|
|
61
|
+
next if source != @global && opt.short == 'h'
|
|
62
|
+
line = padded(opt.short ? "-#{opt.short}," : "", 4)
|
|
63
|
+
description = opt.description
|
|
64
|
+
|
|
65
|
+
if opt.long
|
|
66
|
+
description += ". (Disable with --no-#{opt.long})" if opt.config[:invertable]
|
|
67
|
+
case opt.config[:as].to_s.downcase
|
|
68
|
+
when 'hash'
|
|
69
|
+
value = opt.config[:argument] ? "KEY#{opt.config[:key_delimiter]}VALUE" : ""
|
|
70
|
+
else
|
|
71
|
+
value = opt.config[:argument] ? "#{opt.long.upcase}" : ""
|
|
72
|
+
end
|
|
73
|
+
value = "[#{value}]" if opt.accepts_optional_argument?
|
|
74
|
+
value = "=#{value}" unless value.empty?
|
|
75
|
+
|
|
76
|
+
line += "--#{opt.long}#{value}"
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
[Hem.ui.color(line, :opt), description]
|
|
80
|
+
end.compact
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def commands_for source, opts = {}
|
|
84
|
+
source.commands.map do |name, command|
|
|
85
|
+
next if command.hidden && !opts[:all]
|
|
86
|
+
next unless command.hidden == false || command.description || opts[:all]
|
|
87
|
+
[Hem.ui.color(name, :command), command.description]
|
|
88
|
+
end.compact
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def usage source, command = nil
|
|
92
|
+
banner = source.banner
|
|
93
|
+
if banner.nil?
|
|
94
|
+
arg_list = (source.arg_list || []).map do |arg|
|
|
95
|
+
"<#{arg}>"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
banner = "#{File.basename($0, '.*')}"
|
|
99
|
+
banner << " [command]" if source.commands.any? && command.nil?
|
|
100
|
+
banner << " #{command.split(':').join(' ')}" if command
|
|
101
|
+
banner << " #{arg_list.join(' ')}" if arg_list.size > 0
|
|
102
|
+
banner << " [options]"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def section title, contents, align_to = false
|
|
107
|
+
return nil if contents.empty?
|
|
108
|
+
output = Hem.ui.color("#{title}:\n", :help_title)
|
|
109
|
+
output += contents.map do |line|
|
|
110
|
+
line.is_a?(String) ? " #{line}" : " #{padded(line[0], align_to)}#{line[1]}"
|
|
111
|
+
end.join("\n") + "\n"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def padded str, target
|
|
115
|
+
str + (' ' * (target - str.size))
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Hem
|
|
2
|
+
module Helper
|
|
3
|
+
def locate(pattern, opts = {}, &block)
|
|
4
|
+
match = nil
|
|
5
|
+
|
|
6
|
+
Dir.chdir Hem.project_path do
|
|
7
|
+
match = locate_git(pattern, &block)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
return match unless block_given?
|
|
11
|
+
return true if match
|
|
12
|
+
|
|
13
|
+
Hem.ui.warning opts[:missing] if opts[:missing]
|
|
14
|
+
return false
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def locate_git pattern, &block
|
|
20
|
+
args = [ 'git', 'ls-files', pattern ]
|
|
21
|
+
output = Hem::Helper.shell *args, :capture => true
|
|
22
|
+
paths = output.split("\n")
|
|
23
|
+
found = false
|
|
24
|
+
paths.each do |path|
|
|
25
|
+
path.strip!
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
return paths unless block_given?
|
|
29
|
+
|
|
30
|
+
paths.each do |path|
|
|
31
|
+
Dir.chdir File.dirname(path) do
|
|
32
|
+
Hem::Logging.logger.debug "helper.locator: Found #{path} for #{pattern}"
|
|
33
|
+
yield File.basename(path), path
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
found = true
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
return found
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
include Hem::Helper
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Hem
|
|
2
|
+
module Helper
|
|
3
|
+
def http_download url, target_file, opts = {}
|
|
4
|
+
require 'net/http'
|
|
5
|
+
require 'openssl'
|
|
6
|
+
require 'uri'
|
|
7
|
+
opts = { :progress => Hem.method(:progress) }.merge(opts)
|
|
8
|
+
uri = URI.parse(url)
|
|
9
|
+
size = 0
|
|
10
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
11
|
+
http.use_ssl = uri.scheme == 'https'
|
|
12
|
+
|
|
13
|
+
# TODO: May want to verify SSL validity...
|
|
14
|
+
# http://notetoself.vrensk.com/2008/09/verified-https-in-ruby/#comment-22252
|
|
15
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
16
|
+
|
|
17
|
+
http.start do
|
|
18
|
+
begin
|
|
19
|
+
file = open(target_file, 'wb+')
|
|
20
|
+
http.request_get(uri.path) do |response|
|
|
21
|
+
size = response.content_length
|
|
22
|
+
response.read_body do |chunk|
|
|
23
|
+
file.write(chunk)
|
|
24
|
+
opts[:progress].call(
|
|
25
|
+
target_file,
|
|
26
|
+
chunk.length,
|
|
27
|
+
size,
|
|
28
|
+
:update
|
|
29
|
+
) if opts[:progress]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
ensure
|
|
33
|
+
opts[:progress].call(target_file, 0, size, :finsh) if opts[:progress]
|
|
34
|
+
file.close
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
include Hem::Helper
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
module Hem
|
|
2
|
+
module Helper
|
|
3
|
+
|
|
4
|
+
def bundle_shell *args, &block
|
|
5
|
+
has_bundle = begin
|
|
6
|
+
shell "bundle", "exec", "ruby -v"
|
|
7
|
+
true
|
|
8
|
+
rescue ::Hem::ExternalCommandError
|
|
9
|
+
false
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
if has_bundle
|
|
13
|
+
args = [ 'bundle', 'exec' ] + args
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
shell *args, &block
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def shell *args, &block
|
|
20
|
+
require 'open3'
|
|
21
|
+
require 'tempfile'
|
|
22
|
+
|
|
23
|
+
def chunk_line_iterator stream
|
|
24
|
+
begin
|
|
25
|
+
until (chunk = stream.readpartial(1024)).nil? do
|
|
26
|
+
chunk.each_line do |outer_line|
|
|
27
|
+
outer_line.each_line("\r") do |line|
|
|
28
|
+
yield line
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
rescue EOFError
|
|
33
|
+
# NOP
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
opts = (args.size > 1 && args.last.is_a?(Hash)) ? args.pop : {}
|
|
38
|
+
opts = {
|
|
39
|
+
:capture => false,
|
|
40
|
+
:strip => true,
|
|
41
|
+
:indent => 0,
|
|
42
|
+
:realtime => false,
|
|
43
|
+
:env => {},
|
|
44
|
+
:ignore_errors => false,
|
|
45
|
+
:exit_status => false
|
|
46
|
+
}.merge! opts
|
|
47
|
+
|
|
48
|
+
Hem::Logging.logger.debug("helper.shell: Invoking '#{args.join(" ")}' with #{opts.to_s}")
|
|
49
|
+
|
|
50
|
+
require 'bundler'
|
|
51
|
+
::Bundler.with_clean_env do
|
|
52
|
+
Hem.chefdk_compat
|
|
53
|
+
indent = " " * opts[:indent]
|
|
54
|
+
::Open3.popen3 opts[:env], *args do |stdin, out, err, external|
|
|
55
|
+
buffer = ::Tempfile.new 'hem_run_buf'
|
|
56
|
+
buffer.sync = true
|
|
57
|
+
threads = [external]
|
|
58
|
+
last_buf = ""
|
|
59
|
+
|
|
60
|
+
## Create a thread to read from each stream
|
|
61
|
+
{ :out => out, :err => err }.each do |key, stream|
|
|
62
|
+
threads.push(::Thread.new do
|
|
63
|
+
chunk_line_iterator stream do |line|
|
|
64
|
+
line = ::Hem.ui.color(line, :error) if key == :err
|
|
65
|
+
line_formatted = if opts[:strip]
|
|
66
|
+
line.strip
|
|
67
|
+
else
|
|
68
|
+
line
|
|
69
|
+
end
|
|
70
|
+
buffer.write("#{line_formatted}\n")
|
|
71
|
+
Hem::Logging.logger.debug("helper.shell: #{line_formatted}")
|
|
72
|
+
line = yield line if block
|
|
73
|
+
print indent + line if opts[:realtime] && !line.nil?
|
|
74
|
+
end
|
|
75
|
+
end)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
threads.each do |t|
|
|
79
|
+
t.join
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
buffer.fsync
|
|
83
|
+
buffer.rewind
|
|
84
|
+
|
|
85
|
+
return external.value.exitstatus if opts[:exit_status]
|
|
86
|
+
|
|
87
|
+
raise ::Hem::ExternalCommandError.new(args.join(" "), external.value.exitstatus, buffer) if external.value.exitstatus != 0 && !opts[:ignore_errors]
|
|
88
|
+
|
|
89
|
+
if opts[:capture]
|
|
90
|
+
return buffer.read unless opts[:strip]
|
|
91
|
+
return buffer.read.strip
|
|
92
|
+
else
|
|
93
|
+
return nil
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
include Hem::Helper
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Hem
|
|
2
|
+
module Helper
|
|
3
|
+
|
|
4
|
+
def vm_shell command, opts = {}
|
|
5
|
+
shell ::Hem::Lib::Vm::Command.new(command, opts).to_s, opts
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def vm_mysql opts = {}
|
|
9
|
+
opts = {
|
|
10
|
+
:auto_echo => true,
|
|
11
|
+
:db => "",
|
|
12
|
+
:user => maybe(Hem.project_config.mysql.username) || "",
|
|
13
|
+
:pass => maybe(Hem.project_config.mysql.password) || "",
|
|
14
|
+
:mysql => 'mysql'
|
|
15
|
+
}.merge(opts)
|
|
16
|
+
|
|
17
|
+
opts[:user] = "-u#{opts[:user].shellescape}" unless opts[:user].empty?
|
|
18
|
+
opts[:pass] = "-p#{opts[:pass].shellescape}" unless opts[:pass].empty?
|
|
19
|
+
opts[:db] = opts[:db].shellescape unless opts[:db].empty?
|
|
20
|
+
|
|
21
|
+
::Hem::Lib::Vm::Command.new "#{opts[:mysql]} #{opts[:user]} #{opts[:pass]} #{opts[:db]}".strip, opts
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def vm_command command = nil, opts = {}
|
|
25
|
+
::Hem::Lib::Vm::Command.new command, opts
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
include Hem::Helper
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module Hem
|
|
2
|
+
module Lib
|
|
3
|
+
module Github
|
|
4
|
+
class Api
|
|
5
|
+
|
|
6
|
+
@connected = false
|
|
7
|
+
|
|
8
|
+
def initialize(opts = {})
|
|
9
|
+
@opts = {
|
|
10
|
+
:config_class => Hem::Config::File,
|
|
11
|
+
:user_config => Hem.user_config,
|
|
12
|
+
:ui => Hem.ui,
|
|
13
|
+
:client => Hem::Lib::Github::Client.new
|
|
14
|
+
}.merge! opts
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def connect
|
|
18
|
+
config = @opts[:user_config]
|
|
19
|
+
config[:github] ||= {}
|
|
20
|
+
|
|
21
|
+
if config[:github][:token].nil?
|
|
22
|
+
@opts[:ui].info 'You do not have a stored Github token. Authenticate now to create one.'
|
|
23
|
+
username = @opts[:ui].ask 'Github username'
|
|
24
|
+
password = @opts[:ui].ask 'Github password', echo: false
|
|
25
|
+
|
|
26
|
+
config[:github][:token] = @opts[:client].get_token_for_credentials(username, password)
|
|
27
|
+
|
|
28
|
+
@opts[:config_class].save(Hem.user_config_file, config)
|
|
29
|
+
else
|
|
30
|
+
@opts[:client].authenticate_with_token(config[:github][:token])
|
|
31
|
+
# client = Octokit::Client.new(:access_token => config.github.token)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
@connected = true
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def create_pull_request(repo, source_branch, target_branch, title, body)
|
|
38
|
+
unless @connected
|
|
39
|
+
connect
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
@opts[:client].create_pull_request(repo, source_branch, target_branch, title, body)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Hem
|
|
2
|
+
module Lib
|
|
3
|
+
module Github
|
|
4
|
+
class Client
|
|
5
|
+
|
|
6
|
+
@client = nil
|
|
7
|
+
|
|
8
|
+
def initialize(opts = {})
|
|
9
|
+
require 'octokit'
|
|
10
|
+
@opts = {
|
|
11
|
+
:client_class => Octokit::Client
|
|
12
|
+
}.merge! opts
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def get_token_for_credentials(username, password)
|
|
16
|
+
begin
|
|
17
|
+
@client = @opts[:client_class].new(:login => username, :password => password)
|
|
18
|
+
token_response = @client.create_authorization(:scopes => ['repo'], :note => 'Hem')
|
|
19
|
+
return token_response.token.to_s
|
|
20
|
+
rescue Octokit::UnprocessableEntity => e
|
|
21
|
+
case e.errors[0][:code]
|
|
22
|
+
when 'already_exists'
|
|
23
|
+
raise Hem::GithubAuthenticationError.new 'You already created a token for Hem, please delete this from your Github account before continuing.'
|
|
24
|
+
else
|
|
25
|
+
raise Hem::Error.new e.message
|
|
26
|
+
end
|
|
27
|
+
rescue Exception => e
|
|
28
|
+
raise Hem::Error.new e.message
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def authenticate_with_token(token)
|
|
33
|
+
begin
|
|
34
|
+
@client = @opts[:client_class].new(:access_token => token)
|
|
35
|
+
rescue Exception => e
|
|
36
|
+
raise Hem::Error.new e.message
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def create_pull_request(repo, source_branch, target_branch, title, body)
|
|
41
|
+
if @client.nil?
|
|
42
|
+
raise Hem::Error.new 'Client is not created'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
response = @client.create_pull_request(repo, source_branch, target_branch, title, body)
|
|
46
|
+
response[:html_url].to_s
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module Hem
|
|
2
|
+
module Lib
|
|
3
|
+
module HostCheck
|
|
4
|
+
def ssh_present opts
|
|
5
|
+
advice = "The SSH command could not be located on your system.\n\n"
|
|
6
|
+
|
|
7
|
+
if Hem.windows?
|
|
8
|
+
advice += "To make SSH available you must re-install git using the installer from http://git-scm.com/downloads ensuring you select the 'Use git and unix tools everywhere' option."
|
|
9
|
+
else
|
|
10
|
+
advice += "Please install openssh using your package manager."
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
begin
|
|
14
|
+
shell "ssh -V"
|
|
15
|
+
rescue Errno::ENOENT
|
|
16
|
+
raise Hem::HostCheckError.new("SSH is missing", advice)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def php_present opts
|
|
21
|
+
advice = <<-EOF
|
|
22
|
+
The PHP command could not be located on your system.
|
|
23
|
+
|
|
24
|
+
This is an optional command that can speed up composer dependency installs.
|
|
25
|
+
|
|
26
|
+
Please install it from your package manager ensuring that the following command does not produce any errors:
|
|
27
|
+
|
|
28
|
+
php -r "readfile('https://getcomposer.org/installer');" | php
|
|
29
|
+
EOF
|
|
30
|
+
|
|
31
|
+
begin
|
|
32
|
+
shell "php --version"
|
|
33
|
+
rescue Errno::ENOENT
|
|
34
|
+
raise Hem::HostCheckError.new("PHP is missing", advice)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module Hem
|
|
2
|
+
module Lib
|
|
3
|
+
module HostCheck
|
|
4
|
+
def git_present opts
|
|
5
|
+
advice = "The Git command could not be detected on your system.\n\n"
|
|
6
|
+
if Hem.windows?
|
|
7
|
+
advice += "Please install it from http://git-scm.com/downloads ensuring you select the 'Use git and unix tools everywhere' option."
|
|
8
|
+
else
|
|
9
|
+
advice += "Please install it using your package manager."
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
begin
|
|
13
|
+
shell "git --version"
|
|
14
|
+
rescue Errno::ENOENT
|
|
15
|
+
raise Hem::HostCheckError.new("Git is missing", advice)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def git_config_name_set opts
|
|
20
|
+
advice = <<-EOF
|
|
21
|
+
You have not set your name in git config!
|
|
22
|
+
|
|
23
|
+
Please do so with the following command:
|
|
24
|
+
git config --global user.name <your name here>
|
|
25
|
+
EOF
|
|
26
|
+
begin
|
|
27
|
+
shell "git config user.name"
|
|
28
|
+
rescue Hem::ExternalCommandError
|
|
29
|
+
raise Hem::HostCheckError.new("Git config is incomplete (Full name)", advice)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def git_config_email_set opts
|
|
34
|
+
advice = <<-EOF
|
|
35
|
+
You have not set your email in git config!
|
|
36
|
+
|
|
37
|
+
Please do so with the following command:
|
|
38
|
+
git config --global user.email <your email here>
|
|
39
|
+
EOF
|
|
40
|
+
|
|
41
|
+
begin
|
|
42
|
+
shell "git config user.email"
|
|
43
|
+
rescue Hem::ExternalCommandError
|
|
44
|
+
raise Hem::HostCheckError.new("Git config is incomplete (Email)", advice)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def git_autocrlf_disabled opts
|
|
49
|
+
return unless Hem.windows?
|
|
50
|
+
|
|
51
|
+
advice = <<-EOF
|
|
52
|
+
You're using git with the core.autocrlf option enabled.
|
|
53
|
+
|
|
54
|
+
This setting can often cause problems when you clone a repository on windows but need to execute the contents of that repository within a linux VM.
|
|
55
|
+
|
|
56
|
+
You can disable autocrlf globally with the following command:
|
|
57
|
+
git config --global core.autocrlf false
|
|
58
|
+
|
|
59
|
+
Disabling this setting will cause git to see all line endings as changed in a repository that was cloned with it enabled.
|
|
60
|
+
As such, you must either enable it just for those repositories or delete and re-clone them with the setting disabled.
|
|
61
|
+
|
|
62
|
+
You can enable the setting on a per-clone basis by ensuring that you are in the project directory and executing the following command:
|
|
63
|
+
git config core-autocrlf true
|
|
64
|
+
EOF
|
|
65
|
+
begin
|
|
66
|
+
value = shell "git config core.autocrlf", :capture => true
|
|
67
|
+
if value != "false"
|
|
68
|
+
raise Hem::HostCheckError.new("Git config has autocrlf enabled", advice)
|
|
69
|
+
end
|
|
70
|
+
rescue Hem::ExternalCommandError
|
|
71
|
+
# NOP
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module Hem
|
|
2
|
+
module Lib
|
|
3
|
+
module HostCheck
|
|
4
|
+
def not_using_system_ruby opts
|
|
5
|
+
return if Hem.windows?
|
|
6
|
+
advice = <<-EOF
|
|
7
|
+
You're using a system ruby install which can cause issues with installing Gems and running some older projects.
|
|
8
|
+
|
|
9
|
+
rbenv is HIGHLY recommended.
|
|
10
|
+
|
|
11
|
+
You can install it with the following command:
|
|
12
|
+
curl https://raw.github.com/fesplugas/rbenv-installer/master/bin/rbenv-installer | bash
|
|
13
|
+
|
|
14
|
+
Once installed, run the following to set it as the default ruby and re-install hem-inviqa:
|
|
15
|
+
rbenv install 1.9.3-p448 && rbenv global 1.9.3-448 && gem install hem-inviqa
|
|
16
|
+
EOF
|
|
17
|
+
require "rbconfig"
|
|
18
|
+
which = File.join(RbConfig::CONFIG["bindir"], RbConfig::CONFIG["ruby_install_name"])
|
|
19
|
+
unless which =~ /\.rbenv|\.rvm|jruby/
|
|
20
|
+
raise Hem::HostCheckError.new("Hem is running under a system ruby", advice)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def system_paths_for_ruby opts
|
|
25
|
+
return if Hem.windows?
|
|
26
|
+
|
|
27
|
+
advice = <<-EOF
|
|
28
|
+
The ordering of your system paths may cause a problem with Gems.
|
|
29
|
+
|
|
30
|
+
Unfortunately we can't automatically fix this for you at this time.
|
|
31
|
+
|
|
32
|
+
Please seek assistance.
|
|
33
|
+
|
|
34
|
+
Your paths were detected as:
|
|
35
|
+
|
|
36
|
+
#{ENV['PATH'].split(':').join("\n")}
|
|
37
|
+
EOF
|
|
38
|
+
|
|
39
|
+
paths = ENV['PATH'].split(':')
|
|
40
|
+
system_path_found = false
|
|
41
|
+
ruby_path_found = false
|
|
42
|
+
paths.each do |path|
|
|
43
|
+
system_before_ruby = system_path_found && !ruby_path_found
|
|
44
|
+
ruby_after_system = path =~ /\.rbenv|\.rvm/ && system_path_found
|
|
45
|
+
raise Hem::HostCheckError.new("System paths appear to be mis-ordered", advice) if system_before_ruby or ruby_after_system
|
|
46
|
+
|
|
47
|
+
ruby_path_found = true if path =~ /\.rbenv|\.rvm/
|
|
48
|
+
system_path_found = true if path =~ /\/usr\/bin|\/usr\/local\/bin/
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Hem
|
|
2
|
+
module Lib
|
|
3
|
+
module HostCheck
|
|
4
|
+
def vagrant_version opts
|
|
5
|
+
require 'semantic'
|
|
6
|
+
begin
|
|
7
|
+
version = shell "vagrant --version", :capture => true
|
|
8
|
+
version.gsub!(/^Vagrant[^0-9]+/, '')
|
|
9
|
+
version = ::Semantic::Version.new version.strip
|
|
10
|
+
minimum_version = ::Semantic::Version.new "1.3.5"
|
|
11
|
+
|
|
12
|
+
advice = <<-EOF
|
|
13
|
+
The version of vagrant which you are using (#{version}) is less than the minimum required (#{minimum_version}).
|
|
14
|
+
|
|
15
|
+
Please go to http://www.vagrantup.com/downloads.html and download the latest version for your platform.
|
|
16
|
+
EOF
|
|
17
|
+
raise Hem::HostCheckError.new("Vagrant is too old!", advice) if version < minimum_version
|
|
18
|
+
rescue Errno::ENOENT
|
|
19
|
+
advice = <<-EOF
|
|
20
|
+
Vagrant could not be detected on the path!
|
|
21
|
+
|
|
22
|
+
Please go to http://www.vagrantup.com/downloads.html and download the latest version for your platform.
|
|
23
|
+
EOF
|
|
24
|
+
raise Hem::HostCheckError.new("Vagrant is not on the path", advice)
|
|
25
|
+
rescue Hem::ExternalCommandError => error
|
|
26
|
+
advice = <<-EOF
|
|
27
|
+
Vagrant produced an error while checking its presence.
|
|
28
|
+
|
|
29
|
+
This is usually caused by using the vagrant gem which is no longer supported.
|
|
30
|
+
|
|
31
|
+
Uninstall any gem version of vagrant with the following command selecting "yes" to any prompt:
|
|
32
|
+
gem uninstall vagrant
|
|
33
|
+
|
|
34
|
+
You can then download and install the latest version from http://www.vagrantup.com/downloads.html
|
|
35
|
+
|
|
36
|
+
If you do not have any vagrant gems installed it may be possible that a gem such as vagrant-wrapper is installed and is failing.
|
|
37
|
+
|
|
38
|
+
Please seek assistance from #devops if this is the case.
|
|
39
|
+
EOF
|
|
40
|
+
raise Hem::HostCheckError.new("Vagrant produced an error while checking presence", advice)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|