boxen 2.9.0 → 3.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/boxen.gemspec +12 -12
  2. data/lib/boxen/check.rb +8 -39
  3. data/lib/boxen/cli.rb +19 -45
  4. data/lib/boxen/command.rb +142 -0
  5. data/lib/boxen/command/help.rb +40 -0
  6. data/lib/boxen/command/preflight.rb +38 -0
  7. data/lib/boxen/command/project.rb +49 -0
  8. data/lib/boxen/command/project/install.rb +33 -0
  9. data/lib/boxen/command/run.rb +199 -0
  10. data/lib/boxen/command/service.rb +61 -0
  11. data/lib/boxen/command/service/disable.rb +15 -0
  12. data/lib/boxen/command/service/enable.rb +15 -0
  13. data/lib/boxen/command/service/restart.rb +24 -0
  14. data/lib/boxen/command/version.rb +29 -0
  15. data/lib/boxen/command_status.rb +15 -0
  16. data/lib/boxen/config.rb +43 -61
  17. data/lib/boxen/hook.rb +15 -8
  18. data/lib/boxen/keychain.rb +1 -1
  19. data/lib/boxen/postflight/env.rb +1 -1
  20. data/lib/boxen/postflight/github_issue.rb +124 -0
  21. data/lib/boxen/postflight/hooks.rb +16 -0
  22. data/lib/boxen/postflight/web_hook.rb +63 -0
  23. data/lib/boxen/preflight.rb +4 -7
  24. data/lib/boxen/preflight/creds.rb +8 -47
  25. data/lib/boxen/preflight/facts.rb +36 -0
  26. data/lib/boxen/preflight/homebrew.rb +13 -0
  27. data/lib/boxen/preflight/identity.rb +2 -0
  28. data/lib/boxen/preflight/offline.rb +33 -0
  29. data/lib/boxen/preflight/os.rb +1 -1
  30. data/lib/boxen/preflight/update.rb +109 -0
  31. data/lib/boxen/util/logging.rb +59 -0
  32. data/lib/boxen/version.rb +3 -0
  33. data/script/bootstrap +1 -1
  34. data/script/tests +1 -0
  35. data/test/boxen/test.rb +1 -1
  36. data/test/boxen_cli_test.rb +8 -31
  37. data/test/boxen_command_test.rb +93 -0
  38. data/test/boxen_config_test.rb +1 -31
  39. data/test/boxen_directories_test.rb +4 -4
  40. data/test/boxen_hook_test.rb +25 -0
  41. data/test/command/help_test.rb +49 -0
  42. data/test/command/project/install_test.rb +34 -0
  43. data/test/command/project_test.rb +32 -0
  44. data/test/command/run_test.rb +21 -0
  45. data/test/command/service/disable_test.rb +49 -0
  46. data/test/command/service/enable_test.rb +49 -0
  47. data/test/command/service/restart_test.rb +53 -0
  48. data/test/command/service_test.rb +55 -0
  49. data/test/command/version_test.rb +15 -0
  50. data/test/{boxen_postflight_active_test.rb → postflight/boxen_postflight_active_test.rb} +3 -3
  51. data/test/{boxen_postflight_env_test.rb → postflight/boxen_postflight_env_test.rb} +0 -0
  52. data/test/{boxen_hook_github_issue_test.rb → postflight/boxen_postflight_github_issue_test.rb} +72 -82
  53. data/test/{boxen_hook_web_test.rb → postflight/boxen_postflight_web_hook_test.rb} +12 -11
  54. data/test/preflight/boxen_preflight_creds_test.rb +82 -0
  55. data/test/{boxen_preflight_etc_my_cnf_test.rb → preflight/boxen_preflight_etc_my_cnf_test.rb} +1 -1
  56. data/test/preflight/boxen_preflight_homebrew_test.rb +10 -0
  57. data/test/{boxen_preflight_rvm_test.rb → preflight/boxen_preflight_rvm_test.rb} +1 -1
  58. metadata +247 -171
  59. checksums.yaml +0 -7
  60. data/lib/boxen/flags.rb +0 -282
  61. data/lib/boxen/hook/github_issue.rb +0 -120
  62. data/lib/boxen/hook/web.rb +0 -56
  63. data/lib/boxen/puppeteer.rb +0 -121
  64. data/lib/boxen/runner.rb +0 -149
  65. data/test/boxen_check_test.rb +0 -55
  66. data/test/boxen_flags_test.rb +0 -217
  67. data/test/boxen_preflight_creds_test.rb +0 -177
  68. data/test/boxen_puppeteer_test.rb +0 -101
  69. data/test/boxen_runner_test.rb +0 -171
