capistrano-ext-projectdx 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/capistrano/ext/projectdx/all.rb +14 -0
- data/lib/capistrano/ext/projectdx/cache.rb +8 -0
- data/lib/capistrano/ext/projectdx/campfire.rb +59 -0
- data/lib/capistrano/ext/projectdx/docs.rb +15 -0
- data/lib/capistrano/ext/projectdx/git_branch.rb +60 -0
- data/lib/capistrano/ext/projectdx/misc.rb +35 -0
- data/lib/capistrano/ext/projectdx/passenger.rb +27 -0
- data/lib/capistrano/ext/projectdx/projectdx.rb +72 -0
- data/lib/capistrano/ext/projectdx/time.rb +29 -0
- data/lib/capistrano/ext/projectdx/web.rb +53 -0
- data/lib/capistrano/ext/projectdx.rb +18 -0
- metadata +80 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
# we have to call this something else so
|
2
|
+
# we do not keep loading this file over and over
|
3
|
+
Capistrano::Configuration.instance.load do
|
4
|
+
load_paths << File.dirname(__FILE__)
|
5
|
+
load('projectdx.rb')
|
6
|
+
load('campfire.rb')
|
7
|
+
load('git_branch.rb')
|
8
|
+
load('misc.rb')
|
9
|
+
load('time.rb')
|
10
|
+
load('web.rb')
|
11
|
+
load('passenger.rb')
|
12
|
+
load('docs.rb')
|
13
|
+
load('cache.rb')
|
14
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
namespace :cache do
|
2
|
+
desc "Empty out shared cachedir and the cached javascript and css"
|
3
|
+
task :clean, :roles => :web do
|
4
|
+
run "shopt -s nullglob; cd #{current_path} && for i in ./public/javascripts/cache_*.js; do /bin/rm ${i}; done"
|
5
|
+
run "shopt -s nullglob; cd #{current_path} && for i in ./public/stylesheets/cache_*.css; do /bin/rm ${i}; done"
|
6
|
+
run "shopt -s nullglob; cd #{shared_path} && /bin/rm -rf cache/*"
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
namespace :misc do
|
2
|
+
def send_to_campfire(message)
|
3
|
+
begin
|
4
|
+
gem 'tinder'
|
5
|
+
rescue Gem::LoadError
|
6
|
+
puts "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
7
|
+
puts ""
|
8
|
+
puts "not notifying because tinder not installed. Message is: '#{message}'"
|
9
|
+
puts ""
|
10
|
+
puts "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
11
|
+
return
|
12
|
+
end
|
13
|
+
require 'tinder'
|
14
|
+
# for some reason, ssl isn't working.
|
15
|
+
begin
|
16
|
+
campfire = Tinder::Campfire.new(campfire_host, :ssl => true)
|
17
|
+
campfire.login(campfire_login, campfire_password)
|
18
|
+
rescue => e
|
19
|
+
puts "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
20
|
+
puts ""
|
21
|
+
puts "Unable to login to campfire. Error is: '#{e}'"
|
22
|
+
puts "login: #{campfire_host}, #{campfire_login}, #{campfire_password}"
|
23
|
+
puts ""
|
24
|
+
puts "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
25
|
+
return
|
26
|
+
end
|
27
|
+
begin
|
28
|
+
room = campfire.find_room_by_name(campfire_room)
|
29
|
+
rescue => e
|
30
|
+
logger.error("Trouble initalizing campfire room #{campfire_room}")
|
31
|
+
return
|
32
|
+
end
|
33
|
+
begin
|
34
|
+
room.speak(message)
|
35
|
+
rescue => e
|
36
|
+
puts "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
37
|
+
puts ""
|
38
|
+
puts "Unable to send message to campfire. Message is: '#{message}'"
|
39
|
+
puts ""
|
40
|
+
puts "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
41
|
+
return
|
42
|
+
end
|
43
|
+
end
|
44
|
+
desc "[internal] Send campfire notifications on success"
|
45
|
+
task :send_success, :on_error => :continue do
|
46
|
+
t=end_time
|
47
|
+
time_msg=t.nil? ? '' : " in #{t} minutes"
|
48
|
+
send_to_campfire("#{Etc.getpwnam(Etc.getlogin)['gecos'].split.first} tried to deploy branch #{branch} to #{stage}. It succeeded#{time_msg}! :D")
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "[internal] send notifications in case the deploy fails"
|
52
|
+
task :rollback_notification, :on_error => :continue do
|
53
|
+
on_rollback {
|
54
|
+
t=end_time
|
55
|
+
time_msg=t.nil? ? '' : " after #{t} minutes"
|
56
|
+
send_to_campfire("#{Etc.getpwnam(Etc.getlogin)['gecos'].split.first} tried to deploy branch #{branch} to #{stage}. It failed#{time_msg}. :.(")
|
57
|
+
}
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Capistrano::Configuration.instance.load do
|
2
|
+
namespace :deploy do
|
3
|
+
namespace :docs do
|
4
|
+
desc "update docs directory"
|
5
|
+
task :default do
|
6
|
+
run "cd #{current_path} && rake doc:local RDOC_DIR=#{docsdir}"
|
7
|
+
end
|
8
|
+
desc "force rebuild of docs directory"
|
9
|
+
task :rebuild do
|
10
|
+
run "/bin/rm -rf #{docsdir}"
|
11
|
+
top.deploy.docs.default
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
Capistrano::Configuration.instance.load do
|
2
|
+
def changed_in_git(filename)
|
3
|
+
`git diff --name-only`.grep(/^#{filename}$/).length > 0 ? true : false
|
4
|
+
end
|
5
|
+
|
6
|
+
def commit_of_rev(branch)
|
7
|
+
x=`git rev-parse --revs-only #{branch}`.chomp
|
8
|
+
return nil if x.empty?
|
9
|
+
return x
|
10
|
+
end
|
11
|
+
|
12
|
+
def commit_in_remote_branch?(commit,branch)
|
13
|
+
return false if commit.nil?
|
14
|
+
if %x{git branch -r --contains #{commit}}.grep(/^\s*origin\/#{branch}/).empty?
|
15
|
+
puts ""
|
16
|
+
puts "no rev matches #{commit} in the remote #{branch} branch(es)"
|
17
|
+
return false
|
18
|
+
end
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
def valid_commit?(commit)
|
23
|
+
return false if commit.nil?
|
24
|
+
if [ :production ].include? stage
|
25
|
+
return false unless commit_in_remote_branch?(commit,'production')
|
26
|
+
elsif [ :custbeta ].include? stage
|
27
|
+
return false unless commit_in_remote_branch?(commit,'custbeta')
|
28
|
+
end
|
29
|
+
return true
|
30
|
+
end
|
31
|
+
|
32
|
+
# returns the actual branch name, if it exists. nil if it does not
|
33
|
+
def remote_branch_name(branch)
|
34
|
+
return nil if branch.nil?
|
35
|
+
rem_branch = `git branch -r`.grep(/^\s*origin\/(v|)#{branch}$/)[0]
|
36
|
+
return nil if rem_branch.nil?
|
37
|
+
return rem_branch.sub(/^\s*origin\//, '').chomp
|
38
|
+
end
|
39
|
+
|
40
|
+
release = nil;
|
41
|
+
set :release_number do
|
42
|
+
commit=nil;
|
43
|
+
release=ENV[ 'DEPLOY_VERSION' ] if ENV[ 'DEPLOY_VERSION' ]
|
44
|
+
release=ENV['BUILD_VCS_NUMBER'][0,12] if ENV['BUILD_VCS_NUMBER']
|
45
|
+
commit = commit_of_rev(release)
|
46
|
+
while not valid_commit?(commit) do
|
47
|
+
release=Capistrano::CLI.ui.ask( 'Enter release number to deploy: ' )
|
48
|
+
commit=commit_of_rev(release)
|
49
|
+
end
|
50
|
+
commit
|
51
|
+
end
|
52
|
+
|
53
|
+
set :branch do
|
54
|
+
release_number
|
55
|
+
end
|
56
|
+
|
57
|
+
set :release_commit do
|
58
|
+
branch
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
namespace :misc do
|
2
|
+
desc "[internal] Send campfire notifications on success"
|
3
|
+
task :send_success, :on_error => :continue do
|
4
|
+
t=end_time
|
5
|
+
time_msg=t.nil? ? '' : " in #{t} minutes"
|
6
|
+
send_to_campfire("#{Etc.getpwnam(Etc.getlogin)['gecos'].split.first} tried to deploy branch #{branch} to #{stage}. It succeeded#{time_msg}! :D")
|
7
|
+
end
|
8
|
+
|
9
|
+
desc "[internal] send notifications in case the deploy fails"
|
10
|
+
task :rollback_notification, :on_error => :continue do
|
11
|
+
on_rollback {
|
12
|
+
t=end_time
|
13
|
+
time_msg=t.nil? ? '' : " after #{t} minutes"
|
14
|
+
send_to_campfire("#{Etc.getpwnam(Etc.getlogin)['gecos'].split.first} tried to deploy branch #{branch} to #{stage}. It failed#{time_msg}. :.(")
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "Add trigers on migration to restore database from production state. Used for running stage deployments with optional restore."
|
20
|
+
task :restoredb do
|
21
|
+
before "deploy:migrate", "deploy:db:reset_nobackup"
|
22
|
+
after "deploy:db:reset_nobackup", "deploy:tables"
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Do full deploy of table updates"
|
26
|
+
task :full do
|
27
|
+
before "deploy:migrate", "deploy:tables"
|
28
|
+
end
|
29
|
+
|
30
|
+
namespace :rake do
|
31
|
+
desc "Allow running of remote rake tasks"
|
32
|
+
task :invoke do
|
33
|
+
run "cd #{deploy_to}/current && rake #{ENV['task']} RAILS_ENV=#{rails_env}"
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
Capistrano::Configuration.instance.load do
|
2
|
+
namespace :deploy do
|
3
|
+
# these can be changed when passenger is on production
|
4
|
+
desc "Stop task is a no-op with passenger"
|
5
|
+
task :stop, :roles => :app do ; end
|
6
|
+
|
7
|
+
%w(start restart).each do |name|
|
8
|
+
desc "#{name} passenger on application"
|
9
|
+
task name, :roles => :app do
|
10
|
+
top.passenger.restart
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
namespace :passenger do
|
15
|
+
desc "Restart Passenger"
|
16
|
+
task :restart, :rols => :app do
|
17
|
+
run "touch #{current_path}/tmp/restart.txt"
|
18
|
+
if [ :production ].include? stage
|
19
|
+
run "curl -s -o /dev/null http://sonomacountyenergyaction.org/customers/2/geometries;true"
|
20
|
+
run "curl -s -o /dev/null http://sonomacountyenergyaction.org/customers/1/geometries;true"
|
21
|
+
else
|
22
|
+
run "curl -s -o /dev/null http:/sonoma.`hostname`/customers/2/geometries;true"
|
23
|
+
run "curl -s -o /dev/null http:/sonoma.`hostname`/customers/1/geometries;true"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
Capistrano::Configuration.instance.load do
|
2
|
+
namespace :deploy do
|
3
|
+
desc "update selinux context"
|
4
|
+
task :selinux do
|
5
|
+
run "if [ -d #{release_path} ]; then
|
6
|
+
chcon -R -t httpd_sys_content_t #{release_path} ;
|
7
|
+
fi;
|
8
|
+
if [ -d #{current_path}/ ]; then
|
9
|
+
chcon -R -t httpd_sys_content_t #{current_path}/;
|
10
|
+
fi"
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "install database.yml, and other things "
|
14
|
+
task :local_config do
|
15
|
+
run "cp #{release_path}/config/database.deploy.yml #{release_path}/config/database.yml"
|
16
|
+
case stage
|
17
|
+
when :alpha
|
18
|
+
run "rsync -a #{release_path}/features/ #{release_path}/public/features/"
|
19
|
+
run %Q{ /bin/ls -1 #{release_path}/public/features/ | /bin/awk -v dq='"' 'BEGIN{print "<!DOCTYPE HTML PUBLIC " dq "-//W3C//DTD HTML 4.01//EN" dq "\n" dq "http://www.w3.org/TR/html4/strict.dtd"dq">\n<body><table>"} /feature$/ {print "<tr><td><a href="dq $1 dq ">" $1 "</a></td></tr>"} END{print "</table></body>"}' > #{release_path}/public/features/index.html}
|
20
|
+
end
|
21
|
+
run "mkdir -p #{shared_path}/cache"
|
22
|
+
run "/bin/ln -nsf #{release_path}/../../shared/cache #{release_path}/public/cache"
|
23
|
+
#run "/bin/ln -nsf #{release_path} #{release_path}/../latest"
|
24
|
+
#run "/bin/ln -nsf #{shared_path}/config/database.yml #{release_path}/config/database.yml"
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "Write Version file on server"
|
28
|
+
task :write_version_file, :roles => :web do
|
29
|
+
output=%Q{
|
30
|
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
31
|
+
"http://www.w3.org/TR/html4/strict.dtd">
|
32
|
+
<body>
|
33
|
+
<p>Release Branch: #{release_number}</p>
|
34
|
+
<p>Release Commit: #{release_commit}</p>
|
35
|
+
<p>Deployed on: #{Time.now.strftime('%m/%d/%Y at %H:%M %Z')}</p>
|
36
|
+
</body>
|
37
|
+
}
|
38
|
+
put(output, "#{current_path}/public/version.html")
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "make some directories we like to have"
|
42
|
+
task :make_shared_dirs do
|
43
|
+
run "mkdir -p #{deploy_to}/shared/system"
|
44
|
+
run "mkdir -p #{deploy_to}/shared/config"
|
45
|
+
run "mkdir -p #{deploy_to}/shared/log/old"
|
46
|
+
run "mkdir -p #{deploy_to}/shared/pids"
|
47
|
+
run "mkdir -p #{deploy_to}/releases"
|
48
|
+
run "mkdir -p '#{shared_path}/config/payment_gateways'"
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "remove old submodules from vendors directory"
|
52
|
+
task :cleanup_vendor do
|
53
|
+
run "cd #{deploy_to}/shared/cached-copy && git clean -dxf vendor"
|
54
|
+
end
|
55
|
+
|
56
|
+
before "deploy:update_code", "deploy:cleanup_vendor"
|
57
|
+
before "deploy:rollback:revision", "deploy:rollback_migrations"
|
58
|
+
|
59
|
+
desc "Rolls back database to migration level of the previously deployed release"
|
60
|
+
task :rollback_migrations, :roles => :db, :only => { :primary => true } do
|
61
|
+
if releases.length < 2
|
62
|
+
abort "could not rollback the code because there is no prior release"
|
63
|
+
else
|
64
|
+
rake = fetch(:rake, "rake")
|
65
|
+
rails_env = fetch(:rails_env, "production")
|
66
|
+
migrate_env = fetch(:migrate_env, "")
|
67
|
+
migrate_target = fetch(:migrate_target, :latest)
|
68
|
+
run "cd #{current_path}; #{rake} RAILS_ENV=#{rails_env} #{migrate_env} db:migrate VERSION=`cd #{File.join(previous_release, 'db', 'migrate')} && ls -1 [0-9]*_*.rb | tail -1 | sed -e s/_.*$//`"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end #namespace deploy
|
72
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
def start_time
|
2
|
+
@begin = Time.now()
|
3
|
+
end
|
4
|
+
|
5
|
+
def end_time
|
6
|
+
if @begin.nil?
|
7
|
+
return nil
|
8
|
+
else
|
9
|
+
return to_minutes(Time.now() - @begin)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
namespace :time do
|
14
|
+
desc "[internal] record the current time for later use"
|
15
|
+
task :begin do
|
16
|
+
start_time
|
17
|
+
end
|
18
|
+
desc "[internal] print the time elapsed since time:begin was executed"
|
19
|
+
task :finish do
|
20
|
+
how_long=end_time
|
21
|
+
if how_long.nil?
|
22
|
+
puts "You must run start_time before you can call end_time"
|
23
|
+
else
|
24
|
+
puts ""
|
25
|
+
puts "deploy took: #{end_time} minutes"
|
26
|
+
puts ""
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
namespace :deploy do
|
2
|
+
namespace :web do
|
3
|
+
desc <<-DESC
|
4
|
+
Present a maintenance page to visitors. Disables your application's web \
|
5
|
+
interface by writing a "maintenance.html" file to each web server. The \
|
6
|
+
servers must be configured to detect the presence of this file, and if \
|
7
|
+
it is present, always display it instead of performing the request.
|
8
|
+
|
9
|
+
By default, the maintenance page will just say the site is down for \
|
10
|
+
"maintenance", and will be back "shortly", but you can customize the \
|
11
|
+
page by specifying the REASON environment variable:
|
12
|
+
|
13
|
+
$ cap deploy:web:disable \\
|
14
|
+
REASON="hardware upgrade"
|
15
|
+
|
16
|
+
Further customization will require that you write your own task.
|
17
|
+
DESC
|
18
|
+
#"/home/projectdx/projectdx-cms/current/public/system/maintenance.html"
|
19
|
+
maint_files=["#{shared_path}/system/maintenance.html",
|
20
|
+
]
|
21
|
+
|
22
|
+
task :disable, :roles => :web, :except => { :no_release => true } do
|
23
|
+
require 'erb'
|
24
|
+
on_rollback { maint_files.each do |file|
|
25
|
+
run "if [ -e #{file} ]; then rm #{file}; fi"
|
26
|
+
end
|
27
|
+
}
|
28
|
+
|
29
|
+
reason = ENV['REASON']
|
30
|
+
|
31
|
+
template = File.read("public/maintenance.rhtml")
|
32
|
+
result = ERB.new(template).result(binding)
|
33
|
+
maint_files.each do |file|
|
34
|
+
dir=File.dirname(file)
|
35
|
+
put result, "/tmp/disable_cap", :mode => 0644
|
36
|
+
run "if [ -d #{dir} -a \! -e #{file} ]; then mv /tmp/disable_cap #{file}; fi"
|
37
|
+
run "chcon -t httpd_sys_content_t #{file}; true" # we ignore this since some hosts have home on nfs
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
desc <<-DESC
|
42
|
+
Makes the application web-accessible again. Removes the \
|
43
|
+
"maintenance.html" page generated by deploy:web:disable, which (if your \
|
44
|
+
web servers are configured correctly) will make your application \
|
45
|
+
web-accessible again.
|
46
|
+
DESC
|
47
|
+
task :enable, :roles => :web, :except => { :no_release => true } do
|
48
|
+
maint_files.each do |file|
|
49
|
+
run "if [ -e #{file} ]; then rm #{file}; fi"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'capistrano'
|
2
|
+
Capistrano::Configuration.instance.load do
|
3
|
+
load_paths << File.dirname(__FILE__)+'/projectdx'
|
4
|
+
def to_minutes(seconds)
|
5
|
+
m = (seconds/60).floor
|
6
|
+
s = (seconds - (m * 60)).round
|
7
|
+
# add leading zero to one-digit minute
|
8
|
+
if m < 10
|
9
|
+
m = "0#{m}"
|
10
|
+
end
|
11
|
+
# add leading zero to one-digit second
|
12
|
+
if s < 10
|
13
|
+
s = "0#{s}"
|
14
|
+
end
|
15
|
+
# return formatted time
|
16
|
+
return "#{m}:#{s}"
|
17
|
+
end
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: capistrano-ext-projectdx
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Darrell Fuhriman
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-06-16 00:00:00 -07:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Local extensions to capistrano, which others may find useful
|
23
|
+
email:
|
24
|
+
- darrell@renewfund.com
|
25
|
+
executables: []
|
26
|
+
|
27
|
+
extensions: []
|
28
|
+
|
29
|
+
extra_rdoc_files: []
|
30
|
+
|
31
|
+
files:
|
32
|
+
- lib/capistrano/ext/projectdx/all.rb
|
33
|
+
- lib/capistrano/ext/projectdx/cache.rb
|
34
|
+
- lib/capistrano/ext/projectdx/campfire.rb
|
35
|
+
- lib/capistrano/ext/projectdx/docs.rb
|
36
|
+
- lib/capistrano/ext/projectdx/git_branch.rb
|
37
|
+
- lib/capistrano/ext/projectdx/misc.rb
|
38
|
+
- lib/capistrano/ext/projectdx/passenger.rb
|
39
|
+
- lib/capistrano/ext/projectdx/projectdx.rb
|
40
|
+
- lib/capistrano/ext/projectdx/time.rb
|
41
|
+
- lib/capistrano/ext/projectdx/web.rb
|
42
|
+
- lib/capistrano/ext/projectdx.rb
|
43
|
+
has_rdoc: true
|
44
|
+
homepage: http://github.com/projectdx/capistrano-ext-projectdx
|
45
|
+
licenses: []
|
46
|
+
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
hash: 23
|
67
|
+
segments:
|
68
|
+
- 1
|
69
|
+
- 3
|
70
|
+
- 6
|
71
|
+
version: 1.3.6
|
72
|
+
requirements: []
|
73
|
+
|
74
|
+
rubyforge_project: capistrano-ext-projectdx
|
75
|
+
rubygems_version: 1.3.7
|
76
|
+
signing_key:
|
77
|
+
specification_version: 3
|
78
|
+
summary: Local extensions to capistrano, which others may find useful
|
79
|
+
test_files: []
|
80
|
+
|