baboon 1.0.0

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.
data/README.md ADDED
@@ -0,0 +1,97 @@
1
+ # Baboon
2
+ ![cardinal](https://alexweb.s3.amazonaws.com/baboon.jpeg)
3
+
4
+ [![Build Status](https://secure.travis-ci.org/amanelis/baboon.png)](http://travis-ci.org/amanelis/baboon)
5
+ [![Dependency Status](https://gemnasium.com/amanelis/baboon.png)](https://gemnasium.com/amanelis/baboon)
6
+
7
+ A simple and light weight deployment library for a ruby on rails application 3.0+. No symlinks, no releases, just git and your application.
8
+
9
+
10
+ # How it works
11
+ Baboon is simple. You provide your server addresses, environments, path, repository, username and Baboon does the rest. By running a simple `baboon deploy {env}` it will do all neccessary operations you intend for it to do on a full deploy to a production staging or development server. All you need is a working rails application on a server with a git repository.
12
+
13
+ ---
14
+ # Install
15
+ This must be installed under a current rails application. We recommend vendoring or installing through bundler.
16
+
17
+ gem install baboon
18
+
19
+ ---
20
+ # Configure
21
+
22
+ In your Gemfile, then `bundle install`.
23
+
24
+ group :development do
25
+ gem 'baboon'
26
+ end
27
+
28
+ Now that the gem is installed, run the config generator
29
+
30
+ rails g baboon:install
31
+
32
+ This will build a file into your application under `config/initializers/baboon.rb`. Open this file and start editing. Here is an example of the main configuration options:
33
+
34
+ Baboon.configure do |config|
35
+ config.application = 'Vacuum HQ'
36
+ config.repository = 'git@github.com:amanelis/vacuum.git'
37
+ config.deploy_path = '/home/rails/vacuum'
38
+ config.deploy_user = 'rails
39
+ config.branch = 'master'
40
+ config.rails_env = 'production'
41
+ config.servers = ['192.168.1.1', '192.168.1.2']
42
+ end
43
+
44
+ These must be properly filled out so baboon can properly make deploys.
45
+
46
+ ---
47
+ # Commands
48
+ Once everything is setup you can run `baboon` to see availabe tasks. Start by seeing if your configuration was properlly generated.
49
+
50
+ baboon configuration
51
+
52
+ Once you see and verify your Baboon.configuration you can now go ahead and test a deploy. For now, lets assume you have everything in your config correct and you are deploying to production:
53
+
54
+ baboon deploy
55
+
56
+ Thats it? Yeah, thats it! You should see your bundle installing and Baboon running all tasks. Custom tasks coming soon.
57
+
58
+ The next commands that will be realeased with future versions of baboon are:
59
+
60
+ baboon setup # no manually editing of configuration file
61
+ baboon check # checks the server and config file for proper configuration
62
+ baboon migrate # runs pending migrations
63
+ baboon restart # restarts your server
64
+ baboon rollback # rolls back your to your previous commit, info in ./log/baboon.log
65
+ baboon rake # run custom rake tasks on server
66
+ baboon execute # run a single command on the server
67
+ baboon shell # open a remote shell with the config user
68
+
69
+ ---
70
+ # CLI
71
+
72
+ This is coming very soon…
73
+
74
+
75
+ ---
76
+ ## Dependencies
77
+ #### Install dependencies using bundler
78
+ $ bundle
79
+
80
+ #### Run rSpec
81
+ $ rspec spec/
82
+
83
+ ## Issues
84
+ None.
85
+
86
+ ## Changelog
87
+ #### 1.0.0
88
+ Intial setup of the CLI and basic deploys are working.
89
+
90
+ ## How to contribute
91
+
92
+ * Fork the project.
93
+ * Make your feature addition or bug fix, push to a named branch.
94
+ * Add a test for any code committed.
95
+ * Send a pull request.
96
+
97
+ Copyright (c) 2011 [Alex Manelis](http://twitter.com/amanelis).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env rake
2
+
3
+ directory '.'
4
+ task :dgem do
5
+ sh 'rm *.gem'
6
+ end
7
+
8
+ task :bgem do
9
+ sh 'gem build *.gemspec'
10
+ end
data/bin/baboon ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'baboon/cli'
4
+ Baboon::Cli.start
@@ -0,0 +1,243 @@
1
+ require 'optparse'
2
+
3
+ module Baboon
4
+ class CLI
5
+ module Options
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+ # Return a new CLI instance with the given arguments pre-parsed and
12
+ # ready for execution.
13
+ def parse(args)
14
+ cli = new(args)
15
+ cli.parse_options!
16
+ cli
17
+ end
18
+ end
19
+
20
+ # The hash of (parsed) command-line options
21
+ attr_reader :options
22
+
23
+ # Return an OptionParser instance that defines the acceptable command
24
+ # line switches for Capistrano, and what their corresponding behaviors
25
+ # are.
26
+ def option_parser #:nodoc:
27
+ @logger = Logger.new
28
+ @option_parser ||= OptionParser.new do |opts|
29
+ opts.banner = "Usage: #{File.basename($0)} [options] action ..."
30
+
31
+ opts.on("-d", "--debug",
32
+ "Prompts before each remote command execution."
33
+ ) { |value| options[:debug] = true }
34
+
35
+ opts.on("-e", "--explain TASK",
36
+ "Displays help (if available) for the task."
37
+ ) { |value| options[:explain] = value }
38
+
39
+ opts.on("-F", "--default-config",
40
+ "Always use default config, even with -f."
41
+ ) { options[:default_config] = true }
42
+
43
+ opts.on("-f", "--file FILE",
44
+ "A recipe file to load. May be given more than once."
45
+ ) { |value| options[:recipes] << value }
46
+
47
+ opts.on("-H", "--long-help", "Explain these options and environment variables.") do
48
+ long_help
49
+ exit
50
+ end
51
+
52
+ opts.on("-h", "--help", "Display this help message.") do
53
+ puts opts
54
+ exit
55
+ end
56
+
57
+ opts.on("-l", "--logger [STDERR|STDOUT|file]",
58
+ "Choose logger method. STDERR used by default."
59
+ ) do |value|
60
+ options[:output] = if value.nil? || value.upcase == 'STDERR'
61
+ # Using default logger.
62
+ nil
63
+ elsif value.upcase == 'STDOUT'
64
+ $stdout
65
+ else
66
+ value
67
+ end
68
+ end
69
+
70
+ opts.on("-n", "--dry-run",
71
+ "Prints out commands without running them."
72
+ ) { |value| options[:dry_run] = true }
73
+
74
+ opts.on("-p", "--password",
75
+ "Immediately prompt for the password."
76
+ ) { options[:password] = nil }
77
+
78
+ opts.on("-q", "--quiet",
79
+ "Make the output as quiet as possible."
80
+ ) { options[:verbose] = 0 }
81
+
82
+ opts.on("-r", "--preserve-roles",
83
+ "Preserve task roles"
84
+ ) { options[:preserve_roles] = true }
85
+
86
+ opts.on("-S", "--set-before NAME=VALUE",
87
+ "Set a variable before the recipes are loaded."
88
+ ) do |pair|
89
+ name, value = pair.split(/=/, 2)
90
+ options[:pre_vars][name.to_sym] = value
91
+ end
92
+
93
+ opts.on("-s", "--set NAME=VALUE",
94
+ "Set a variable after the recipes are loaded."
95
+ ) do |pair|
96
+ name, value = pair.split(/=/, 2)
97
+ options[:vars][name.to_sym] = value
98
+ end
99
+
100
+ opts.on("-T", "--tasks [PATTERN]",
101
+ "List all tasks (matching optional PATTERN) in the loaded recipe files."
102
+ ) do |value|
103
+ options[:tasks] = if value
104
+ value
105
+ else
106
+ true
107
+ end
108
+ options[:verbose] ||= 0
109
+ end
110
+
111
+ opts.on("-t", "--tool",
112
+ "Abbreviates the output of -T for tool integration."
113
+ ) { options[:tool] = true }
114
+
115
+ opts.on("-V", "--version",
116
+ "Display the Capistrano version, and exit."
117
+ ) do
118
+ require 'capistrano/version'
119
+ puts "Capistrano v#{Capistrano::Version}"
120
+ exit
121
+ end
122
+
123
+ opts.on("-v", "--verbose",
124
+ "Be more verbose. May be given more than once."
125
+ ) do
126
+ options[:verbose] ||= 0
127
+ options[:verbose] += 1
128
+ end
129
+
130
+ opts.on("-X", "--skip-system-config",
131
+ "Don't load the system config file (capistrano.conf)"
132
+ ) { options.delete(:sysconf) }
133
+
134
+ opts.on("-x", "--skip-user-config",
135
+ "Don't load the user config file (.caprc)"
136
+ ) { options.delete(:dotfile) }
137
+ end
138
+ end
139
+
140
+ # If the arguments to the command are empty, this will print the
141
+ # allowed options and exit. Otherwise, it will parse the command
142
+ # line and set up any default options.
143
+ def parse_options! #:nodoc:
144
+ @options = { :recipes => [], :actions => [],
145
+ :vars => {}, :pre_vars => {},
146
+ :sysconf => default_sysconf, :dotfile => default_dotfile }
147
+
148
+ if args.empty?
149
+ warn "Please specify at least one action to execute."
150
+ warn option_parser
151
+ exit
152
+ end
153
+
154
+ option_parser.parse!(args)
155
+
156
+ coerce_variable_types!
157
+
158
+ # if no verbosity has been specified, be verbose
159
+ options[:verbose] = 3 if !options.has_key?(:verbose)
160
+
161
+ look_for_default_recipe_file! if options[:default_config] || options[:recipes].empty?
162
+ extract_environment_variables!
163
+
164
+ options[:actions].concat(args)
165
+
166
+ password = options.has_key?(:password)
167
+ options[:password] = Proc.new { self.class.password_prompt }
168
+ options[:password] = options[:password].call if password
169
+ end
170
+
171
+ # Extracts name=value pairs from the remaining command-line arguments
172
+ # and assigns them as environment variables.
173
+ def extract_environment_variables! #:nodoc:
174
+ args.delete_if do |arg|
175
+ next unless arg.match(/^(\w+)=(.*)$/)
176
+ ENV[$1] = $2
177
+ end
178
+ end
179
+
180
+ # Looks for a default recipe file in the current directory.
181
+ def look_for_default_recipe_file! #:nodoc:
182
+ current = Dir.pwd
183
+
184
+ loop do
185
+ %w(Capfile capfile).each do |file|
186
+ if File.file?(file)
187
+ options[:recipes] << file
188
+ @logger.info "Using recipes from #{File.join(current,file)}"
189
+ return
190
+ end
191
+ end
192
+
193
+ pwd = Dir.pwd
194
+ Dir.chdir("..")
195
+ break if pwd == Dir.pwd # if changing the directory made no difference, then we're at the top
196
+ end
197
+
198
+ Dir.chdir(current)
199
+ end
200
+
201
+ def default_sysconf #:nodoc:
202
+ File.join(sysconf_directory, "capistrano.conf")
203
+ end
204
+
205
+ def default_dotfile #:nodoc:
206
+ File.join(home_directory, ".caprc")
207
+ end
208
+
209
+ def sysconf_directory #:nodoc:
210
+ # TODO if anyone cares, feel free to submit a patch that uses a more
211
+ # appropriate location for this file in Windows.
212
+ ENV["SystemRoot"] || '/etc'
213
+ end
214
+
215
+ def home_directory #:nodoc:
216
+ ENV["HOME"] ||
217
+ (ENV["HOMEPATH"] && "#{ENV["HOMEDRIVE"]}#{ENV["HOMEPATH"]}") ||
218
+ "/"
219
+ end
220
+
221
+ def coerce_variable_types!
222
+ [:pre_vars, :vars].each do |collection|
223
+ options[collection].keys.each do |key|
224
+ options[collection][key] = coerce_variable(options[collection][key])
225
+ end
226
+ end
227
+ end
228
+
229
+ def coerce_variable(value)
230
+ case value
231
+ when /^"(.*)"$/ then $1
232
+ when /^'(.*)'$/ then $1
233
+ when /^\d+$/ then value.to_i
234
+ when /^\d+\.\d*$/ then value.to_f
235
+ when "true" then true
236
+ when "false" then false
237
+ when "nil" then nil
238
+ else value
239
+ end
240
+ end
241
+ end
242
+ end
243
+ end
data/lib/baboon/cli.rb ADDED
@@ -0,0 +1,148 @@
1
+ require 'baboon'
2
+ require 'baboon/configuration'
3
+ require 'baboon/logger'
4
+
5
+ require 'thor'
6
+ require 'net/ssh'
7
+
8
+ module Baboon
9
+ class Error
10
+ class << self
11
+ def stop reason
12
+ raise StandardError, reason
13
+ end
14
+ end
15
+ end
16
+
17
+ class Util
18
+ class << self
19
+ def read_configuration(file)
20
+ configuration = []
21
+ line_number = 0
22
+ text = File.open(file).read
23
+ text.gsub!(/\r\n?/, '\n')
24
+
25
+ text.each_line do |line|
26
+ next if line.include?('Baboon.configure')
27
+ next if line.include?('end')
28
+ line.gsub!(/^(.*)\s=\s/, '')
29
+ line.gsub!('\'', '')
30
+ line.strip!
31
+
32
+ configuration << { BABOON_CONFIGURATION_OPTIONS[line_number] => line }
33
+ line_number += 1
34
+ end
35
+
36
+ return configuration.reduce({}, :merge)
37
+ end
38
+ end
39
+ end
40
+
41
+ class Cli < Thor
42
+ attr_accessor :logger, :configuration
43
+
44
+ def initialize(*args)
45
+ super
46
+ @logger ||= Logger.new({level: 3, disable_formatters: false})
47
+
48
+ $stdout.sync = true
49
+
50
+ # Load the users baboon configuration
51
+ if File.exists?("config/initializers/baboon.rb")
52
+ @configuration = Util.read_configuration("config/initializers/baboon.rb")
53
+
54
+ Baboon.configure do |config|
55
+ config.application = @configuration[:application]
56
+ config.repository = @configuration[:repository]
57
+ config.deploy_path = @configuration[:deploy_path]
58
+ config.deploy_user = @configuration[:deploy_user]
59
+ config.branch = @configuration[:branch]
60
+ config.rails_env = @configuration[:rails_env]
61
+ config.servers = @configuration[:servers]
62
+ end
63
+ else
64
+ #Error.stop("Baboon says there is no configuration file at: config/initializers/baboon.rb. Please run `rails g baboon:install`")
65
+ printf @logger.format("Baboon says there is no configuration file at config/initializers/baboon.rb, run the following command", "31", 1)
66
+ printf @logger.format("USAGE: rails g baboon:install", "35", 1)
67
+ end
68
+ end
69
+
70
+ desc "deploy", "Starts a real deploy to a server"
71
+ def deploy
72
+ printf @logger.format(" == Baboon starting deploy", "32", 1)
73
+
74
+ # Essentially these are the instructions we need run for the Ubuntu 11.04
75
+ instructions = [
76
+ "cd #{Baboon.configuration.deploy_path} && bundle install",
77
+ "cd #{Baboon.configuration.deploy_path} && git fetch",
78
+ "cd #{Baboon.configuration.deploy_path} && git checkout #{Baboon.configuration.branch.to_s}",
79
+ "cd #{Baboon.configuration.deploy_path} && git merge origin/#{Baboon.configuration.branch.to_s}",
80
+ "cd #{Baboon.configuration.deploy_path} && touch tmp/restart.txt"
81
+ ]
82
+
83
+ # Vars for connecting via ssh to the server
84
+ credentials = {
85
+ user: Baboon.configuration.deploy_user.to_s,
86
+ host: 'ec2-50-19-131-228.compute-1.amazonaws.com'
87
+ }
88
+
89
+ Net::SSH.start(credentials[:host], credentials[:user]) do |session|
90
+ instructions.each do |instruction|
91
+ puts "instruction executing: #{instruction}"
92
+ puts ""
93
+ session.exec instruction
94
+ session.loop
95
+ end
96
+ end
97
+
98
+ printf @logger.format(" == Baboon deploy Complete", "31", 1)
99
+ end
100
+
101
+ desc "configuration", "Shows the current configuration for baboon"
102
+ def configuration
103
+ printf @logger.format("Baboon[Application]: #{Baboon.configuration.application}", "37", 1)
104
+ printf @logger.format("Baboon[Repository]: #{Baboon.configuration.repository}", "37", 1)
105
+ printf @logger.format("Baboon[Deploy_path]: #{Baboon.configuration.deploy_path}", "37", 1)
106
+ printf @logger.format("Baboon[Deploy_user]: #{Baboon.configuration.deploy_user}", "37", 1)
107
+ printf @logger.format("Baboon[Branch]: #{Baboon.configuration.branch}", "37", 1)
108
+ printf @logger.format("Baboon[Rails_env]: #{Baboon.configuration.rails_env}", "37", 1)
109
+ printf @logger.format("Baboon[Servers]: #{Baboon.configuration.servers}", "37", 1)
110
+ end
111
+
112
+ # desc "init", "Generates deployment customization scripts for your app"
113
+ # def init
114
+ # require 'generators/baboon/install/intall_generator'
115
+ # InstallGenerator::start([])
116
+ # end
117
+ #
118
+ # desc "restart", "Restarts the application on the server"
119
+ # def restart
120
+ # run "cd #{deploy_to} && deploy/restart | tee -a log/deploy.log"
121
+ # end
122
+ #
123
+ # desc "rollback", "Rolls back the checkout to before the last push"
124
+ # def rollback
125
+ # run "cd #{deploy_to} && git reset --hard ORIG_HEAD"
126
+ # invoke :restart
127
+ # end
128
+ #
129
+ # desc "log", "Shows the last part of the deploy log on the server"
130
+ # method_option :tail, :aliases => '-t', :type => :boolean, :default => false
131
+ # method_option :lines, :aliases => '-l', :type => :numeric, :default => 20
132
+ # def log(n = nil)
133
+ # tail_args = options.tail? ? '-f' : "-n#{n || options.lines}"
134
+ # run "tail #{tail_args} #{deploy_to}/log/deploy.log"
135
+ # end
136
+ #
137
+ # desc "upload <files>", "Copy local files to the remote app"
138
+ # def upload(*files)
139
+ # files = files.map { |f| Dir[f.strip] }.flatten
140
+ # abort "Error: Specify at least one file to upload" if files.empty?
141
+ #
142
+ # scp_upload files.inject({}) { |all, file|
143
+ # all[file] = File.join(deploy_to, file)
144
+ # all
145
+ # }
146
+ # end
147
+ end
148
+ end
@@ -0,0 +1,38 @@
1
+ require 'baboon'
2
+
3
+ module Baboon
4
+ # Baboon.configuration => output of configuration options
5
+ class << self
6
+ attr_accessor :configuration
7
+ end
8
+
9
+ # This method should be called with a block, even though none are given
10
+ # in the parameters of the method
11
+ def self.configure
12
+ self.configuration ||= Configuration.new
13
+ yield configuration
14
+ end
15
+
16
+ class Configuration
17
+ def initialize
18
+ # Cannot call attr inside of class, need to class_eval it
19
+ class << self
20
+ self
21
+ end.class_eval do
22
+ # Define all of the attributes
23
+ BABOON_CONFIGURATION_OPTIONS.each do |name|
24
+ attr_accessor name
25
+
26
+ # For each given symbol we generate accessor method that sets option's
27
+ # value being called with an argument, or returns option's current value
28
+ # when called without arguments
29
+ define_method name do |*values|
30
+ value = values.first
31
+ value ? self.send("#{name}=", value) : instance_variable_get("@#{name}")
32
+ end
33
+ end
34
+ end
35
+ # Initialize defaults
36
+ end # initialize
37
+ end # class Configuration
38
+ end # module Baboon
@@ -0,0 +1,153 @@
1
+ module Baboon
2
+ class Logger
3
+ attr_accessor :level, :device, :disable_formatters
4
+
5
+ IMPORTANT = 0
6
+ INFO = 1
7
+ DEBUG = 2
8
+ TRACE = 3
9
+
10
+ MAX_LEVEL = 3
11
+
12
+ COLORS = {
13
+ :none => "0",
14
+ :black => "30",
15
+ :red => "31",
16
+ :green => "32",
17
+ :yellow => "33",
18
+ :blue => "34",
19
+ :magenta => "35",
20
+ :cyan => "36",
21
+ :white => "37"
22
+ }
23
+
24
+ STYLES = {
25
+ :bright => 1,
26
+ :dim => 2,
27
+ :underscore => 4,
28
+ :blink => 5,
29
+ :reverse => 7,
30
+ :hidden => 8
31
+ }
32
+
33
+ # Set up default formatters
34
+ @formatters = [
35
+ # TRACE
36
+ { :match => /command finished/, :color => :white, :style => :dim, :level => 3, :priority => -10 },
37
+ { :match => /executing locally/, :color => :yellow, :level => 3, :priority => -20 },
38
+
39
+ # DEBUG
40
+ { :match => /executing `.*/, :color => :green, :level => 2, :priority => -10, :timestamp => true },
41
+ { :match => /.*/, :color => :yellow, :level => 2, :priority => -30 },
42
+
43
+ # INFO
44
+ { :match => /.*out\] (fatal:|ERROR:).*/, :color => :red, :level => 1, :priority => -10 },
45
+ { :match => /Permission denied/, :color => :red, :level => 1, :priority => -20 },
46
+ { :match => /sh: .+: command not found/, :color => :magenta, :level => 1, :priority => -30 },
47
+
48
+ # IMPORTANT
49
+ { :match => /^err ::/, :color => :red, :level => 0, :priority => -10 },
50
+ { :match => /.*/, :color => :blue, :level => 0, :priority => -20 }
51
+ ]
52
+
53
+ class << self
54
+ def add_formatter(options) #:nodoc:
55
+ @formatters.push(options)
56
+ @sorted_formatters = nil
57
+ end
58
+
59
+ def sorted_formatters
60
+ # Sort matchers in reverse order so we can break if we found a match.
61
+ @sorted_formatters ||= @formatters.sort_by { |i| -(i[:priority] || i[:prio] || 0) }
62
+ end
63
+ end
64
+
65
+ def initialize(options={})
66
+ output = options[:output] || $stderr
67
+ if output.respond_to?(:puts)
68
+ @device = output
69
+ else
70
+ @device = File.open(output.to_str, "a")
71
+ @needs_close = true
72
+ end
73
+
74
+ @options = options
75
+ @level = options[:level] || 0
76
+ @disable_formatters = options[:disable_formatters]
77
+ end
78
+
79
+ def close
80
+ device.close if @needs_close
81
+ end
82
+
83
+ def log(level, message, line_prefix=nil)
84
+ if level <= self.level
85
+ # Only format output if device is a TTY or formatters are not disabled
86
+ if device.tty? && !@disable_formatters
87
+ color = :none
88
+ style = nil
89
+
90
+ Logger.sorted_formatters.each do |formatter|
91
+ if (formatter[:level] == level || formatter[:level].nil?)
92
+ if message =~ formatter[:match] || line_prefix =~ formatter[:match]
93
+ color = formatter[:color] if formatter[:color]
94
+ style = formatter[:style] || formatter[:attribute] # (support original cap colors)
95
+ message.gsub!(formatter[:match], formatter[:replace]) if formatter[:replace]
96
+ message = formatter[:prepend] + message unless formatter[:prepend].nil?
97
+ message = message + formatter[:append] unless formatter[:append].nil?
98
+ message = Time.now.strftime('%Y-%m-%d %T') + ' ' + message if formatter[:timestamp]
99
+ break unless formatter[:replace]
100
+ end
101
+ end
102
+ end
103
+
104
+ if color == :hide
105
+ # Don't do anything if color is set to :hide
106
+ return false
107
+ end
108
+
109
+ term_color = COLORS[color]
110
+ term_style = STYLES[style]
111
+
112
+ # Don't format message if no color or style
113
+ unless color == :none and style.nil?
114
+ unless line_prefix.nil?
115
+ line_prefix = format(line_prefix, term_color, term_style, nil)
116
+ end
117
+ message = format(message, term_color, term_style)
118
+ end
119
+ end
120
+
121
+ indent = "%*s" % [MAX_LEVEL, "*" * (MAX_LEVEL - level)]
122
+ (RUBY_VERSION >= "1.9" ? message.lines : message).each do |line|
123
+ if line_prefix
124
+ device.puts "#{indent} [#{line_prefix}] #{line.strip}\n"
125
+ else
126
+ device.puts "#{indent} #{line.strip}\n"
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ def important(message, line_prefix=nil)
133
+ log(IMPORTANT, message, line_prefix)
134
+ end
135
+
136
+ def info(message, line_prefix=nil)
137
+ log(INFO, message, line_prefix)
138
+ end
139
+
140
+ def debug(message, line_prefix=nil)
141
+ log(DEBUG, message, line_prefix)
142
+ end
143
+
144
+ def trace(message, line_prefix=nil)
145
+ log(TRACE, message, line_prefix)
146
+ end
147
+
148
+ def format(message, color, style, nl = "\n")
149
+ style = "#{style};" if style
150
+ "\e[#{style}#{color}m" + message.to_s.strip + "\e[0m#{nl}"
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,3 @@
1
+ module Baboon
2
+ VERSION = "1.0.0"
3
+ end
data/lib/baboon.rb ADDED
@@ -0,0 +1,28 @@
1
+ # Standard configuration options for Baboon
2
+ #
3
+ # These options are important at this location. Change here and they
4
+ # are persisted throughout the entire Baboon configuration and as well
5
+ # as the config initializer baboon.rb file that is generated in the
6
+ # standing Rails application.
7
+ #
8
+ # option[:application] String => Has no berrance to the deployment, call it whatever.
9
+ # option[:repository] String => For now baboon only supports Git. This should be the actual Git repository of the application baboon will deploy.
10
+ # option[:deploy_path] String => The actual deploy path the application will sit at on the server. Exactly where the app's .git/ folder would be.
11
+ # option[:deploy_user] String/Symbol => The user baboon will be authenticating with on the server. Should have your key stored for optimal authentication.
12
+ # option[:branch] String/Symbol => The branch on your repository baboon will be pulling from.
13
+ # option[:rails_env] String/Symbol => For rake tasks to be run properly on your server, baboon needs to know what env it will be running on your server.
14
+ # option[:server] Array[String] => This will be an array of ip addresses of the servers baboon will deploy to.
15
+ BABOON_CONFIGURATION_OPTIONS = [
16
+ :application, # => This will be the name of the Application - not the directory
17
+ :repository, # => This will be the :scm of the repository the application will be cloning
18
+ :deploy_path, # => This will be the actual deploy path of the application, should have /home/#{user}/app
19
+ :deploy_user, # => This will be the user the system will authenticate with to do the deploy, should have sudo
20
+ :branch, # => Branch we will be cloning from on GIT
21
+ :rails_env, # => The rails environment the sever will be running
22
+ :servers # => An array of servers baboon will push to
23
+ ]
24
+
25
+ require 'baboon/configuration'
26
+ require 'baboon/cli'
27
+ require 'baboon/logger'
28
+ require 'baboon/version'
@@ -0,0 +1,5 @@
1
+ class String
2
+ def is_i?
3
+ !!(self =~ /^[-+]?[0-9]+$/)
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ require 'rails/generators/base'
2
+
3
+ module Baboon
4
+ module Generators
5
+ class ConfigGenerator < Rails::Generators::Base
6
+ desc 'Creates a yaml for Baboon at config/baboon.yml'
7
+
8
+ def self.source_root
9
+ @source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
10
+ end
11
+
12
+ def create_initializer_file
13
+ template "baboon.yml", "config/baboon.yml"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ application: Your Application Name
2
+ repository: git@github.com:your_project.git
3
+ deploy_path: /path/to/project
4
+ deploy_user: rails
5
+ deploy_branch: master
6
+
7
+ environments:
8
+ production:
9
+ servers: [192.168.1.100, 192.168.1.101]
10
+ staging:
11
+ servers: [10.0.0.1, 10.0.0.2]
@@ -0,0 +1,17 @@
1
+ require 'rails/generators/base'
2
+
3
+ module Baboon
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ desc 'Creates an initializer for Baboon at config/initializers/baboon.rb'
7
+
8
+ def self.source_root
9
+ @source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
10
+ end
11
+
12
+ def create_initializer_file
13
+ template "baboon.rb", "config/initializers/baboon.rb"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ Baboon.configure do |config|
2
+ config.application = 'NAME OF YOUR APPLICATION'
3
+ config.repository = 'git@github.com:{some-project}.git'
4
+ config.deploy_path = '{path_to_application_on_server}'
5
+ config.deploy_user = 'rails'
6
+ config.branch = 'master'
7
+ config.rails_env = 'production'
8
+ config.servers = ['server_1', 'server_2']
9
+ end
@@ -0,0 +1,107 @@
1
+ require 'spec_helper'
2
+
3
+ describe Baboon::Configuration do
4
+ describe 'configuration object should respond accordingly if not configured' do
5
+ before do
6
+ Baboon.configure do |config|; end
7
+ end
8
+
9
+ context 'when nothing is given for application' do
10
+ it 'should not be nil' do
11
+ Baboon.configuration.application.should == nil
12
+ end
13
+ end
14
+
15
+ context 'when nothing is given for repository' do
16
+ it 'should not be nil' do
17
+ Baboon.configuration.repository.should == nil
18
+ end
19
+ end
20
+
21
+ context 'when nothing is given for deploy_path' do
22
+ it 'should not be nil' do
23
+ Baboon.configuration.deploy_path.should == nil
24
+ end
25
+ end
26
+
27
+ context 'when nothing is given for deploy_user' do
28
+ it 'should not be nil' do
29
+ Baboon.configuration.deploy_user.should == nil
30
+ end
31
+ end
32
+
33
+ context 'when nothing is given for branch' do
34
+ it 'should not be nil' do
35
+ Baboon.configuration.branch.should == nil
36
+ end
37
+ end
38
+
39
+ context 'when nothing is given for rails_env' do
40
+ it 'should not be nil' do
41
+ Baboon.configuration.rails_env.should == nil
42
+ end
43
+ end
44
+
45
+ context 'when nothing is given for servers' do
46
+ it 'should not be nil' do
47
+ Baboon.configuration.servers.should == nil
48
+ end
49
+ end
50
+ end
51
+
52
+ describe 'configuration object should respond accordingly if is configured' do
53
+ before do
54
+ Baboon.configure do |config|
55
+ config.application = 'console'
56
+ config.repository = 'git@github.com:128lines/console.fm.git'
57
+ config.deploy_path = '/home/rails/console.fm/'
58
+ config.deploy_user = :rails
59
+ config.branch = :master
60
+ config.rails_env = :production
61
+ config.servers = ['server_1', 'server_2']
62
+ end
63
+ end
64
+
65
+ context 'when a application is assigned' do
66
+ it 'should not be nil' do
67
+ Baboon.configuration.application.should eq('console')
68
+ end
69
+ end
70
+
71
+ context 'when a repository is assigned' do
72
+ it 'should not be nil' do
73
+ Baboon.configuration.repository.should eq('git@github.com:128lines/console.fm.git')
74
+ end
75
+ end
76
+
77
+ context 'when a deploy_path is assigned' do
78
+ it 'should not be nil' do
79
+ Baboon.configuration.deploy_path.should eq('/home/rails/console.fm/')
80
+ end
81
+ end
82
+
83
+ context 'when a deploy_user is assigned' do
84
+ it 'should not be nil' do
85
+ Baboon.configuration.deploy_user.should eq(:rails)
86
+ end
87
+ end
88
+
89
+ context 'when a branch is assigned' do
90
+ it 'should not be nil' do
91
+ Baboon.configuration.branch.should eq(:master)
92
+ end
93
+ end
94
+
95
+ context 'when a rails_env is assigned' do
96
+ it 'should not be nil' do
97
+ Baboon.configuration.rails_env.should eq(:production)
98
+ end
99
+ end
100
+
101
+ context 'when a server is assigned' do
102
+ it 'should not be nil' do
103
+ Baboon.configuration.servers.should eq(['server_1', 'server_2'])
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Baboon do
4
+ it "should have a valid CONFIGURATION HASH" do
5
+ BABOON_CONFIGURATION_OPTIONS.should_not be_nil
6
+ end
7
+ end
@@ -0,0 +1 @@
1
+ require 'spec_helper'
@@ -0,0 +1,16 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_group 'Baboon', 'lib/'
4
+ end
5
+
6
+ ENV['RAILS_ENV'] ||= 'test'
7
+ require File.expand_path('../../lib/baboon', __FILE__)
8
+
9
+ PROJECT_ROOT = File.expand_path('../..', __FILE__)
10
+ $LOAD_PATH << File.join(PROJECT_ROOT, 'lib')
11
+
12
+ RSpec.configure do |config|
13
+ config.color_enabled = true
14
+ config.tty = true
15
+ config.mock_with :rspec
16
+ end
metadata ADDED
@@ -0,0 +1,295 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: baboon
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Alex Manelis
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thor
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: net-ssh
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: net-scp
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rails
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: rspec
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rspec-core
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: rspec-mocks
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: rspec-rails
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ - !ruby/object:Gem::Dependency
159
+ name: rspec-expectations
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ - !ruby/object:Gem::Dependency
175
+ name: shoulda-matchers
176
+ requirement: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ! '>='
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ type: :development
183
+ prerelease: false
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ! '>='
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ - !ruby/object:Gem::Dependency
191
+ name: simplecov
192
+ requirement: !ruby/object:Gem::Requirement
193
+ none: false
194
+ requirements:
195
+ - - ! '>='
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ type: :development
199
+ prerelease: false
200
+ version_requirements: !ruby/object:Gem::Requirement
201
+ none: false
202
+ requirements:
203
+ - - ! '>='
204
+ - !ruby/object:Gem::Version
205
+ version: '0'
206
+ - !ruby/object:Gem::Dependency
207
+ name: capybara
208
+ requirement: !ruby/object:Gem::Requirement
209
+ none: false
210
+ requirements:
211
+ - - ! '>='
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ type: :development
215
+ prerelease: false
216
+ version_requirements: !ruby/object:Gem::Requirement
217
+ none: false
218
+ requirements:
219
+ - - ! '>='
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
222
+ - !ruby/object:Gem::Dependency
223
+ name: faker
224
+ requirement: !ruby/object:Gem::Requirement
225
+ none: false
226
+ requirements:
227
+ - - ! '>='
228
+ - !ruby/object:Gem::Version
229
+ version: '0'
230
+ type: :development
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ none: false
234
+ requirements:
235
+ - - ! '>='
236
+ - !ruby/object:Gem::Version
237
+ version: '0'
238
+ description: A lite deployment package for rails applications.
239
+ email:
240
+ - amanelis@gmail.com
241
+ executables:
242
+ - baboon
243
+ extensions: []
244
+ extra_rdoc_files: []
245
+ files:
246
+ - Rakefile
247
+ - bin/baboon
248
+ - lib/baboon/cli/options.rb
249
+ - lib/baboon/cli.rb
250
+ - lib/baboon/configuration.rb
251
+ - lib/baboon/logger.rb
252
+ - lib/baboon/version.rb
253
+ - lib/baboon.rb
254
+ - lib/core_ext/string.rb
255
+ - lib/generators/baboon/config/config_generator.rb
256
+ - lib/generators/baboon/config/templates/baboon.yml
257
+ - lib/generators/baboon/install/install_generator.rb
258
+ - lib/generators/baboon/install/templates/baboon.rb
259
+ - spec/lib/baboon/configuration_spec.rb
260
+ - spec/lib/baboon_spec.rb
261
+ - spec/lib/generators/baboon/install/install_generator_spec.rb
262
+ - spec/spec_helper.rb
263
+ - README.md
264
+ homepage: https://github.com/amanelis/baboon
265
+ licenses:
266
+ - MIT
267
+ post_install_message:
268
+ rdoc_options: []
269
+ require_paths:
270
+ - lib
271
+ required_ruby_version: !ruby/object:Gem::Requirement
272
+ none: false
273
+ requirements:
274
+ - - ! '>='
275
+ - !ruby/object:Gem::Version
276
+ version: '0'
277
+ segments:
278
+ - 0
279
+ hash: -1949911459240274034
280
+ required_rubygems_version: !ruby/object:Gem::Requirement
281
+ none: false
282
+ requirements:
283
+ - - ! '>='
284
+ - !ruby/object:Gem::Version
285
+ version: '0'
286
+ segments:
287
+ - 0
288
+ hash: -1949911459240274034
289
+ requirements: []
290
+ rubyforge_project: baboon
291
+ rubygems_version: 1.8.24
292
+ signing_key:
293
+ specification_version: 3
294
+ summary: Add a configuration file, setup and deploy.
295
+ test_files: []