@@ -1,30 +1,30 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
+ $:.unshift File.expand_path("../lib", __FILE__)
4
+ require "boxen/version"
5
+
3
6
  Gem::Specification.new do |gem|
4
7
  gem.name = "boxen"
5
- gem.version = "2.9.0"
6
- # Thanks go out to the previous maintainers John Barnette, Will
7
- # Farrington, David Goodlad and Mike McQuaid for getting this project
8
- # to where it is today.
9
- gem.authors = ["Jacob Bednarz"]
10
- gem.email = ["jacob.bednarz@gmail.com"]
8
+ gem.version = Boxen::VERSION
9
+ gem.authors = ["John Barnette", "Will Farrington", "David Goodlad"]
10
+ gem.email = ["jbarnette@github.com", "wfarr@github.com", "dgoodlad@github.com"]
11
11
  gem.description = "Manage Mac development boxes with love (and Puppet)."
12
12
  gem.summary = "You know, for laptops and stuff."
13
13
  gem.homepage = "https://github.com/boxen/boxen"
14
- gem.license = 'MIT'
15
14
 
16
- gem.files = `git ls-files`.split $/
17
- gem.test_files = gem.files.grep /^test/
15
+ gem.files = `git ls-files`.split( $/)
16
+ gem.test_files = gem.files.grep(/^test/)
17
+ gem.executables = gem.files.grep(/^bin/).map { |bin| File.basename(bin) }
18
18
  gem.require_paths = ["lib"]
19
19
 
20
20
  gem.add_dependency "ansi", "~> 1.4"
21
21
  gem.add_dependency "hiera", "~> 1.0"
22
- gem.add_dependency "highline", "~> 1.6.0"
22
+ gem.add_dependency "highline", "~> 1.6"
23
23
  gem.add_dependency "json_pure", [">= 1.7.7", "< 2.0"]
24
24
  gem.add_dependency "librarian-puppet", "~> 1.0.0"
25
25
  gem.add_dependency "octokit", "~> 2.7", ">= 2.7.1"
26
- gem.add_dependency "puppet", "~> 3.7"
26
+ gem.add_dependency "puppet", "~> 3.0"
27
27
 
28
- gem.add_development_dependency "minitest", "4.4.0" # pinned for mocha
28
+ gem.add_development_dependency "minitest", "~> 5.0" # pinned for mocha
29
29
  gem.add_development_dependency "mocha", "~> 0.13"
30
30
  end
@@ -1,20 +1,11 @@
1
- require "ansi"
1
+ require "boxen/util/logging"
2
2
 
3
3
  module Boxen
4
4
 
5
5
  # The superclass for preflight and postflight sanity checks.
6
6
 
7
7
  class Check
8
-
9
- # A collection of preflight instances for `config`. An instance is
10
- # created for every constant under `self` that's also a
11
- # subclass of `self`.
12
-
13
- def self.checks(config)
14
- constants.map { |n| const_get n }.
15
- select { |c| c < self }.
16
- map { |c| c.new config }
17
- end
8
+ include Boxen::Util::Logging
18
9
 
19
10
  # Search `dir` and load all Ruby files under it.
20
11
 
@@ -22,16 +13,12 @@ module Boxen
22
13
  Dir["#{dir}/*.rb"].sort.each { |f| load f }
23
14
  end
24
15
 
25
- # Check each instance against `config`.
26
-
27
- def self.run(config)
28
- checks(config).each { |check| check.run unless check.ok? }
29
- end
30
-
31
16
  attr_reader :config
17
+ attr_reader :command
32
18
 
33
- def initialize(config)
34
- @config = config
19
+ def initialize(config, command)
20
+ @config = config
21
+ @command = command
35
22
  end
36
23
 
37
24
  # Is everything good to go? Implemented by subclasses.
@@ -46,27 +33,9 @@ module Boxen
46
33
  raise "Subclasses must implement this method."
47
34
  end
48
35
 
49
- # A fancier `abort` and `warn`. This will probably really annoy
50
- # someone at some point because it's overriding a Kernel method,
51
- # but it's limited to checks.
52
-
53
- def abort(message, *extras)
54
- extras << { :color => :red }
55
- warn message, *extras
56
- exit 1
57
- end
58
-
59
- def warn(message, *extras)
60
- options = Hash === extras.last ? extras.pop : {}
61
- color = options[:color] || :yellow
62
-
63
- $stderr.puts ANSI.send(color) { "--> #{message}" }
64
-
65
- unless extras.empty?
66
- extras.each { |line| $stderr.puts " #{line}" }
67
- end
68
36
 
69
- $stderr.puts
37
+ def debug?
38
+ @config.debug?
70
39
  end
71
40
  end
72
41
  end
@@ -1,61 +1,35 @@
1
+ require "boxen/command"
1
2
  require "boxen/config"
2
- require "boxen/flags"
3
- require "boxen/postflight"
4
- require "boxen/preflight"
5
- require "boxen/runner"
6
- require "boxen/util"
3
+ require "boxen/util/logging"
7
4
 
8
5
  module Boxen
9
6
  class CLI
10
- attr_reader :config
11
- attr_reader :flags
12
- attr_reader :runner
13
-
14
- def initialize(config, flags)
15
- @config = config
16
- @flags = flags
17
- @runner = Boxen::Runner.new(@config, @flags)
18
- end
19
-
20
- def run
21
- if flags.help?
22
- puts flags
23
- exit
24
- end
7
+ include Boxen::Util::Logging
25
8
 
26
- runner.run
9
+ def self.run(*args)
10
+ new.run(*args)
27
11
  end
28
12
 
29
- # Run Boxen by wiring together the command-line flags, config,
30
- # preflights, Puppet execution, and postflights. Returns Puppet's
31
- # exit code.
32
-
33
- def self.run(*args)
34
- config = Boxen::Config.load
35
- flags = Boxen::Flags.new args
13
+ def initialize
14
+ end
36
15
 
37
- # Apply command-line flags to the config in case we're changing or
38
- # overriding anything.
39
- flags.apply config
16
+ def run(*args)
17
+ cmd, *cmd_args = args.flatten
40
18
 
41
- if flags.run?
42
- # Run the preflight checks.
43
- Boxen::Preflight.run config
19
+ with_friendly_errors do
20
+ config = Boxen::Config.load
21
+ status = Boxen::Command.invoke cmd, config, *cmd_args
44
22
 
45
- # Save the config for Puppet (and next time).
46
- Boxen::Config.save config
23
+ status.code
47
24
  end
25
+ end
48
26
 
49
- # Make the magic happen.
50
- status = Boxen::CLI.new(config, flags).run
51
-
52
- if flags.run?
53
- # Run the postflight checks.
54
- Boxen::Postflight.run config if status.success?
55
- end
27
+ private
56
28
 
57
- # Return Puppet's exit status.
58
- return status.code
29
+ def with_friendly_errors(&block)
30
+ yield
31
+ rescue => e
32
+ abort "#{e.class.name}: #{e.message}"
59
33
  end
60
34
  end
61
35
  end
@@ -0,0 +1,142 @@
1
+ require "boxen/command_status"
2
+
3
+ # Pulled in so the others don't have to
4
+ require "boxen/preflight"
5
+ require "boxen/postflight"
6
+ require "boxen/util/logging"
7
+
8
+ class Boxen::Command
9
+ include Boxen::Util::Logging
10
+
11
+ class UnknownCommandError < StandardError; end
12
+ class CommandNotRunError < StandardError; end
13
+
14
+ attr_reader :config
15
+
16
+ def self.help
17
+ raise "You should define this"
18
+ end
19
+
20
+ def self.detailed_help
21
+ raise "You should definitely define this"
22
+ end
23
+
24
+ def self.preflight(*klasses)
25
+ preflights.replace preflights | klasses.flatten
26
+ end
27
+
28
+ def self.preflights
29
+ @preflights ||= []
30
+ end
31
+
32
+ def self.postflight(*klasses)
33
+ postflights.replace postflights | klasses.flatten
34
+ end
35
+
36
+ def self.postflights
37
+ @postflights ||= []
38
+ end
39
+
40
+ def self.all
41
+ @commands
42
+ end
43
+
44
+ def self.register(name, klass, *aliases)
45
+ unless defined?(@commands)
46
+ @commands = {}
47
+ end
48
+ unless defined?(@aliases)
49
+ @aliases = {}
50
+ end
51
+
52
+ @commands[name] = klass
53
+ aliases.each { |a| @aliases[a] = name }
54
+ end
55
+
56
+ def self.reset!
57
+ @commands = {}
58
+ end
59
+
60
+ def self.invoke(name, *args)
61
+ if @commands && name && @commands.has_key?(name.to_sym)
62
+ @commands[name.to_sym].new(*args).invoke
63
+ elsif @aliases && name && @aliases.has_key?(name.to_sym)
64
+ invoke(@aliases[name.to_sym], *args)
65
+ else
66
+ raise UnknownCommandError,
67
+ "could not find `#{name.inspect.to_s}` in the list of registered commands"
68
+ end
69
+ end
70
+
71
+ def initialize(config, *args)
72
+ @config = config
73
+ @args = args
74
+ end
75
+
76
+ def invoke
77
+ if preflights?
78
+ @cmd_status = self.run
79
+
80
+ postflights
81
+
82
+ @cmd_status
83
+ end
84
+ end
85
+
86
+ def run
87
+ raise "So your command #{self.class.name} hasn't defined a run method, so we dunno what to do. Sorry."
88
+ end
89
+
90
+ def preflights?
91
+ if self.class.preflights.any?
92
+ info "Performing preflight checks"
93
+ end
94
+
95
+ self.class.preflights.all? do |p|
96
+
97
+ debug "Performing preflight check: #{p.name}"
98
+
99
+ p = p.new(@config, self)
100
+ status = p.ok?
101
+
102
+ if status
103
+ debug "Passed preflight check: #{p.class.name}"
104
+ else
105
+ p.run
106
+ end
107
+
108
+ status
109
+ end
110
+ end
111
+
112
+ def postflights
113
+ if self.class.postflights.any?
114
+ info "Performing postflight checks"
115
+ end
116
+
117
+ self.class.postflights.each do |p|
118
+ p = p.new(@config, self)
119
+ p.run unless p.ok?
120
+ end
121
+ end
122
+
123
+ def debug?
124
+ @config.debug?
125
+ end
126
+
127
+ def success?
128
+ if @cmd_status
129
+ @cmd_status.success?
130
+ else
131
+ raise CommandNotRunError,
132
+ "the command hasn't been run, so we can't know if it was successful"
133
+ end
134
+ end
135
+ end
136
+
137
+ require "boxen/command/help"
138
+ require "boxen/command/version"
139
+ require "boxen/command/run"
140
+ require "boxen/command/preflight"
141
+ require "boxen/command/project"
142
+ require "boxen/command/service"
@@ -0,0 +1,40 @@
1
+ require "boxen/command"
2
+
3
+ class Boxen::Command::Help < Boxen::Command
4
+ def self.help
5
+ "Displays help, obviously"
6
+ end
7
+
8
+ def self.detailed_help
9
+ <<-EOS
10
+
11
+ boxen help [<command>]
12
+
13
+ With no arguments, displays short help information for all commands.
14
+
15
+ Given a command name as an argument, displays detailed help about that command.
16
+
17
+ EOS
18
+ end
19
+
20
+ def run
21
+ if @args.any?
22
+ puts Boxen::Command.all[@args.first.to_sym].detailed_help
23
+ else
24
+ Boxen::Command.all.each do |name, _|
25
+ display_help_for_command name
26
+ end
27
+ end
28
+
29
+ Boxen::CommandStatus.new(0)
30
+ end
31
+
32
+ def display_help_for_command(name)
33
+ # only shows top-level commands, not subcommands
34
+ unless name =~ /:/
35
+ puts " #{name.to_s.ljust(16)} #{Boxen::Command.all[name.to_sym].help}"
36
+ end
37
+ end
38
+ end
39
+
40
+ Boxen::Command.register :help, Boxen::Command::Help, :"--help"
@@ -0,0 +1,38 @@
1
+ require "boxen/command"
2
+
3
+ class Boxen::Command::Preflight < Boxen::Command
4
+ def self.help
5
+ "Run a single preflight and return whether or not it's ok."
6
+ end
7
+
8
+ def self.detailed_help
9
+ <<-EOS
10
+
11
+ boxen preflight <check>
12
+
13
+ Run preflight named <check> and return whether or not it's ok.
14
+
15
+ EOS
16
+ end
17
+
18
+ def run
19
+ if defined?(preflight)
20
+ info "#{preflight.name}: #{preflight.new(@config).ok?.inspect}"
21
+ return Boxen::CommandStatus.new(0)
22
+ else
23
+ fail("Could not find a preflight named: #{preflight_name}")
24
+ end
25
+ rescue => e
26
+ fail("Command failed: #{e.message} #{e.backtrace}")
27
+ end
28
+
29
+ def preflight
30
+ Object.const_get(preflight_name)
31
+ end
32
+
33
+ def preflight_name
34
+ "Boxen::Preflight::#{ARGV[1].capitalize}"
35
+ end
36
+ end
37
+
38
+ Boxen::Command.register :preflight, Boxen::Command::Preflight
@@ -0,0 +1,49 @@
1
+ require "boxen/command"
2
+ #require "boxen/service"
3
+
4
+ class Boxen::Command::Project < Boxen::Command
5
+ def self.detailed_help
6
+ <<-EOS
7
+
8
+ boxen project
9
+
10
+ Display all projects Boxen knows about.
11
+
12
+ boxen project:install <project1> [<project2> ...]
13
+
14
+ Install a Boxen-managed project.
15
+
16
+ NOTE: 'boxen project' is aliased to 'projects' for convenience
17
+
18
+ EOS
19
+ end
20
+
21
+ def self.help
22
+ "Show and install Boxen-managed projects"
23
+ end
24
+
25
+ def run
26
+ @args = [] # we don't care about args here
27
+
28
+ puts "Boxen knows about the following projects:"
29
+ puts
30
+
31
+ projects.each do |project|
32
+ puts " #{project.name}"
33
+ end
34
+
35
+ puts
36
+ puts "You can install any of them by running \"boxen project:install <project>\""
37
+ puts
38
+
39
+ Boxen::CommandStatus.new(0)
40
+ end
41
+
42
+ def projects
43
+ @projects ||= @config.projects
44
+ end
45
+ end
46
+
47
+ require "boxen/command/project/install"
48
+
49
+ Boxen::Command.register :project, Boxen::Command::Project, :projects