baboon 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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: []