deployable 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Rakefile +1 -0
- data/deployable.gemspec +24 -0
- data/examples/config/deploy/acceptance.rb +0 -0
- data/examples/config/deploy/production.rb +0 -0
- data/examples/config/deploy.rb +0 -0
- data/examples/scripts/initd.rb +190 -0
- data/lib/deployable/bundler-0.7.rb +23 -0
- data/lib/deployable/database.rb +121 -0
- data/lib/deployable/passenger.rb +24 -0
- data/lib/deployable/passenger_standalone.rb +34 -0
- data/lib/deployable/rvm.rb +33 -0
- data/lib/deployable/version.rb +3 -0
- data/lib/deployable.rb +8 -0
- metadata +62 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/deployable.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "deployable/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "deployable"
|
7
|
+
s.version = Deployable::VERSION
|
8
|
+
s.authors = ["Digitpaint", "Flurin Egger"]
|
9
|
+
s.email = ["info@digitpaint.nl", "flurin@digitpaint.nl"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{A collection of handy capistrano deploy recipes}
|
12
|
+
s.description = s.summary
|
13
|
+
|
14
|
+
s.rubyforge_project = "deployable"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
# s.add_development_dependency "rspec"
|
23
|
+
# s.add_runtime_dependency "rest-client"
|
24
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,190 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# chkconfig: - 85 15
|
4
|
+
# description: Passenger Standalone
|
5
|
+
require 'yaml'
|
6
|
+
require 'pathname'
|
7
|
+
|
8
|
+
# The user the applications run as.
|
9
|
+
USER = "admin"
|
10
|
+
USER_HOME_PATH = File.expand_path("~#{USER}")
|
11
|
+
RVM_PATH = USER_HOME_PATH + "/.rvm/"
|
12
|
+
|
13
|
+
# The place where all your applications reside. This scripts assumes that
|
14
|
+
# you have the following structure in your APPLICATIONS_PATH:
|
15
|
+
# APPLICATIONS_PATH
|
16
|
+
# |- APPLICATION_NAME
|
17
|
+
# |- STAGE
|
18
|
+
# |- server.yml (REQUIRED)
|
19
|
+
# |- current
|
20
|
+
APPLICATIONS_PATH = USER_HOME_PATH + "/applications/"
|
21
|
+
|
22
|
+
# Example :Server.yml
|
23
|
+
#
|
24
|
+
# passenger:
|
25
|
+
# port: 10001 # The port number passenger standalone will be ran on
|
26
|
+
# rvm:
|
27
|
+
# rvm_ruby_string: "rubyversion@gemsetname" # The ruby version and gemset RVM will use
|
28
|
+
# callbacks: # All callbacks are optional and are references to scripts relative to APPLICATIONS_PATH/APPLICATION_NAME/STAGE
|
29
|
+
# start:
|
30
|
+
# before: # Ran before passenger has started
|
31
|
+
# after: # Ran after passenger has started
|
32
|
+
# stop:
|
33
|
+
# before: # Ran before passenger has been stopped
|
34
|
+
# after: # Ran after passenger has been stopped
|
35
|
+
|
36
|
+
# ======================================================
|
37
|
+
# Shouldn't be necessary to change stuff below this line
|
38
|
+
# ======================================================
|
39
|
+
|
40
|
+
# Main start routine.
|
41
|
+
def run!
|
42
|
+
command = ARGV.first
|
43
|
+
available_commands = %w{start stop list}
|
44
|
+
raise "Use one of #{available_commands.join("|")} as first argument" unless available_commands.include?(command)
|
45
|
+
|
46
|
+
applications = Dir.glob("#{APPLICATIONS_PATH}*/*").inject({}){|mem, dir| parts = dir.split("/"); mem[parts[-2]] ||= []; mem[parts[-2]] << parts[-1]; mem}
|
47
|
+
|
48
|
+
if command == "list"
|
49
|
+
str = "All applications for #{USER}"
|
50
|
+
puts str
|
51
|
+
puts "=" * str.size
|
52
|
+
|
53
|
+
applications.each do |application, stages|
|
54
|
+
puts "#{application} (#{APPLICATIONS_PATH}/#{application})"
|
55
|
+
stages.each do |stage|
|
56
|
+
puts " - #{stage}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
else
|
60
|
+
if application = ARGV[1]
|
61
|
+
unless applications.has_key?(application)
|
62
|
+
raise "Can't find application #{application}"
|
63
|
+
end
|
64
|
+
|
65
|
+
if stage = ARGV[2]
|
66
|
+
unless applications[application].include?(stage)
|
67
|
+
raise "Stage #{stage} not found for application #{application}"
|
68
|
+
end
|
69
|
+
Application.new(application,stage).start_or_stop!(command)
|
70
|
+
else
|
71
|
+
applications[application].each do |stage|
|
72
|
+
Application.new(application,stage).start_or_stop!(command)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
else
|
76
|
+
applications.each do |application, stages|
|
77
|
+
stages.each do |stage|
|
78
|
+
Application.new(application,stage).start_or_stop!(command)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
true
|
84
|
+
end
|
85
|
+
|
86
|
+
# Wrapper class to handle application specific start and stop methods
|
87
|
+
# including callbacks
|
88
|
+
class Application
|
89
|
+
|
90
|
+
attr_reader :config, :path, :name, :stage
|
91
|
+
|
92
|
+
def initialize(application_name,stage)
|
93
|
+
@path = Pathname.new("#{APPLICATIONS_PATH}#{application_name}/#{stage}")
|
94
|
+
@name = application_name
|
95
|
+
@stage = start_or_stop
|
96
|
+
|
97
|
+
# Sanity check!
|
98
|
+
raise "No server.yml found in '#{@path}'" unless File.exist?(@path +"server.yml")
|
99
|
+
|
100
|
+
# Load config
|
101
|
+
@config = YAML.load(File.read((@path +"server.yml").to_s))
|
102
|
+
end
|
103
|
+
|
104
|
+
def start_or_stop!(command)
|
105
|
+
case command
|
106
|
+
when "start" then self.start!
|
107
|
+
when "stop" then self.stop!
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def start!
|
112
|
+
say "Start #{USER} #{self.name} #{self.stage}"
|
113
|
+
|
114
|
+
# Check for passenger gem.
|
115
|
+
unless rvm_execute(self.config, "gem list passenger") =~ /passenger/
|
116
|
+
say "Installing Passenger..."
|
117
|
+
rvm_execute(self.config, "gem install passenger")
|
118
|
+
end
|
119
|
+
|
120
|
+
# Run the before start callback
|
121
|
+
run_callback(:start, :before)
|
122
|
+
|
123
|
+
# Start the server
|
124
|
+
puts rvm_execute(self.config, "passenger start #{self.path + "current"} --user #{user} --port #{server_config['passenger']['port']} --environment production -d --pid-file #{self.path + "passenger.pid"}")
|
125
|
+
|
126
|
+
# Run the after start callback
|
127
|
+
run_callback(:start, :after)
|
128
|
+
end
|
129
|
+
|
130
|
+
def stop!
|
131
|
+
say "Stop #{USER} #{self.name} #{self.stage}"
|
132
|
+
|
133
|
+
# Run the before :stop callback
|
134
|
+
run_callback(:stop, :before)
|
135
|
+
|
136
|
+
puts rvm_execute(self.config, "passenger stop --pid-file #{self.path + "passenger.pid"}")
|
137
|
+
|
138
|
+
# Run the after :stop callback
|
139
|
+
run_callback(:stop, :after)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Simple output wrapper
|
143
|
+
def say(msg)
|
144
|
+
puts msg
|
145
|
+
end
|
146
|
+
|
147
|
+
protected
|
148
|
+
|
149
|
+
def callback(key, time)
|
150
|
+
return unless self.config.has_key?("callbacks")
|
151
|
+
|
152
|
+
callbacks = self.config["callbacks"]
|
153
|
+
|
154
|
+
if callback = (callbacks[key.to_s] && callbacks[key.to_s][time.to_s])
|
155
|
+
if File.exists?(self.path + callback)
|
156
|
+
say "Running #{time} #{key} callback '#{callback}'"
|
157
|
+
say rvm_execute(self.config, "bash #{self.path + callback}")
|
158
|
+
else
|
159
|
+
raise "Defined callback #{time} #{key} '#{callback}' does not exist!"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
# Helper method to run within an RVM environment
|
167
|
+
def rvm_execute(server_config, command)
|
168
|
+
execute("rvm_path=#{RVM_PATH} #{RVM_PATH}bin/rvm-shell '#{server_config['rvm']['rvm_ruby_string']}' -c '#{command}'")
|
169
|
+
end
|
170
|
+
|
171
|
+
# Execute command and decide wether or not to SUDO
|
172
|
+
def execute(command)
|
173
|
+
whoami = `whoami`.strip
|
174
|
+
if whoami == USER
|
175
|
+
`#{command} 2>&1`
|
176
|
+
else
|
177
|
+
`sudo -u #{USER} -H #{command} 2>&1`
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
begin
|
182
|
+
if run!
|
183
|
+
puts "Done!"
|
184
|
+
else
|
185
|
+
puts "Usage: passenger-standalone {start|stop|list} [application] [stage]"
|
186
|
+
end
|
187
|
+
rescue StandardError => e
|
188
|
+
puts "ERROR: #{e.message}"
|
189
|
+
puts "Usage: passenger-standalone {start|stop|list} [application] [stage]"
|
190
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# = Bundler 0.7.x related tasks
|
2
|
+
#
|
3
|
+
# Warning: Do not load 0.7.x AND 1.0.x tasks at the same time!
|
4
|
+
Capistrano::Configuration.instance(true).load do
|
5
|
+
namespace :bundler do
|
6
|
+
desc "Setup bundler dirs in shared"
|
7
|
+
task :setup, :roles => [:app] do
|
8
|
+
run "mkdir -p #{deploy_to}/shared/bundler_gems/gems #{deploy_to}/shared/bundler_gems/specifications"
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Bundle gems in release_path/vendor/bundler_gems (symlinked to shared)"
|
12
|
+
task :bundle, :roles => [:app] do
|
13
|
+
run "cd #{release_path}/vendor/bundler_gems; ln -fs #{deploy_to}/shared/bundler_gems/gems"
|
14
|
+
run "cd #{release_path}/vendor/bundler_gems; ln -fs #{deploy_to}/shared/bundler_gems/specifications"
|
15
|
+
run "cd #{release_path}; gem bundle --cached"
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "Install bundler"
|
19
|
+
task :install, :roles => [:app] do
|
20
|
+
run "gem install bundler --version=0.7.2"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# = Database.yml related tasks
|
2
|
+
#
|
3
|
+
# == Usage
|
4
|
+
#
|
5
|
+
# * Include this file in your <tt>deploy.rb</tt> configuration file.
|
6
|
+
# * Setup the required variables (see below)
|
7
|
+
# * After deploy:setup run database:setup
|
8
|
+
# * After deploy:update_code run database:copy_config_to_release
|
9
|
+
#
|
10
|
+
# == Setting variables
|
11
|
+
#
|
12
|
+
# The recipe uses the variable :database_config. You can put in there whatever you like but these are the defaults:
|
13
|
+
#
|
14
|
+
# set :database_config, {
|
15
|
+
# :username => "",
|
16
|
+
# :host => "",
|
17
|
+
# :development => "",
|
18
|
+
# :production => "",
|
19
|
+
# :test => ""
|
20
|
+
# }
|
21
|
+
#
|
22
|
+
# == Password
|
23
|
+
#
|
24
|
+
# Because you definitely don't want the password for the database in your SCM the recipe
|
25
|
+
# asks you for it.
|
26
|
+
#
|
27
|
+
# == Custom template
|
28
|
+
#
|
29
|
+
# By default, this script creates the database.yml below.
|
30
|
+
#
|
31
|
+
# If you want to overwrite the default template, simply create a custom Erb template
|
32
|
+
# called <tt>database.yml.erb</tt> and save it into <tt>config/deploy/templates</tt> folder.
|
33
|
+
#
|
34
|
+
# Although the name of the file can't be changed, you can customize the directory
|
35
|
+
# where it is stored defining a variable called <tt>:template_dir</tt>.
|
36
|
+
#
|
37
|
+
# # store your custom template at foo/bar/database.yml.erb
|
38
|
+
# set :template_dir, "foo/bar"
|
39
|
+
#
|
40
|
+
# # example of database template
|
41
|
+
#
|
42
|
+
# # MySQL (default setup). Versions 4.1 and 5.0 are recommended.
|
43
|
+
#
|
44
|
+
# db: &db
|
45
|
+
# adapter: mysql2
|
46
|
+
# username: <%= db[:username] %>
|
47
|
+
# password: <%= db[:password] %>
|
48
|
+
# host: <%= db[:host] %>
|
49
|
+
#
|
50
|
+
# development:
|
51
|
+
# <<: *db
|
52
|
+
# database: <%= db[:development] %>
|
53
|
+
#
|
54
|
+
# test:
|
55
|
+
# <<: *db
|
56
|
+
# database: <%= db[:test] %>
|
57
|
+
#
|
58
|
+
# production:
|
59
|
+
# <<: *db
|
60
|
+
# database: <%= db[:production] %>
|
61
|
+
#
|
62
|
+
#
|
63
|
+
# Because this is an Erb template, you can place variables and Ruby scripts
|
64
|
+
# within the file.
|
65
|
+
# For instance, the template above takes advantage of Capistrano CLI
|
66
|
+
# to ask for a MySQL database password instead of hard coding it into the template.
|
67
|
+
require 'ostruct'
|
68
|
+
|
69
|
+
Capistrano::Configuration.instance.load do
|
70
|
+
namespace :database do
|
71
|
+
desc <<-DESC
|
72
|
+
Creates the database.yml configuration file in deploy path.
|
73
|
+
It asks for a database password.
|
74
|
+
|
75
|
+
By default, this task uses a template unless a template \
|
76
|
+
called database.yml.erb is found either is :template_dir \
|
77
|
+
or /config/deploy folders. The default template matches \
|
78
|
+
the template for config/database.yml file shipped with Rails.
|
79
|
+
|
80
|
+
DESC
|
81
|
+
task :setup, :except => { :no_release => true } do
|
82
|
+
|
83
|
+
default_template = <<-EOF
|
84
|
+
# MySQL (default setup). Versions 4.1 and 5.0 are recommended.
|
85
|
+
|
86
|
+
db: &db
|
87
|
+
adapter: <%= config[:adapter] || "mysql2" %>
|
88
|
+
username: <%= config[:username] %>
|
89
|
+
password: <%= Capistrano::CLI.ui.ask("Database password: ") %>
|
90
|
+
host: <%= config[:host] %>
|
91
|
+
|
92
|
+
development:
|
93
|
+
<<: *db
|
94
|
+
database: <%= config[:development] %>
|
95
|
+
|
96
|
+
test:
|
97
|
+
<<: *db
|
98
|
+
database: <%= config[:test] %>
|
99
|
+
|
100
|
+
production:
|
101
|
+
<<: *db
|
102
|
+
database: <%= config[:production] %>
|
103
|
+
EOF
|
104
|
+
|
105
|
+
location = fetch(:template_dir, "config/deploy/templates") + '/database.yml.erb'
|
106
|
+
template = File.file?(location) ? File.read(location) : default_template
|
107
|
+
|
108
|
+
|
109
|
+
view = ERB.new(template)
|
110
|
+
put view.result(OpenStruct.new(:config => fetch(:database_config)).send(:binding)), "#{deploy_to}/database.yml"
|
111
|
+
end
|
112
|
+
|
113
|
+
desc <<-DESC
|
114
|
+
Copies the setup database.yml to the just deployed release.
|
115
|
+
DESC
|
116
|
+
task :copy_config_to_release, :except => { :no_release => true } do
|
117
|
+
run "cp #{deploy_to}/database.yml #{release_path}/config/database.yml"
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# = Passenger related recipes
|
2
|
+
#
|
3
|
+
# These tasks overwrite the default start/stop/restart tasks for deployment
|
4
|
+
# With passenger we only need to touch 'CURRENT_PATH/tmp/restart.txt'
|
5
|
+
#
|
6
|
+
# Warning: This overwrites the default deploy:restart, deploy:start and deploy:stop tasks
|
7
|
+
Capistrano::Configuration.instance(true).load do
|
8
|
+
|
9
|
+
namespace :deploy do
|
10
|
+
task :restart, :roles => [:app] do
|
11
|
+
run "touch #{current_path}/tmp/restart.txt"
|
12
|
+
end
|
13
|
+
|
14
|
+
task :start, :roles => [:app] do
|
15
|
+
# do nothing
|
16
|
+
end
|
17
|
+
|
18
|
+
task :stop, :roles => [:app] do
|
19
|
+
# do nothing
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# = Passenger Standalone related recipes
|
2
|
+
#
|
3
|
+
# These tasks handle setup of server.yml to use in combination
|
4
|
+
# with the DP init.d script for passenger standalone installations (see examples/scripts/initd.rb)
|
5
|
+
#
|
6
|
+
#
|
7
|
+
require 'yaml'
|
8
|
+
Capistrano::Configuration.instance(true).load do
|
9
|
+
namespace :passenger_standalone do
|
10
|
+
desc "Setup server.yml in the 'deploy_to' directory"
|
11
|
+
task :setup, :roles => [:app] do
|
12
|
+
config = fetch(:passenger_standalone)
|
13
|
+
config = deep_stringify_keys(config)
|
14
|
+
unless config["rvm"] && config["rvm"]["rvm_ruby_string"]
|
15
|
+
config["rvm"] ||= {}
|
16
|
+
config["rvm"]["rvm_ruby_string"] = fetch(:rvm_ruby_string)
|
17
|
+
end
|
18
|
+
|
19
|
+
put config.to_yaml, "#{deploy_to}/server.yml"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Helper method to make all keys of the config strings
|
24
|
+
def deep_stringify_keys(hash)
|
25
|
+
hash.inject({}) do |mem, (k,v)|
|
26
|
+
if v.kind_of?(Hash)
|
27
|
+
mem[k.to_s] = deep_stringify_keys(v)
|
28
|
+
else
|
29
|
+
mem[k.to_s] = v
|
30
|
+
end
|
31
|
+
mem
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# = RVM related tasks
|
2
|
+
#
|
3
|
+
# These tasks make working with RVM and gemsits a little bit easier.
|
4
|
+
#
|
5
|
+
# == Usage
|
6
|
+
# We want to be able to set the defined RVMRC in the deploy script
|
7
|
+
# on the server too. To achieve this we have to set the RVMRC
|
8
|
+
# after every deploy and we have to trust the just created RVMRC too.
|
9
|
+
#
|
10
|
+
# == Example
|
11
|
+
# require 'deployable/rvm'
|
12
|
+
# before "deploy:setup", "rvm:create_gemset"
|
13
|
+
# after "deploy:update_code", "rvm:set_rvmrc", "rvm:trust_rvmrc"
|
14
|
+
#
|
15
|
+
Capistrano::Configuration.instance(true).load do
|
16
|
+
namespace :rvm do
|
17
|
+
desc "Trust the RVMRC in release_path"
|
18
|
+
task :trust_rvmrc do
|
19
|
+
run "rvm rvmrc trust #{release_path}"
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Set an RVMRC according to the rubystring in release_path"
|
23
|
+
task :set_rvmrc, :roles => [:app] do
|
24
|
+
put "rvm use #{rvm_ruby_string}", "#{release_path}/.rvmrc"
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "Create the gemset"
|
28
|
+
task :create_gemset, :roles => [:app] do
|
29
|
+
ruby,gemset = rvm_ruby_string.split("@")
|
30
|
+
run "rvm gemset create #{gemset}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/deployable.rb
ADDED
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: deployable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Digitpaint
|
9
|
+
- Flurin Egger
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2012-01-22 00:00:00.000000000Z
|
14
|
+
dependencies: []
|
15
|
+
description: A collection of handy capistrano deploy recipes
|
16
|
+
email:
|
17
|
+
- info@digitpaint.nl
|
18
|
+
- flurin@digitpaint.nl
|
19
|
+
executables: []
|
20
|
+
extensions: []
|
21
|
+
extra_rdoc_files: []
|
22
|
+
files:
|
23
|
+
- .gitignore
|
24
|
+
- Gemfile
|
25
|
+
- Rakefile
|
26
|
+
- deployable.gemspec
|
27
|
+
- examples/config/deploy.rb
|
28
|
+
- examples/config/deploy/acceptance.rb
|
29
|
+
- examples/config/deploy/production.rb
|
30
|
+
- examples/scripts/initd.rb
|
31
|
+
- lib/deployable.rb
|
32
|
+
- lib/deployable/bundler-0.7.rb
|
33
|
+
- lib/deployable/database.rb
|
34
|
+
- lib/deployable/passenger.rb
|
35
|
+
- lib/deployable/passenger_standalone.rb
|
36
|
+
- lib/deployable/rvm.rb
|
37
|
+
- lib/deployable/version.rb
|
38
|
+
homepage: ''
|
39
|
+
licenses: []
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project: deployable
|
58
|
+
rubygems_version: 1.8.6
|
59
|
+
signing_key:
|
60
|
+
specification_version: 3
|
61
|
+
summary: A collection of handy capistrano deploy recipes
|
62
|
+
test_files: []
|