obbistrano 1.0.76

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.
@@ -0,0 +1,9 @@
1
+ h1. Automated Server and application deployment
2
+
3
+ h2. Application Deploy
4
+
5
+
6
+
7
+ h2. Server Initialisation and Setup
8
+
9
+
@@ -0,0 +1,45 @@
1
+ require 'rubygems'
2
+ require "httparty"
3
+
4
+ class GithubApi
5
+ include HTTParty
6
+ base_uri "https://github.com/api/v2/yaml"
7
+
8
+ attr_accessor :format, :login, :token, :repo, :base_uri
9
+
10
+ def initialize(login = nil, token = nil, format = "yaml")
11
+ @format = format
12
+ if login
13
+ @login = login
14
+ @token = token
15
+ end
16
+ end
17
+
18
+ def create_repo(params)
19
+ uri = uri = "#{self.class.base_uri}/repos/create"
20
+ post_params = {"login"=>@login, "token"=>@token}
21
+ self.class.post(uri, :query=>post_params.merge(params))
22
+ end
23
+
24
+ def add_collaborator(user)
25
+ uri = "#{self.class.base_uri}/repos/collaborators/#{@repo}/add/#{user}"
26
+ post_params = {"login"=>@login, "token"=>@token}
27
+ self.class.post(uri, :query=>post_params)
28
+ end
29
+
30
+ def add_key(params)
31
+ uri = "#{self.class.base_uri}/repos/key/#{@repo}/add"
32
+ post_params = {"login"=>@login, "token"=>@token}
33
+ params = post_params.merge(params)
34
+ self.class.post(uri, :query=>post_params.merge(params))
35
+ end
36
+
37
+ def create_issue(params)
38
+ uri = "#{self.class.base_uri}/issues/open/#{@login}/#{@repo}"
39
+ post_params = {"login"=>@login, "token"=>@token}
40
+ params = post_params.merge(params)
41
+ self.class.post(uri, :query=>post_params.merge(params))
42
+ end
43
+
44
+ end
45
+
@@ -0,0 +1,3 @@
1
+ require "slicehost"
2
+ require "githubapi"
3
+ require "obbistrano_tasks"
@@ -0,0 +1,415 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+
3
+ #### Performs the initial setup for tasks ####
4
+ task :config_setup do
5
+ set :root_pass, root rescue nil
6
+ set :environment, environment rescue set :environment, "production"
7
+ end
8
+
9
+
10
+ #### Slicehost Namespace.... Allows Auto Creation of DNS ####
11
+
12
+ namespace :slicehost do
13
+
14
+ desc "Sets up slicehost DNS for each of the servers specified with a role of web."
15
+ task :setup do
16
+ get_slice_ip
17
+ servers = find_servers :roles => :web
18
+ servers.each do |s|
19
+ if !zone = Zone.find(:first, :params => {:origin => "#{s}."})
20
+ zone = Zone.new(:origin => s, :ttl => TTL)
21
+ zone.save
22
+ end
23
+ recordOne = Record.new(:record_type => 'A', :zone_id => zone.id, :name => 'www', :data => "#{slice_ip}")
24
+ recordTwo = Record.new(:record_type => 'A', :zone_id => zone.id, :name => '@', :data => "#{slice_ip}")
25
+ recordThree = Record.new(:record_type => 'A', :zone_id => zone.id, :name => 'beta', :data => "#{slice_ip}")
26
+ recordFour = Record.new(:record_type => 'A', :zone_id => zone.id, :name => zone.origin, :data => "#{slice_ip}")
27
+ recordFive = Record.new(:record_type => 'NS', :zone_id => zone.id, :name => zone.origin, :data => 'ns1.slicehost.net.')
28
+ recordSix = Record.new(:record_type => 'NS', :zone_id => zone.id, :name => zone.origin, :data => 'ns2.slicehost.net.')
29
+ recordSeven = Record.new(:record_type => 'NS', :zone_id => zone.id, :name => zone.origin, :data => 'ns3.slicehost.net.')
30
+ [recordOne, recordTwo, recordThree, recordFour, recordFive, recordSix, recordSeven].each {|r| r.save}
31
+ end
32
+ end
33
+
34
+ task :get_slice_ip do
35
+ set :slice_ip, get_ip(fetch("host", false))
36
+ end
37
+
38
+ desc "Sets up slicehost DNS for Google Apps usage on each of the servers specified with a role of web."
39
+ task :googleapps do
40
+ SLICEHOST_API_PASSWORD = "#{slicehost_api_key}"
41
+ mx_records = <<-RECORD
42
+ ASPMX.L.GOOGLE.COM.
43
+ ALT1.ASPMX.L.GOOGLE.COM.
44
+ ALT2.ASPMX.L.GOOGLE.COM.
45
+ ASPMX2.GOOGLEMAIL.COM.
46
+ ASPMX3.GOOGLEMAIL.COM.
47
+ RECORD
48
+ servers = find_servers :roles => :web
49
+ servers.each do |s|
50
+ mx_aux = %w[5 10 10 20 20 30 ]
51
+ aux_count = 0
52
+ zone = Zone.find(:first, :params => {:origin => "#{s}."})
53
+ mx_records.each do |rec|
54
+ r = Record.new(:record_type => 'MX', :zone_id => zone.id, :name => "#{s}." , :data => "#{rec}", :aux => mx_aux[aux_count])
55
+ r.save
56
+ aux_count =+ 1
57
+ end
58
+ recordOne = Record.new(:record_type => 'CNAME', :zone_id => zone.id, :name => 'mail', :data => "ghs.google.com.")
59
+ recordTwo = Record.new(:record_type => 'CNAME', :zone_id => zone.id, :name => 'docs', :data => "ghs.google.com.")
60
+ [recordOne, recordTwo].each {|r| r.save}
61
+ end
62
+ end
63
+
64
+ end
65
+
66
+
67
+ #### Github Namespace.... Allows Auto Creation of Repository, ssh keys and Repo permissions ####
68
+
69
+ namespace :github do
70
+ task :setup do
71
+ puts "*** You need to specify a github login and token to run this operation" if !defined? "#{github_login}" || !defined? "#{github_token}"
72
+ exit if !defined? "#{github_login}" || !defined? "#{github_token}"
73
+ api = GithubApi.new("#{github_login}", "#{github_token}")
74
+ params = {
75
+ :name =>"#{application}",
76
+ :body =>"Project for #{application}",
77
+ :public =>0
78
+ }
79
+ api.create_repo(params)
80
+ api.repo = "#{application}"
81
+ api.add_collaborator("rossriley")
82
+ api.add_collaborator("Sheldon")
83
+ api.add_collaborator("charlesmarshall")
84
+ api.add_collaborator("MichalNoskovic")
85
+ app:ssh_key
86
+ server_ssh_key = capture("cat .ssh/id_rsa.pub")
87
+ server_ssh_key
88
+ api.add_key({:title=>"#{host}",:key=>server_ssh_key})
89
+ end
90
+
91
+
92
+ end
93
+
94
+ namespace :app do
95
+
96
+ task :config_check do
97
+ config_setup
98
+ databases rescue set(:databases, ["#{application}"])
99
+ aliases rescue set(:aliases, []);
100
+ end
101
+
102
+ task :needs_root do
103
+ config_check
104
+ puts "*** This operation needs root access - Please pass in a root password using -s root=password" if !defined? "#{root_pass}"
105
+ exit if !defined? "#{root_pass}"
106
+ end
107
+
108
+
109
+
110
+ # =============================================================================
111
+ # DEPLOYING APPLICATIONS
112
+ # =============================================================================
113
+
114
+ task :deploy do
115
+ config_check
116
+ deploy_check
117
+ php_wax_deploy if defined? "#{phpwax}"
118
+ cms_deploy if defined? "#{cms}"
119
+ css_build
120
+ js_build
121
+ end
122
+
123
+ task :deploy_check do
124
+ fetch "repository" rescue abort "You have not specified a repository for this application"
125
+ git_deploy if repository.include? "git"
126
+ svn_deploy if repository.include? "svn"
127
+ end
128
+
129
+ task :syncdb do
130
+ logger.level = -1
131
+ run "cd #{deploy_to} && script/syncdb #{environment}"
132
+ logger.level=2
133
+ logger.info "Application database has been synchronised"
134
+ end
135
+
136
+ task :git_deploy do
137
+ logger.level = 2
138
+ logger.info "Deploying application from #{repository} on branch #{branch}"
139
+ logger.level = -1
140
+ begin
141
+ run "ls #{deploy_to}/.git"
142
+ rescue
143
+ run "mkdir -p #{deploy_to}"
144
+ run "cd #{deploy_to} && git init"
145
+ run "cd #{deploy_to} && git remote add origin #{repository}"
146
+ end
147
+ logger.level = 2
148
+ run "cd #{deploy_to} && git fetch"
149
+ begin
150
+ run "cd #{deploy_to} && git checkout -b #{branch} origin/#{branch}"
151
+ rescue
152
+ run "cd #{deploy_to} && git pull origin #{branch}"
153
+ run "cd #{deploy_to} && git checkout #{branch}"
154
+ run "cd #{deploy_to} && git checkout #{commit}" if defined? "#{commit}"
155
+ end
156
+
157
+ logger.info "Application has been updated on branch #{branch}"
158
+ end
159
+
160
+ task :svn_deploy do
161
+ run "svn export #{repository} #{deploy_to} --force"
162
+ end
163
+
164
+ task :cms_deploy do
165
+ logger.level = -1
166
+ run "mkdir -p #{deploy_to}/plugins/cms"
167
+ begin
168
+ run "ls #{deploy_to}/plugins/cms/.git/"
169
+ rescue
170
+ logger.level = 2
171
+ logger.info "Initialising Wildfire Folder"
172
+ run "cd #{deploy_to}/plugins/cms && git init"
173
+ run "cd #{deploy_to}/plugins/cms && git remote add origin git://github.com/phpwax/wildfire.git"
174
+ end
175
+ logger.info "Updating Wildfire Code from remote"
176
+ run "cd #{deploy_to}/plugins/cms && git fetch"
177
+ logger.level = -1
178
+ begin
179
+ run "cd #{deploy_to}/plugins/cms && git checkout -b #{cms} origin/#{cms}"
180
+ rescue
181
+ run "cd #{deploy_to}/plugins/cms && git checkout #{cms}"
182
+ end
183
+ run "cd #{deploy_to}/plugins/cms && git pull origin #{cms}"
184
+ logger.level = 2
185
+ logger.info "Wildfire CMS has been updated on branch #{cms}"
186
+ end
187
+
188
+
189
+ task :php_wax_deploy do
190
+ logger.level = -1
191
+ run "mkdir -p #{deploy_to}/wax"
192
+ begin
193
+ run "ls #{deploy_to}/wax/.git/"
194
+ rescue
195
+ logger.level = 2
196
+ logger.info "Initialising PHP Wax Folder"
197
+ run "cd #{deploy_to}/wax && git init"
198
+ run "cd #{deploy_to}/wax && git remote add origin git://github.com/phpwax/phpwax.git"
199
+ end
200
+ logger.info "Updating PHP Wax Code from remote"
201
+ run "cd #{deploy_to}/wax && git fetch"
202
+ logger.level = -1
203
+ begin
204
+ run "cd #{deploy_to}/wax && git checkout -b #{phpwax} origin/#{phpwax}"
205
+ rescue
206
+ run "cd #{deploy_to}/wax && git checkout #{phpwax}"
207
+ end
208
+ run "cd #{deploy_to}/wax && git pull origin #{phpwax}"
209
+ logger.level = 3
210
+ logger.info "PHP Wax has been updated on branch #{phpwax}"
211
+ end
212
+
213
+
214
+ task :css_build do
215
+ set :css_files, Dir.glob("**/*.css") if !defined? "#{css_files}"
216
+ run "cd #{deploy_to} && rm -f public/stylesheets/build.css"
217
+ css_files.each do |f|
218
+ run "cd #{deploy_to} && cat #{f} >> #{deploy_to}/public/stylesheets/build.css"
219
+ end
220
+ end
221
+
222
+ task :js_build do
223
+ set :js_files, Dir.glob("**/*.js") if !defined? "#{js_files}"
224
+ run "cd #{deploy_to} && rm -f public/javascripts/build.js"
225
+ js_files.each do |f|
226
+ run "cd #{deploy_to} && cat #{f} >> #{deploy_to}/public/javascripts/build.js"
227
+ end
228
+ end
229
+ ####### ##############
230
+
231
+
232
+ # =============================================================================
233
+ # GENERAL ADMIN FOR APPLICATIONS
234
+ # =============================================================================
235
+
236
+ desc "Restarts the Apache Server. Requires root password to access."
237
+ task :restart do
238
+ config_check
239
+ needs_root
240
+ with_user("root", "#{root_pass}") do
241
+ run "/etc/rc.d/init.d/httpd restart"
242
+ end
243
+ end
244
+
245
+ desc "Clears the application's cache files from tmp/cache."
246
+ task :clearcache do
247
+ run "cd #{deploy_to} && rm -f tmp/cache/*"
248
+ end
249
+
250
+ desc "Clears the application's log files from tmp/log."
251
+ task :clearlogs do
252
+ run "cd #{deploy_to} && rm -f tmp/log/*"
253
+ end
254
+
255
+
256
+
257
+ # =============================================================================
258
+ # USER AND APPLICATION SETUP AND INITIALISATION
259
+ # =============================================================================
260
+
261
+ task :setup do
262
+ config_check
263
+ try_login
264
+ setup_mysql
265
+ vhost
266
+ ssh_key
267
+ end
268
+
269
+
270
+ task :setup_user do
271
+ needs_root
272
+ set :user_to_add, "#{user}"
273
+ set :passwd_to_add, "#{password}"
274
+ with_user("root", "#{root_pass}") do
275
+ run "useradd -p `openssl passwd #{passwd_to_add}` #{user_to_add}"
276
+ run "chmod -R 0755 /home/#{user_to_add}"
277
+ end
278
+ end
279
+
280
+ task :setup_mysql do
281
+ needs_root
282
+ set :user_to_add, "#{user}"
283
+ set :passwd_to_add, "#{password}"
284
+ with_user("root", "#{root_pass}") do
285
+ "#{databases}".each do |db|
286
+ begin
287
+ run "mysql -uroot -p#{root_pass} -e \"CREATE USER '#{user_to_add}'@'localhost' IDENTIFIED BY '#{passwd_to_add}';\""
288
+ run "mysql -uroot -p#{root_pass} -e 'CREATE DATABASE #{db}'"
289
+ run "musql -uroot -p#{root_pass} -e \"GRANT ALL PRIVILEGES ON `#{db}` . * TO '#{user_to_add}'@'localhost' IDENTIFIED BY '#{passwd_to_add}';\""
290
+ rescue
291
+ logger.info "Database #{db} already exists"
292
+ end
293
+ end
294
+ end
295
+
296
+ end
297
+
298
+ task :try_login do
299
+ config_check
300
+ begin
301
+ run "ls"
302
+ puts "Logged in ok"
303
+ rescue
304
+ print "==== The user does not yet exist. Would you like to create? [Y/N]"
305
+ line = STDIN.gets.upcase.strip
306
+ puts "*** Could not continue as the login does not exist" if line !="Y"
307
+ exit if line != "Y"
308
+ setup_user
309
+ end
310
+ end
311
+
312
+ desc "Creates or gets an ssh key for the application"
313
+ task :ssh_key do
314
+ config_check
315
+ begin
316
+ run "cat .ssh/id_rsa.pub"
317
+ rescue
318
+ run "mkdir -p .ssh/"
319
+ run "ssh-keygen -t rsa -f .ssh/id_rsa -N ''"
320
+ run "cat .ssh/id_rsa.pub"
321
+ end
322
+ end
323
+
324
+ desc "Creates an Apache virtual host file"
325
+ task :vhost do
326
+ config_check
327
+ needs_root
328
+ with_user("root", "#{root_pass}") do
329
+ public_ip = ""
330
+ run "ifconfig eth0 | grep inet | awk '{print $2}' | sed 's/addr://'" do |_, _, public_ip| end
331
+ public_ip = public_ip.strip
332
+ roles[:web].servers.each do |webserver|
333
+ f = File.open(File.join(File.dirname(__FILE__), 'templates/apache_vhost.erb' ))
334
+ contents = f.read
335
+ f.close
336
+ buffer = ERB.new(contents)
337
+ config = buffer.result(binding())
338
+ put config, "/etc/httpd/conf.d/#{webserver}-apache-vhost.conf"
339
+ end
340
+ end
341
+ restart
342
+ end
343
+
344
+
345
+
346
+ # =============================================================================
347
+ # +MIGRATING+ APPLICATIONS
348
+ # =============================================================================
349
+
350
+ task :copy_site do
351
+ config_check
352
+ needs_root
353
+ backup
354
+ print "==== Which server would you like to copy #{application} to? [Full Domain Name] "
355
+ line = STDIN.gets.strip
356
+ begin
357
+ new_server = options["servers"][line]["domain"]
358
+ rescue
359
+ puts "*** Can't find that new server in the config"
360
+ exit
361
+ end
362
+ with_user("root", "#{root_pass}") do
363
+ run "rsync -avzh . -e ssh root@#{new_server}:/backup/#{application}/ --exclude 'tmp/*' --exclude '.git/*'"
364
+ end
365
+ options["apps"]["#{application}"]["server"] = line
366
+ config_write
367
+ try_login
368
+ restore
369
+ end
370
+
371
+ end
372
+
373
+
374
+ def get_ip(domain)
375
+ require 'socket'
376
+ t = TCPSocket.gethostbyname(domain)
377
+ t[3]
378
+ end
379
+
380
+ def with_user(new_user, new_pass, &block)
381
+ old_user, old_pass = user, password
382
+ set :user, new_user
383
+ set :password, new_pass
384
+ close_sessions
385
+ yield
386
+ set :user, old_user
387
+ set :password, old_pass
388
+ close_sessions
389
+ end
390
+ def close_sessions
391
+ sessions.values.each { |session| session.close }
392
+ sessions.clear
393
+ end
394
+
395
+
396
+ namespace :deploy do
397
+ desc "Uses the specified repository to deploy an application. Also checks for correct versions of PHPWax and plugins."
398
+ task :default do
399
+ logger.level=-1
400
+ app.deploy
401
+ end
402
+ end
403
+
404
+ namespace :setup do
405
+ desc "Sets up the server with a user, home directory and mysql login."
406
+ task :default do
407
+ app.setup
408
+ end
409
+ end
410
+
411
+ end
412
+
413
+
414
+
415
+
@@ -0,0 +1,16 @@
1
+ require 'rubygems'
2
+ require 'activeresource'
3
+
4
+ TTL = 86400
5
+
6
+ class Record < ActiveResource::Base
7
+ self.site = "https://#{SLICEHOST_API_PASSWORD}@api.slicehost.com/"
8
+ end
9
+
10
+ class Zone < ActiveResource::Base
11
+ self.site = "https://#{SLICEHOST_API_PASSWORD}@api.slicehost.com/"
12
+ end
13
+
14
+ class Slice < ActiveResource::Base
15
+ self.site = "https://#{SLICEHOST_API_PASSWORD}@api.slicehost.com/"
16
+ end
@@ -0,0 +1,16 @@
1
+ <VirtualHost <%=public_ip%>:80>
2
+ ServerName <%=webserver%>
3
+ <%aliases.each do |aliass|%>
4
+ ServerAlias <%=aliass%>
5
+ <%end%>
6
+ DocumentRoot /home/<%=application%>/<%=deploy_to%>/public
7
+ DirectoryIndex index.html index.htm index.php
8
+ AddOutputFilterByType DEFLATE text/html text/plain text/xml application/x-javascript text/css
9
+ SetOutputFilter DEFLATE
10
+
11
+ <Directory /home/<%=application%>/<%=deploy_to%>/public>
12
+ Options Indexes IncludesNOEXEC FollowSymLinks
13
+ allow from all
14
+ AllowOverride All
15
+ </Directory>
16
+ </VirtualHost>
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{obbistrano}
5
+ s.version = "1.0.76"
6
+ s.authors = ["Ross Riley", "One Black Bear"]
7
+ s.date = Time.now
8
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
9
+ s.require_paths = ["lib"]
10
+ s.description = %q{An extension to Capistrano to allow deploys to Slicehost for One Black Bear}
11
+ s.email = %q{ross@oneblackbear.com}
12
+ s.files = ["README.textile", "obbistrano.gemspec", "lib/obbistrano.rb","lib/githubapi.rb", "lib/slicehost.rb", "lib/obbistrano_tasks.rb", "lib/templates/apache_vhost.erb"]
13
+ s.homepage = %q{http://github.com/oneblackbear/obbistrano}
14
+ s.rubygems_version = %q{1.3.0}
15
+ s.summary = %q{Adds extra namespaces to Capistrano to allow simple setup, deploys and maintenance.}
16
+ if s.respond_to? :specification_version then
17
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
18
+ s.specification_version = 2
19
+
20
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
21
+ s.add_runtime_dependency(%q<capistrano>, [">= 2.5"])
22
+ s.add_runtime_dependency(%q<activeresource>, [">= 2"])
23
+ s.add_runtime_dependency(%q<httparty>, [">= 0.4.3"])
24
+ else
25
+ s.add_dependency(%q<capistrano>, [">= 2.5"])
26
+ s.add_dependency(%q<activeresource>, [">= 2"])
27
+ s.add_dependency(%q<httparty>, [">= 0.4.3"])
28
+ end
29
+ else
30
+ s.add_dependency(%q<capistrano>, [">= 2.5"])
31
+ s.add_dependency(%q<activeresource>, [">= 2"])
32
+ s.add_dependency(%q<httparty>, [">= 0.4.3"])
33
+ end
34
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: obbistrano
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.76
5
+ platform: ruby
6
+ authors:
7
+ - Ross Riley
8
+ - One Black Bear
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-10-08 00:00:00 +01:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: capistrano
18
+ type: :runtime
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "2.5"
25
+ version:
26
+ - !ruby/object:Gem::Dependency
27
+ name: activeresource
28
+ type: :runtime
29
+ version_requirement:
30
+ version_requirements: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "2"
35
+ version:
36
+ - !ruby/object:Gem::Dependency
37
+ name: httparty
38
+ type: :runtime
39
+ version_requirement:
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: 0.4.3
45
+ version:
46
+ description: An extension to Capistrano to allow deploys to Slicehost for One Black Bear
47
+ email: ross@oneblackbear.com
48
+ executables: []
49
+
50
+ extensions: []
51
+
52
+ extra_rdoc_files: []
53
+
54
+ files:
55
+ - README.textile
56
+ - obbistrano.gemspec
57
+ - lib/obbistrano.rb
58
+ - lib/githubapi.rb
59
+ - lib/slicehost.rb
60
+ - lib/obbistrano_tasks.rb
61
+ - lib/templates/apache_vhost.erb
62
+ has_rdoc: true
63
+ homepage: http://github.com/oneblackbear/obbistrano
64
+ licenses: []
65
+
66
+ post_install_message:
67
+ rdoc_options: []
68
+
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "0"
76
+ version:
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: "0"
82
+ version:
83
+ requirements: []
84
+
85
+ rubyforge_project:
86
+ rubygems_version: 1.3.4
87
+ signing_key:
88
+ specification_version: 2
89
+ summary: Adds extra namespaces to Capistrano to allow simple setup, deploys and maintenance.
90
+ test_files: []
91
+