marcosgz-cap-recipe 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -3,3 +3,5 @@
3
3
  Gemfile.lock
4
4
  pkg/*
5
5
  .DS_Store
6
+ .rvmrc
7
+ /examples
data/Gemfile CHANGED
@@ -1 +1,7 @@
1
1
  source "http://rubygems.org"
2
+
3
+ gem "pry"
4
+ gem "rails"
5
+
6
+ # Specify your gem's dependencies in capistrano-template.gemspec
7
+ gemspec
data/README.md CHANGED
@@ -5,3 +5,126 @@ Under development
5
5
  ```ruby
6
6
  require 'capistrano/recipe'
7
7
  ```
8
+
9
+ ## Required configs
10
+ ```ruby
11
+ set :user, 'admin'
12
+ set :group, 'admin'
13
+ set :domain, 'www.example.com'
14
+ ```
15
+
16
+ ### Unicorn
17
+ ```ruby
18
+ set :unicorn_setup_settings, {
19
+ port: 80
20
+ }
21
+ ```
22
+
23
+ ### Passenger
24
+ ```ruby
25
+ set :passenger_setup_settings, {
26
+ port: 80
27
+ }
28
+ ```
29
+
30
+ ### Thin
31
+ ```ruby
32
+ set :thin_setup_settings, {
33
+ port: 80
34
+ }
35
+ ```
36
+
37
+ ### Database
38
+ ```ruby
39
+ set :db_setup_settings, {
40
+ common: {
41
+ host: '127.0.0.1',
42
+ database: 'db_name'
43
+ }
44
+ }
45
+ ```
46
+
47
+ ### Gateways
48
+ ```ruby
49
+ set :gateways_setup_settings, {
50
+ common: {
51
+ example: {
52
+ username: 'foo',
53
+ password: 'bar'
54
+ }
55
+ }
56
+ }
57
+ ```
58
+
59
+ ### Mailers
60
+ ```ruby
61
+ set :mailer_setup_settings, {
62
+ common: {
63
+ user_name: "email@example.com",
64
+ password: "secret"
65
+ }
66
+ }
67
+ ```
68
+
69
+ ### Newrelic
70
+ ```ruby
71
+ set :newrelic_setup_settings, {
72
+ common: {
73
+ app_name: 'AppName',
74
+ license_key: 'secret'
75
+ },
76
+ staging: {
77
+ app_name: 'AppName (Staging)'
78
+ }
79
+ }
80
+ ```
81
+
82
+ ### Settler
83
+ ```ruby
84
+ set :settler_setup_settings, {
85
+ name: 'String Text', # "name" => {"alt"=>"name", "value"=>"String Text"}
86
+ price: 100.0, # "price" => {"alt"=>"price", "value"=>"100.0", "typecast"=>"float"}
87
+ views: 9, # "views" => {"alt"=>"views", "value"=>"9", "typecast"=>"integer"}
88
+ approved: true, # "approved" => {"alt"=>"approved", "value"=>"true", "typecast"=>"boolean"}
89
+ deleted: false, # "deleted" => {"alt"=>"deleted", "value"=>"false", "typecast"=>"boolean"}
90
+ published_at: Time.now, # "published_at"=> {"alt"=>"published_at", "value"=>"2013-04-03 16:25:26 -0300", "typecast"=>"datetime"}
91
+ password: { # "password" => {"alt"=>"Password", "value"=>"secret", "typecast"=>"password"}
92
+ alt: 'Password',
93
+ value: 'secret',
94
+ typecast: 'password'
95
+ }
96
+ }
97
+
98
+ ```
99
+
100
+ ### Shards
101
+ ```ruby
102
+ set :shards_setup_settings, {
103
+ databases: {
104
+ production:{
105
+ slave1: {}
106
+ }
107
+ }
108
+ }
109
+ ```
110
+
111
+ ### Tire
112
+ ```ruby
113
+ set :tire_setup_settings, {
114
+ common: {
115
+ url: "http://localhost:9200"
116
+ }
117
+ }
118
+ ```
119
+
120
+ ### Uploader
121
+ ```ruby
122
+ set :uploader_setup_settings, {
123
+ common: {
124
+ fog_credentials: {
125
+ provider: 'Rackspace'
126
+ },
127
+ fog_directory: 'public_assets'
128
+ }
129
+ }
130
+ ```
@@ -1,5 +1,18 @@
1
1
  require 'active_support/core_ext/hash/reverse_merge'
2
2
  require 'active_support/core_ext/hash/slice'
3
+ require 'active_support/core_ext/hash/deep_merge'
4
+ require 'active_support/core_ext/hash/indifferent_access'
3
5
  require 'capistrano'
4
6
 
5
7
  Dir.glob(File.join(File.dirname(__FILE__), '/recipes/*.rb')).sort.each { |f| load f }
8
+
9
+ class DeepToHash
10
+ def self.to_hash(value)
11
+ case value
12
+ when Hash
13
+ Hash[value.to_hash.map { |key, value| [key, to_hash(value)] }]
14
+ else
15
+ value
16
+ end
17
+ end
18
+ end
@@ -1,14 +1,10 @@
1
1
  Capistrano::Configuration.instance(:must_exist).load do
2
2
 
3
3
  set :app_setup_defaults, %w(app:create:dirs app:create:application_server db:setup)
4
- set :app_setup_aditional, [] unless exists?(:app_setup_aditional)
5
-
6
- set :user, 'app' unless exists?(:user)
7
- set :group, 'app' unless exists?(:group)
8
4
 
9
5
  namespace :app do
10
6
  task :setup, :roles => :app do
11
- (fetch(:app_setup_defaults)+fetch(:app_setup_aditional)).each do |name|
7
+ (fetch(:app_setup_defaults)+_app_setup_aditional).each do |name|
12
8
  if (t=top.find_task(name))
13
9
  execute_task(t)
14
10
  end
@@ -74,4 +70,23 @@ Capistrano::Configuration.instance(:must_exist).load do
74
70
 
75
71
  end
76
72
 
73
+ def _app_setup_aditional
74
+ fetch(:app_setup_aditional, [])
75
+ end
76
+
77
+ def fetch_user
78
+ fetch(:user, 'app')
79
+ end
80
+
81
+ def fetch_group
82
+ fetch(:group, 'app')
83
+ end
84
+
85
+ def default_rails_environments_hash
86
+ default_rails_environments.inject({}){|r, v| r.merge Hash[v, {}] }
87
+ end
88
+
89
+ def default_rails_environments
90
+ fetch(:rails_environments, %w(production development staging test))
91
+ end
77
92
  end
@@ -1,53 +1,14 @@
1
- # Example
2
- # =======
3
- #
4
- # db_setup_settings:
5
- # common:
6
- # host: 127.0.0.1
7
- # database: db_name
8
-
9
1
  Capistrano::Configuration.instance(:must_exist).load do
10
- set(:database_remote_file) { File.join(shared_path, 'config/database.yml') } unless exists?(:database_remote_file)
11
- set(:database_template, 'database.yml.erb') unless exists?(:database_template)
12
-
13
- def database_setup_defaults
14
- {
15
- 'common' => {
16
- 'adapter' => fetch(:database_adapter, 'mysql2'),
17
- 'encoding' => fetch(:database_encoding, 'utf8'),
18
- 'reconnect' => fetch(:database_reconnect, false),
19
- 'pool' => fetch(:database_pool, 2),
20
- 'username' => fetch(:database_username) { user },
21
- 'password' => self[:database_password],
22
- 'host' => self[:database_host]
23
- },
24
- 'development' => {},
25
- 'staging' => {},
26
- 'production' => {},
27
- 'test' => {}
28
- }
29
- end
30
-
31
- # task: `database:setup'
32
- def database_template_settings
33
- fetch(:db_setup_settings, {}).reverse_merge(
34
- database_setup_defaults.keys.inject({}) {|r, e| r.merge Hash[e, Hash.new] }
35
- ).inject({}) do |r, (k,v)|
36
- r.merge Hash[k, v.reverse_merge(database_setup_defaults[k] || {})]
37
- end
38
- end
39
-
40
2
  # Required attributes
41
3
  # ===================
42
4
  # *database_name* prod_db
43
5
  namespace :db do
44
-
45
6
  namespace :setup do
46
7
  desc "Upload configs"
47
8
  task :default, :roles => :app do
48
9
  if exists?(:db_setup_settings)
49
10
  set(:recipe_settings, database_template_settings)
50
- put template.render(fetch(:database_template)), fetch(:database_remote_file)
11
+ put template.render(_database_template), _database_remote_path
51
12
  else
52
13
  puts "[FATAL] - Database template settings were not found"
53
14
  abort
@@ -56,9 +17,38 @@ Capistrano::Configuration.instance(:must_exist).load do
56
17
 
57
18
  desc "Download configs"
58
19
  task :get, :roles => :db do
59
- download fetch(:database_remote_file), File.join(local_rails_root, 'config/database.yml')
20
+ download _database_remote_path, _database_local_path
60
21
  end
61
22
  end
23
+ end
62
24
 
25
+ def database_setup_defaults
26
+ HashWithIndifferentAccess.new({
27
+ 'common' => {
28
+ 'adapter' => fetch(:database_adapter, 'mysql2'),
29
+ 'encoding' => fetch(:database_encoding, 'utf8'),
30
+ 'reconnect' => fetch(:database_reconnect, false),
31
+ 'username' => fetch(:database_username) { fetch_user },
32
+ 'password' => self[:database_password],
33
+ 'host' => fetch(:database_host, '127.0.1.1')
34
+ }
35
+ }.reverse_merge(default_rails_environments_hash))
36
+ end
37
+
38
+ def database_template_settings
39
+ DeepToHash.to_hash database_setup_defaults.deep_merge(fetch(:db_setup_settings, {}))
40
+ end
41
+
42
+ def _database_remote_path
43
+ File.join(shared_path, fetch(:database_remote_path, 'config/database.yml'))
44
+ end
45
+
46
+ def _database_local_path
47
+ File.join(local_rails_root, fetch(:database_local_path, 'config/database.yml'))
48
+ end
49
+
50
+ def _database_template
51
+ fetch(:database_template, 'database.yml.erb')
63
52
  end
53
+
64
54
  end
@@ -1,36 +1,42 @@
1
- # Example
2
- # =======
3
- #
4
- # gateways_setup_settings:
5
- # example1:
6
- # login: 'username'
7
- # password: 'secret'
8
-
9
1
  Capistrano::Configuration.instance(:must_exist).load do
10
- set(:gateways_remote_file) { File.join(shared_path, 'config/gateways.yml') } unless exists?(:gateways_remote_file)
11
- set(:gateways_template, 'gateways.yml.erb') unless exists?(:gateways_template)
12
-
13
2
 
14
- # Required attributes
15
- # ===================
16
- # *gateways_name* prod_db
17
3
  namespace :gateways do
18
4
  namespace :setup do
19
5
  desc "Upload configs"
20
6
  task :default, :roles => :app do
21
7
  if exists?(:gateways_setup_settings)
22
- set(:recipe_settings) { fetch(:gateways_setup_settings, {}) }
23
- put template.render(fetch(:gateways_template)), fetch(:gateways_remote_file)
8
+ set(:recipe_settings) { gateways_template_settings }
9
+ put template.render(_gateways_template), _gateways_remote_file
24
10
  else
25
- puts "[FATAL] - Gateway template settings were not found"
11
+ puts "[FATAL] - Gateways template settings were not found"
26
12
  abort
27
13
  end
28
14
  end
29
15
 
30
16
  desc "Download configs"
31
17
  task :get, :roles => :db do
32
- download fetch(:gateways_remote_file), File.join(local_rails_root, 'config/gateways.yml')
18
+ download _gateways_remote_file, _gateways_local_file
33
19
  end
34
20
  end
35
21
  end
22
+
23
+ def gateways_setup_defaults
24
+ HashWithIndifferentAccess.new({'common'=>{}}.reverse_merge(default_rails_environments_hash))
25
+ end
26
+
27
+ def gateways_template_settings
28
+ DeepToHash.to_hash gateways_setup_defaults.deep_merge(fetch(:gateways_setup_settings, {}))
29
+ end
30
+
31
+ def _gateways_remote_file
32
+ File.join(shared_path, fetch(:gateways_remote_file, 'config/gateways.yml'))
33
+ end
34
+
35
+ def _gateways_local_file
36
+ File.join(local_rails_root, fetch(:gateways_local_file, 'config/gateways.yml'))
37
+ end
38
+
39
+ def _gateways_template
40
+ fetch(:gateways_template, 'gateways.yml.erb')
41
+ end
36
42
  end
@@ -1,22 +1,11 @@
1
- # Example
2
- # =======
3
- #
4
- # mailer_setup_settings:
5
- # user_name: "email@example.com"
6
- # password: "secret"
7
-
8
1
  Capistrano::Configuration.instance(:must_exist).load do
9
-
10
- set(:mailer_remote_file) { File.join(shared_path, 'config/mailers.yml') } unless exists?(:mailer_remote_file)
11
- set(:mailer_template, 'mailers.yml.erb') unless exists?(:mailer_template)
12
-
13
2
  namespace :mailer do
14
3
  namespace :setup do
15
4
  desc "Upload configs"
16
5
  task :default, :roles => :app do
17
6
  if exists?(:mailer_setup_settings)
18
- set :recipe_settings, fetch(:mailer_setup_settings, {})
19
- put template.render(fetch(:mailer_template)), fetch(:mailer_remote_file)
7
+ set(:recipe_settings) { mailer_template_settings }
8
+ put template.render(_mailer_template), _mailer_remote_file
20
9
  else
21
10
  puts "[FATAL] - Mailers template settings were not found"
22
11
  abort
@@ -25,8 +14,28 @@ Capistrano::Configuration.instance(:must_exist).load do
25
14
 
26
15
  desc "Download configs"
27
16
  task :get, :roles => :db do
28
- download fetch(:mailer_remote_file), File.join(local_rails_root, 'config/mailers.yml')
17
+ download _mailer_remote_file, _mailer_local_file
29
18
  end
30
19
  end
31
20
  end
21
+
22
+ def mailer_setup_defaults
23
+ HashWithIndifferentAccess.new({'common'=>{}}.reverse_merge(default_rails_environments_hash))
24
+ end
25
+
26
+ def mailer_template_settings
27
+ DeepToHash.to_hash mailer_setup_defaults.deep_merge(fetch(:mailer_setup_settings, {}))
28
+ end
29
+
30
+ def _mailer_remote_file
31
+ File.join(shared_path, fetch(:mailer_remote_file, 'config/mailers.yml'))
32
+ end
33
+
34
+ def _mailer_local_file
35
+ File.join(local_rails_root, fetch(:mailer_local_file, 'config/mailers.yml'))
36
+ end
37
+
38
+ def _mailer_template
39
+ fetch(:mailer_template, 'mailers.yml.erb')
40
+ end
32
41
  end
@@ -1,19 +1,30 @@
1
- # Example
2
- # =======
3
- #
4
- # newrelic_setup_settings:
5
- # common:
6
- # app_name: AppName
7
- # license_key: secret
8
- # staging:
9
- # app_name: AppName (Staging)
10
-
11
1
  Capistrano::Configuration.instance(:must_exist).load do
12
- set(:newrelic_remote_file) { File.join(shared_path, 'config/newrelic.yml') } unless exists?(:newrelic_remote_file)
13
- set(:newrelic_template, 'newrelic.yml.erb') unless exists?(:newrelic_template)
2
+ # Required attributes
3
+ # ===================
4
+ # *license_key* 123xyz
5
+ # *app_name* Production App
6
+ namespace :newrelic do
7
+ namespace :setup do
8
+ desc "Upload configs"
9
+ task :default, :roles => :app do
10
+ if exists?(:newrelic_setup_settings)
11
+ set(:recipe_settings) { newrelic_template_settings }
12
+ put template.render(_newrelic_template), _newrelic_remote_path
13
+ else
14
+ puts "[FATAL] - Newrelic template settings were not found"
15
+ abort
16
+ end
17
+ end
18
+
19
+ desc "Download configs"
20
+ task :get, :roles => :db do
21
+ download _newrelic_remote_path, _newrelic_local_path
22
+ end
23
+ end
24
+ end
14
25
 
15
26
  def newrelic_setup_defaults
16
- {
27
+ HashWithIndifferentAccess.new({
17
28
  'common' => {
18
29
  # ============================== LICENSE KEY ===============================
19
30
 
@@ -175,39 +186,22 @@ Capistrano::Configuration.instance(:must_exist).load do
175
186
  'staging' => {'developer_mode' => true},
176
187
  'test' => {},
177
188
  'production' => {'monitor_mode' => true}
178
- }
189
+ }.reverse_merge(default_rails_environments_hash))
179
190
  end
180
191
 
181
- # task: `newrelic:setup'
182
192
  def newrelic_template_settings
183
- fetch(:newrelic_setup_settings, {}).reverse_merge(
184
- newrelic_setup_defaults.keys.inject({}) {|r, e| r.merge Hash[e, Hash.new] }
185
- ).inject({}) do |r, (k,v)|
186
- r.merge Hash[k, v.reverse_merge(newrelic_setup_defaults[k] || {})]
187
- end
193
+ DeepToHash.to_hash newrelic_setup_defaults.deep_merge(fetch(:newrelic_setup_settings, {}))
188
194
  end
189
195
 
190
- # Required attributes
191
- # ===================
192
- # *license_key* 123xyz
193
- # *app_name* Production App
194
- namespace :newrelic do
195
- namespace :setup do
196
- desc "Upload configs"
197
- task :default, :roles => :app do
198
- if exists?(:newrelic_setup_settings)
199
- set(:recipe_settings) { newrelic_template_settings }
200
- put template.render(fetch(:newrelic_template)), fetch(:newrelic_remote_file)
201
- else
202
- puts "[FATAL] - Newrelic template settings were not found"
203
- abort
204
- end
205
- end
196
+ def _newrelic_remote_path
197
+ File.join(shared_path, fetch(:newrelic_remote_path, 'config/newrelic.yml'))
198
+ end
206
199
 
207
- desc "Download configs"
208
- task :get, :roles => :db do
209
- download fetch(:newrelic_remote_file), File.join(local_rails_root, 'config/newrelic.yml')
210
- end
211
- end
200
+ def _newrelic_local_path
201
+ File.join(local_rails_root, fetch(:newrelic_local_path, 'config/newrelic.yml'))
202
+ end
203
+
204
+ def _newrelic_template
205
+ fetch(:newrelic_template, 'newrelic.yml.erb')
212
206
  end
213
207
  end
@@ -1,33 +1,5 @@
1
- # Example
2
- # =======
3
- #
4
- # passenger_setup_settings:
5
- # port: 80
6
- # auth_user_file: '/path/to/htpasswd'
7
-
8
1
  Capistrano::Configuration.instance(:must_exist).load do
9
2
 
10
- # task: `passenger:setup'
11
- def passenger_template_settings
12
- fetch(:passenger_setup_settings, {}).reverse_merge({
13
- 'sites_available' => fetch(:apache_sites_available, "/home/#{user}/configs/apache/sites-available"),
14
- 'sites_enabled' => fetch(:apache_sites_enabled, "/home/#{user}/configs/apache/sites-enabled"),
15
- 'vhost_filename' => fetch(:apache_vhost_filename) { "#{application}.conf" },
16
- 'template_filename' => fetch(:apache_template_filename) { 'passenger.conf.erb' },
17
- 'server_name' => fetch(:domain),
18
- 'document_root' => File.join(fetch(:current_path), 'public'),
19
- 'rails_env' => fetch(:rails_env, 'production')
20
- })
21
- end
22
-
23
- def apache_available_vhost
24
- File.join(*passenger_template_settings.slice('sites_available', 'vhost_filename').values)
25
- end
26
-
27
- def apache_enabled_vhost
28
- File.join(*passenger_template_settings.slice('sites_enabled', 'vhost_filename').values)
29
- end
30
-
31
3
  namespace :passenger do
32
4
  desc "Restart Rails app running under Phusion Passenger by touching restart.txt"
33
5
  task :restart, :roles => :app, :except => { :no_release => true } do
@@ -47,26 +19,26 @@ Capistrano::Configuration.instance(:must_exist).load do
47
19
  desc "Remove passenger config"
48
20
  task :remove, :roles => :app, :except => { :no_release => true } do
49
21
  passenger.disable
50
- run "rm #{apache_available_vhost}"
22
+ run "rm #{_passenger_available_vhost}"
51
23
  end
52
24
 
53
25
  desc "Disable passenger config"
54
26
  task :disable, :roles => :app, :except => { :no_release => true } do
55
- run "rm #{apache_enabled_vhost}"
27
+ run "rm #{_passenger_enabled_vhost}"
56
28
  end
57
29
 
58
30
  desc "Enable passenger config"
59
31
  task :enable, :roles => :app, :except => { :no_release => true } do
60
- run "ln -nsf #{apache_available_vhost} #{apache_enabled_vhost}"
32
+ run "ln -nsf #{_passenger_available_vhost} #{_passenger_enabled_vhost}"
61
33
  end
62
34
 
63
35
  namespace :setup do
64
36
  desc "Upload configs"
65
37
  task :default, :roles => :app do
66
38
  if exists?(:passenger_setup_settings)
67
- run "mkdir -p #{ passenger_template_settings.slice('sites_available', 'sites_enabled').map{|k,v| v}.join(' ') }"
39
+ run "mkdir -p #{_passenger_sites_available} #{_passenger_sites_enabled}"
68
40
  set(:recipe_settings) { passenger_template_settings }
69
- put template.render( passenger_template_settings['template_filename'] ), apache_available_vhost
41
+ put template.render(_passenger_template), _passenger_available_vhost
70
42
  passenger.enable
71
43
  else
72
44
  puts "[FATAL] - Passenger template settings were not found"
@@ -81,4 +53,40 @@ Capistrano::Configuration.instance(:must_exist).load do
81
53
  end
82
54
 
83
55
  end
56
+
57
+ def passenger_setup_defaults
58
+ HashWithIndifferentAccess.new({
59
+ 'server_name' => fetch(:domain),
60
+ 'document_root' => File.join(current_path, 'public'),
61
+ 'rails_env' => fetch(:rails_env, 'production')
62
+ })
63
+ end
64
+
65
+ def passenger_template_settings
66
+ DeepToHash.to_hash passenger_setup_defaults.deep_merge(fetch(:passenger_setup_settings, {}))
67
+ end
68
+
69
+ def _passenger_available_vhost
70
+ File.join(_passenger_sites_available, _passenger_vhost_filename)
71
+ end
72
+
73
+ def _passenger_enabled_vhost
74
+ File.join(_passenger_sites_enabled, _passenger_vhost_filename)
75
+ end
76
+
77
+ def _passenger_vhost_filename
78
+ fetch(:passenger_vhost_filename) { "#{application}.conf" }
79
+ end
80
+
81
+ def _passenger_sites_available
82
+ fetch(:passenger_sites_available, "/home/#{fetch_user}/configs/apache/sites-available")
83
+ end
84
+
85
+ def _passenger_sites_enabled
86
+ fetch(:passenger_sites_enabled, "/home/#{fetch_user}/configs/apache/sites-enabled")
87
+ end
88
+
89
+ def _passenger_template
90
+ fetch(:passenger_template, 'passenger.conf.erb')
91
+ end
84
92
  end
@@ -1,32 +1,11 @@
1
- # Example
2
- # =======
3
- #
4
- # settler_setup_settings:
5
- # host: example.com
6
- # partner_name: FooBar
7
-
8
1
  Capistrano::Configuration.instance(:must_exist).load do
9
- set(:settler_remote_file) { File.join(shared_path, 'config/settler.yml') } unless exists?(:settler_remote_file)
10
- set(:settler_template, 'settler.yml.erb') unless exists?(:settler_template)
11
-
12
- # task: `settler:setup'
13
- def settler_template_settings
14
- fetch(:settler_setup_settings, {}).inject({}) do |r, (k,v)|
15
- r.merge Hash[k, {'alt' => k, 'value' => v}]
16
- end
17
- end
18
-
19
-
20
- # Required attributes
21
- # ===================
22
- # *settler_name* prod_db
23
2
  namespace :settler do
24
3
  namespace :setup do
25
4
  desc "Upload configs"
26
5
  task :default, :roles => :app do
27
6
  if exists?(:settler_setup_settings)
28
7
  set(:recipe_settings) { settler_template_settings }
29
- put template.render(fetch(:settler_template)), fetch(:settler_remote_file)
8
+ put template.render(_settler_template), _settler_remote_file
30
9
  else
31
10
  puts "[FATAL] - Settler template settings were not found"
32
11
  abort
@@ -35,8 +14,40 @@ Capistrano::Configuration.instance(:must_exist).load do
35
14
 
36
15
  desc "Download configs"
37
16
  task :get, :roles => :db do
38
- download fetch(:settler_remote_file), File.join(local_rails_root, 'config/settler.yml')
17
+ download _settler_remote_file, _settler_local_file
18
+ end
19
+ end
20
+ end
21
+
22
+ def settler_template_settings
23
+ fetch(:settler_setup_settings, {}).inject({}) do |r, (k,v)|
24
+ case v.class.name
25
+ when 'Hash', 'ActiveSupport::HashWithIndifferentAccess'
26
+ r[k] = v
27
+ when 'Float'
28
+ r[k] = {'alt' => k.to_s, 'value' => v.to_s, 'typecast' => 'float'}
29
+ when 'Fixnum'
30
+ r[k] = {'alt' => k.to_s, 'value' => v.to_s, 'typecast' => 'integer'}
31
+ when 'TrueClass', 'FalseClass'
32
+ r[k] = {'alt' => k.to_s, 'value' => v.to_s, 'typecast' => 'boolean'}
33
+ when 'DateTime', 'Date', 'Time'
34
+ r[k] = {'alt' => k.to_s, 'value' => v.to_s, 'typecast' => 'datetime'}
35
+ else
36
+ r[k] = {'alt' => k.to_s, 'value' => v.to_s}
39
37
  end
38
+ r
40
39
  end
41
40
  end
41
+
42
+ def _settler_remote_file
43
+ File.join(shared_path, fetch(:settler_remote_file, 'config/settler.yml'))
44
+ end
45
+
46
+ def _settler_local_file
47
+ File.join(local_rails_root, fetch(:settler_local_file, 'config/settler.yml'))
48
+ end
49
+
50
+ def _settler_template
51
+ fetch(:settler_template, 'settler.yml.erb')
52
+ end
42
53
  end
@@ -1,40 +1,16 @@
1
- # Example
2
- # =======
3
- #
4
- # shards_setup_settings:
5
- # databases:
6
- # production:
7
- # slave1: {}
8
1
  Capistrano::Configuration.instance(:must_exist).load do
9
- set(:shards_remote_file) { File.join(shared_path, 'config/shards.yml') } unless exists?(:shards_remote_file)
10
- set(:shards_template, 'shards.yml.erb') unless exists?(:shards_template)
11
-
12
- def shards_setup_defaults
13
- {
14
- 'replicated' => true,
15
- 'verify_connection' => true,
16
- 'environments' => %w(production),
17
- 'databases' => {}
18
- }
19
- end
20
-
21
- # task: `shards:setup'
22
- def shards_template_settings
23
- fetch(:shards_setup_settings, {}).reverse_merge(shards_setup_defaults)
24
- end
25
-
26
2
  namespace :shards do
27
3
  namespace :setup do
28
4
  desc "Upload configs"
29
5
  task :default, :roles => :app do
30
6
  if exists?(:shards_setup_settings)
31
7
  set(:recipe_settings) do
32
- {
8
+ HashWithIndifferentAccess.new({
33
9
  'main' => database_template_settings,
34
10
  'shards' => shards_template_settings
35
- }
11
+ })
36
12
  end
37
- put template.render(fetch(:shards_template)), fetch(:shards_remote_file)
13
+ put template.render(_shards_template), _shards_remote_path
38
14
  else
39
15
  puts "[FATAL] - Shards template settings were not found"
40
16
  abort
@@ -43,9 +19,34 @@ Capistrano::Configuration.instance(:must_exist).load do
43
19
 
44
20
  desc "Download configs"
45
21
  task :get, :roles => :db do
46
- download fetch(:shards_remote_file), File.join(local_rails_root, "config/shards.yml")
22
+ download _shards_remote_path, _shards_local_path
47
23
  end
48
24
  end
49
25
 
50
26
  end
27
+
28
+ def shards_setup_defaults
29
+ HashWithIndifferentAccess.new({
30
+ 'replicated' => true,
31
+ 'verify_connection' => true,
32
+ 'environments' => %w(production),
33
+ 'databases' => {}
34
+ })
35
+ end
36
+
37
+ def shards_template_settings
38
+ DeepToHash.to_hash shards_setup_defaults.deep_merge(fetch(:shards_setup_settings, {}))
39
+ end
40
+
41
+ def _shards_remote_path
42
+ File.join(shared_path, fetch(:shards_remote_path, 'config/shards.yml'))
43
+ end
44
+
45
+ def _shards_local_path
46
+ File.join(local_rails_root, fetch(:shards_local_path, 'config/shards.yml'))
47
+ end
48
+
49
+ def _shards_template
50
+ fetch(:shards_template, 'shards.yml.erb')
51
+ end
51
52
  end
@@ -1,52 +1,26 @@
1
1
  Capistrano::Configuration.instance(:must_exist).load do
2
- set(:thin_remote_file) { File.join(shared_path, 'config/thin.yml') } unless exists?(:thin_remote_file)
3
- set(:thin_template, 'thin.yml.erb') unless exists?(:thin_template)
4
-
5
-
6
- # The wrapped bin to start thin
7
- # This is necessary if you're using rvm
8
- set :thin_bin, 'bundle exec thin' unless exists?(:thin_bin)
9
-
10
- # The remote location of thin's config file. Used by god to fire it up
11
- set(:thin_remote_config) { File.join(current_path, 'config', 'thin.yml') }
12
-
13
- # task: `thin:setup'
14
- def thin_template_settings
15
- fetch(:thin_setup_settings, {}).reverse_merge({
16
- 'chdir' => fetch(:current_path),
17
- 'timeout' => fetch(:thin_timeout, 30),
18
- 'servers' => fetch(:thin_servers, 4),
19
- 'rails_env' => fetch(:rails_env, 'production')
20
- })
21
- end
22
-
23
- def thin_cmd(action)
24
- "cd #{current_path}; #{thin_bin} -C #{thin_remote_config} #{action}"
25
- end
26
-
27
2
  namespace :thin do
28
3
  desc "Thin restart"
29
4
  task :restart, :roles => :app, :except => { :no_release => true } do
30
- run thin_cmd('restart')
5
+ run _thin_cmd('restart')
31
6
  end
32
7
 
33
8
  desc "Thin start"
34
9
  task :start, :roles => :app, :except => { :no_release => true } do
35
- run thin_cmd('start')
10
+ run _thin_cmd('start')
36
11
  end
37
12
 
38
13
  desc "Thin stop"
39
14
  task :stop, :roles => :app, :except => { :no_release => true } do
40
- run thin_cmd('stop')
15
+ run _thin_cmd('stop')
41
16
  end
42
17
 
43
-
44
18
  namespace :setup do
45
19
  desc "Upload configs"
46
20
  task :default, :roles => :app do
47
21
  if exists?(:thin_setup_settings)
48
22
  set(:recipe_settings) { thin_template_settings }
49
- put template.render(fetch(:thin_template)), fetch(:thin_remote_file)
23
+ put template.render(_thin_template), _thin_remote_path
50
24
  else
51
25
  puts "[FATAL] - Thin template settings were not found"
52
26
  abort
@@ -55,10 +29,49 @@ Capistrano::Configuration.instance(:must_exist).load do
55
29
 
56
30
  desc "Download configs"
57
31
  task :get, :roles => :db do
58
- download fetch(:thin_remote_file), File.join(local_rails_root, "config/thin.yml")
32
+ download _thin_remote_path, _thin_local_path
59
33
  end
60
34
  end
35
+ end
36
+
37
+ def thin_setup_defaults
38
+ HashWithIndifferentAccess.new({
39
+ 'chdir' => fetch(:current_path),
40
+ 'timeout' => fetch(:thin_timeout, 30),
41
+ 'servers' => fetch(:thin_servers, 4),
42
+ 'rails_env' => fetch(:rails_env, 'production')
43
+ })
44
+ end
45
+
46
+ def thin_template_settings
47
+ DeepToHash.to_hash thin_setup_defaults.deep_merge(fetch(:thin_setup_settings, {}))
48
+ end
49
+
50
+ def _thin_cmd(action)
51
+ "cd #{current_path}; #{_thin_bin} -C #{_thin_current_config_path} #{action}"
52
+ end
53
+
54
+ # The wrapped bin to start thin
55
+ # This is necessary if you're using rvm
56
+ def _thin_bin
57
+ fetch(:thin_bin, 'bundle exec thin')
58
+ end
59
+
60
+ # The remote location of thin's config file. Used by god to fire it up
61
+ def _thin_current_config_path
62
+ File.join(current_path, 'config', 'thin.yml')
63
+ end
64
+
65
+ def _thin_remote_path
66
+ File.join(shared_path, fetch(:thin_remote_path, 'config/thin.yml'))
67
+ end
68
+
69
+ def _thin_local_path
70
+ File.join(local_rails_root, fetch(:thin_local_path, 'config/thin.yml'))
71
+ end
61
72
 
73
+ def _thin_template
74
+ fetch(:thin_template, 'thin.yml.erb')
62
75
  end
63
76
 
64
77
  end
@@ -1,23 +1,11 @@
1
- # Example
2
- # =======
3
- #
4
- # tire_setup_settings:
5
- # url: "http://localhost:9200"
6
-
7
1
  Capistrano::Configuration.instance(:must_exist).load do
8
- set(:tire_remote_file) { File.join(shared_path, 'config/tire.yml') } unless exists?(:tire_remote_file)
9
- set(:tire_template, 'tire.yml.erb') unless exists?(:tire_template)
10
-
11
- # Required attributes
12
- # ===================
13
- # *url* http://localhost:9200
14
2
  namespace :tire do
15
3
  namespace :setup do
16
4
  desc "Upload configs"
17
5
  task :default, :roles => :app do
18
6
  if exists?(:tire_setup_settings)
19
- set :recipe_settings, fetch(:tire_setup_settings, {})
20
- put template.render(fetch(:tire_template)), fetch(:tire_remote_file)
7
+ set(:recipe_settings) { tire_template_settings }
8
+ put template.render(_tire_template), _tire_remote_file
21
9
  else
22
10
  puts "[FATAL] - Tire template settings were not found"
23
11
  abort
@@ -26,8 +14,32 @@ Capistrano::Configuration.instance(:must_exist).load do
26
14
 
27
15
  desc "Download configs"
28
16
  task :get, :roles => :db do
29
- download fetch(:tire_remote_file), File.join(local_rails_root, "config/tire.yml")
17
+ download _tire_remote_file, _tire_local_file
30
18
  end
31
19
  end
32
20
  end
21
+
22
+ def tire_setup_defaults
23
+ HashWithIndifferentAccess.new({
24
+ 'common'=>{
25
+ 'url' => 'http://localhost:9200'
26
+ }
27
+ }.reverse_merge(default_rails_environments_hash))
28
+ end
29
+
30
+ def tire_template_settings
31
+ DeepToHash.to_hash tire_setup_defaults.deep_merge(fetch(:tire_setup_settings, {}))
32
+ end
33
+
34
+ def _tire_remote_file
35
+ File.join(shared_path, fetch(:tire_remote_file, 'config/tire.yml'))
36
+ end
37
+
38
+ def _tire_local_file
39
+ File.join(local_rails_root, fetch(:tire_local_file, 'config/tire.yml'))
40
+ end
41
+
42
+ def _tire_template
43
+ fetch(:tire_template, 'tire.yml.erb')
44
+ end
33
45
  end
@@ -1,59 +1,4 @@
1
- # Example
2
- # =======
3
- #
4
- # unicorn_setup_settings:
5
- # port: 80
6
1
  Capistrano::Configuration.instance(:must_exist).load do
7
- set(:monit_root){ "/home/#{user}/monit/metromix" }
8
-
9
- # The wrapped bin to start unicorn
10
- # This is necessary if you're using rvm
11
- set :unicorn_bin, 'bundle exec unicorn' unless exists?(:unicorn_bin)
12
-
13
- # The remote location of unicorn's config file. Used by god to fire it up
14
- set(:unicorn_remote_config) { "#{current_path}/config/unicorn.rb" }
15
-
16
- set(:unicorn_template, 'unicorn.rb.erb') unless exists?(:unicorn_template)
17
- set(:unicorn_monit_template, 'unicorn_monit.erb') unless exists?(:unicorn_monit_template)
18
-
19
- # Defines where the unicorn pid will live.
20
- set(:unicorn_pid) { File.join(shared_path, "pids", "unicorn.pid") } unless exists?(:unicorn_pid)
21
-
22
- # task: `unicorn:setup'
23
- def unicorn_template_settings
24
- fetch(:unicorn_setup_settings, {}).reverse_merge({
25
- # Number of workers (Rule of thumb is 2 per CPU)
26
- # Just be aware that every worker needs to cache all classes and thus eat some
27
- # of your RAM.
28
- 'workers' => fetch(:unicorn_workers, 4),
29
- # Workers timeout in the amount of seconds below, when the master kills it and
30
- # forks another one.
31
- 'workers_timeout' => fetch(:unicorn_workers_timeout, 30),
32
- # Workers are started with this user/group
33
- # By default we get the user/group set in capistrano.
34
- 'user' => fetch(:unicorn_user) { user },
35
- 'group' => fetch(:unicorn_group) { group },
36
- 'rails_env' => fetch(:rails_env, 'production'),
37
- # configs for the monit template
38
- 'pids_root' => fetch(:unicorn_pids_root) { File.join(shared_path, "pids") },
39
- 'application' => fetch(:application),
40
- 'current_path' => fetch(:current_path),
41
- 'remote_config' => fetch(:unicorn_remote_config)
42
- })
43
- end
44
-
45
- def unicorn_start_cmd
46
- "cd #{current_path} && #{unicorn_bin} -c #{unicorn_remote_config} -E #{rails_env} -D"
47
- end
48
-
49
- def unicorn_stop_cmd
50
- "kill -QUIT `cat #{unicorn_pid}`"
51
- end
52
-
53
- def unicorn_restart_cmd
54
- "kill -USR2 `cat #{unicorn_pid}`"
55
- end
56
-
57
2
  namespace :unicorn do
58
3
  desc "Starts unicorn directly"
59
4
  task :start, :roles => :app, :except => { :no_release => true } do
@@ -62,12 +7,12 @@ Capistrano::Configuration.instance(:must_exist).load do
62
7
 
63
8
  desc "Stops unicorn directly"
64
9
  task :stop, :roles => :app, :except => { :no_release => true } do
65
- run unicorn_stop_cmd
10
+ run unicorn_kill_cmd('QUIT')
66
11
  end
67
12
 
68
13
  desc "Restarts unicorn directly"
69
14
  task :restart, :roles => :app, :except => { :no_release => true } do
70
- run unicorn_restart_cmd
15
+ run unicorn_kill_cmd('USR2')
71
16
  end
72
17
 
73
18
  # Required attributes
@@ -78,7 +23,7 @@ Capistrano::Configuration.instance(:must_exist).load do
78
23
  task :default, :roles => :app do
79
24
  if exists?(:unicorn_setup_settings)
80
25
  set(:recipe_settings) { unicorn_template_settings }
81
- put template.render(fetch(:unicorn_template)), File.join(shared_path, 'config/unicorn.rb')
26
+ put template.render(_unicorn_template), _unicorn_shared_file
82
27
  else
83
28
  puts "[FATAL] - Unicorn template settings were not found"
84
29
  abort
@@ -87,18 +32,18 @@ Capistrano::Configuration.instance(:must_exist).load do
87
32
 
88
33
  desc "Download configs"
89
34
  task :get, :roles => :db do
90
- download File.join(shared_path, 'config/unicorn.rb'), File.join(local_rails_root, "config/unicorn.rb")
35
+ download _unicorn_shared_file, _unicorn_local_file
91
36
  end
92
37
  end
93
38
 
94
39
  namespace :monit do
95
40
  namespace :setup do
96
41
  desc "Upload configs"
97
- task :default, :roles => :db do
42
+ task :default, :roles => :app do
98
43
  if exists?(:unicorn_setup_settings)
99
- run "mkdir -p #{monit_root}"
44
+ run "mkdir -p #{_monit_root}"
100
45
  set(:recipe_settings) { unicorn_template_settings }
101
- put template.render(fetch(:unicorn_monit_template)), File.join(monit_root, application)
46
+ put template.render(_unicorn_monit_template), _monit_remote_file
102
47
  else
103
48
  puts "[FATAL] - Unicorn/Monit template settings were not found"
104
49
  abort
@@ -107,10 +52,89 @@ Capistrano::Configuration.instance(:must_exist).load do
107
52
 
108
53
  desc "Download configs"
109
54
  task :get, :roles => :db do
110
- download File.join(monit_root, application), File.join(local_rails_root, "config/#{application}-monit")
55
+ download _monit_remote_file, File.join(local_rails_root, "config/#{application}-monit")
111
56
  end
112
57
  end
113
58
 
114
59
  end
115
60
  end
61
+
62
+ def unicorn_setup_defaults
63
+ HashWithIndifferentAccess.new({
64
+ # Number of workers (Rule of thumb is 2 per CPU)
65
+ # Just be aware that every worker needs to cache all classes and thus eat some
66
+ # of your RAM.
67
+ 'workers' => fetch(:unicorn_workers, 4),
68
+ # Workers timeout in the amount of seconds below, when the master kills it and
69
+ # forks another one.
70
+ 'workers_timeout' => fetch(:unicorn_workers_timeout, 30),
71
+ # Workers are started with this user/group
72
+ # By default we get the user/group set in capistrano.
73
+ 'user' => fetch(:unicorn_user) { fetch_user },
74
+ 'group' => fetch(:unicorn_group) { fetch_group },
75
+ 'rails_env' => fetch(:rails_env, 'production'),
76
+ # configs for the monit template
77
+ 'pids_root' => _unicorn_pids_root,
78
+ 'application' => fetch(:application),
79
+ 'current_path' => current_path,
80
+ 'remote_config' => _unicorn_current_file
81
+ })
82
+ end
83
+
84
+ def unicorn_template_settings
85
+ DeepToHash.to_hash unicorn_setup_defaults.deep_merge(fetch(:unicorn_setup_settings, {}))
86
+ end
87
+
88
+ def unicorn_start_cmd
89
+ "cd #{current_path} && #{_unicorn_bin} -c #{_unicorn_current_file} -E #{rails_env} -D"
90
+ end
91
+
92
+ def unicorn_kill_cmd(arg)
93
+ "kill -#{arg} `cat #{_unicorn_pid}`"
94
+ end
95
+
96
+ # The wrapped bin to start unicorn
97
+ # This is necessary if you're using rvm
98
+ def _unicorn_bin
99
+ fetch(:unicorn_bin, 'bundle exec unicorn')
100
+ end
101
+
102
+ # Defines where the unicorn pid will live.
103
+ def _unicorn_pid
104
+ fetch(:unicorn_pid) { File.join(shared_path, "pids", "unicorn.pid") }
105
+ end
106
+
107
+ def _unicorn_pids_root
108
+ _unicorn_pid.split('/').tap{|x| x.pop }.join('/')
109
+ end
110
+
111
+ # The remote location of unicorn's config file. Used by god to fire it up
112
+ def _unicorn_current_file
113
+ File.join(current_path, fetch(:unicorn_remote_file, 'config/unicorn.rb'))
114
+ end
115
+
116
+ def _unicorn_shared_file
117
+ File.join(shared_path, fetch(:unicorn_remote_file, 'config/unicorn.rb'))
118
+ end
119
+
120
+ def _unicorn_local_file
121
+ File.join(local_rails_root, fetch(:unicorn_local_file, 'config/unicorn.rb'))
122
+ end
123
+
124
+ def _unicorn_template
125
+ fetch(:unicorn_template, 'unicorn.rb.erb')
126
+ end
127
+
128
+ def _unicorn_monit_template
129
+ fetch(:unicorn_monit_template, 'unicorn_monit.erb')
130
+ end
131
+
132
+ def _monit_root
133
+ fetch(:monit_root) { "/home/#{fetch_user}/monit" }
134
+ end
135
+
136
+ def _monit_remote_file
137
+ File.join(_monit_root, application)
138
+ end
139
+
116
140
  end
@@ -1,25 +1,11 @@
1
- # Example
2
- # =======
3
- #
4
- # uploader_setup_settings:
5
- # fog_credentials:
6
- # provider: Rackspace
7
- # rackspace_username: username
8
- # rackspace_api_key: secret
9
- # fog_directory: frontend
10
- # fog_host: http://123.rackcdn.com
11
-
12
1
  Capistrano::Configuration.instance(:must_exist).load do
13
- set(:uploader_remote_file) { File.join(shared_path, 'config/uploader.yml') } unless exists?(:uploader_remote_file)
14
- set(:uploader_template, 'uploader.yml.erb') unless exists?(:uploader_template)
15
-
16
2
  namespace :uploader do
17
3
  namespace :setup do
18
4
  desc "Upload configs"
19
5
  task :default, :roles => :app do
20
6
  if exists?(:uploader_setup_settings)
21
- set :recipe_settings, fetch(:uploader_setup_settings, {})
22
- put template.render(fetch(:uploader_template)), fetch(:uploader_remote_file)
7
+ set(:recipe_settings) { uploader_template_settings }
8
+ put template.render(_uploader_template), _uploader_remote_file
23
9
  else
24
10
  puts "[FATAL] - Uploader template settings were not found"
25
11
  abort
@@ -28,9 +14,30 @@ Capistrano::Configuration.instance(:must_exist).load do
28
14
 
29
15
  desc "Download configs"
30
16
  task :get, :roles => :db do
31
- download fetch(:uploader_remote_file), File.join(local_rails_root, "config/uploader.yml")
17
+ download _uploader_remote_file, _uploader_local_file
32
18
  end
33
19
  end
34
20
 
35
21
  end
22
+
23
+ def uploader_setup_defaults
24
+ HashWithIndifferentAccess.new({'common'=>{}}.reverse_merge(default_rails_environments_hash))
25
+ end
26
+
27
+ def uploader_template_settings
28
+ DeepToHash.to_hash uploader_setup_defaults.deep_merge(fetch(:uploader_setup_settings, {}))
29
+ end
30
+
31
+ def _uploader_remote_file
32
+ File.join(shared_path, fetch(:uploader_remote_file, 'config/uploader.yml'))
33
+ end
34
+
35
+ def _uploader_local_file
36
+ File.join(local_rails_root, fetch(:uploader_local_file, 'config/uploader.yml'))
37
+ end
38
+
39
+ def _uploader_template
40
+ fetch(:uploader_template, 'uploader.yml.erb')
41
+ end
42
+
36
43
  end
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "marcosgz-cap-recipe"
6
- s.version = "0.0.8"
6
+ s.version = "0.0.9"
7
7
  s.authors = ["Marcos G. Zimmermann"]
8
8
  s.email = ["mgzmaster@gmail.com"]
9
9
  s.homepage = "https://github.com/marcosgz/capistrano-recipe"
@@ -17,5 +17,5 @@ Gem::Specification.new do |s|
17
17
  s.require_paths = ["lib"]
18
18
 
19
19
  s.add_dependency "capistrano", "> 2.0.0"
20
- s.add_development_dependency "pry", "~> 0.9.11.4"
20
+ s.add_dependency "marcosgz-cap-template", "~> 0.0.3"
21
21
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marcosgz-cap-recipe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-18 00:00:00.000000000 Z
12
+ date: 2013-04-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: capistrano
@@ -28,21 +28,21 @@ dependencies:
28
28
  - !ruby/object:Gem::Version
29
29
  version: 2.0.0
30
30
  - !ruby/object:Gem::Dependency
31
- name: pry
31
+ name: marcosgz-cap-template
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  none: false
34
34
  requirements:
35
35
  - - ~>
36
36
  - !ruby/object:Gem::Version
37
- version: 0.9.11.4
38
- type: :development
37
+ version: 0.0.3
38
+ type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
41
41
  none: false
42
42
  requirements:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
- version: 0.9.11.4
45
+ version: 0.0.3
46
46
  description:
47
47
  email:
48
48
  - mgzmaster@gmail.com
@@ -93,4 +93,3 @@ signing_key:
93
93
  specification_version: 3
94
94
  summary: Capistrano recipe
95
95
  test_files: []
96
- has_rdoc: