baboon 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +97 -0
- data/Rakefile +10 -0
- data/bin/baboon +4 -0
- data/lib/baboon/cli/options.rb +243 -0
- data/lib/baboon/cli.rb +148 -0
- data/lib/baboon/configuration.rb +38 -0
- data/lib/baboon/logger.rb +153 -0
- data/lib/baboon/version.rb +3 -0
- data/lib/baboon.rb +28 -0
- data/lib/core_ext/string.rb +5 -0
- data/lib/generators/baboon/config/config_generator.rb +17 -0
- data/lib/generators/baboon/config/templates/baboon.yml +11 -0
- data/lib/generators/baboon/install/install_generator.rb +17 -0
- data/lib/generators/baboon/install/templates/baboon.rb +9 -0
- data/spec/lib/baboon/configuration_spec.rb +107 -0
- data/spec/lib/baboon_spec.rb +7 -0
- data/spec/lib/generators/baboon/install/install_generator_spec.rb +1 -0
- data/spec/spec_helper.rb +16 -0
- metadata +295 -0
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
data/bin/baboon
ADDED
@@ -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
|
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,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 @@
|
|
1
|
+
require 'spec_helper'
|
data/spec/spec_helper.rb
ADDED
@@ -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: []
|