jtrupiano-capistrano-extensions 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,22 @@
1
+ # Created 2008-08-20
2
+
3
+ === v0.1.3 / 2008-08-25
4
+ * 2008-08-25 : VERSION BUMP
5
+ Introduced a new property :shared_content, which is intended to completely replace :content_directories
6
+ eventually. All directories previously specified by :content_directories go through a simple transformation
7
+ to match the new hash construct that is :shared_content. Now, we can specify non-public directories (though
8
+ they are still limited to within RAILS_ROOT), e.g.
9
+
10
+ set(:shared_content) { "feeds" => "content" }
11
+
12
+ This will create a symlink whose source is #{shared_path}/feeds and whose target is RAILS_ROOT/content.
13
+ Then, on successive deployments, this symlink is just recreated, and all of our feeds are still accessible
14
+ (because they were stored outside of RAILS_ROOT and then symlinked in).
15
+
16
+ === v0.1.2 / 2008-07-20
17
+ 2008-08-20
18
+ * Fixed a mysql bug that was encountered in "sync" operations. When passing a password on the command-line
19
+ (e.g. mysqldump -uuser -ppass), $'s in the password need to be escaped. I also fixed the scenario where
20
+ there was no password (common for restoring to the development environment). Previously you would be
21
+ prompted for a password only in the case where there was no password required. This was a result of
22
+ the way the mysql commands were being built: "mysql -u#{user} -p#{password}" where password was nil or ""
data/Manifest.txt ADDED
@@ -0,0 +1,11 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/capistrano-extensions-sync-content
6
+ bin/capistrano-extensions-sync-db
7
+ lib/capistrano-extensions.rb
8
+ lib/capistrano-extensions/deploy.rb
9
+ lib/capistrano-extensions/geminstaller_dependency.rb
10
+ lib/capistrano-extensions/version.rb
11
+
data/README.txt ADDED
@@ -0,0 +1,217 @@
1
+ = capistrano-extensions
2
+
3
+ * http://github.com/jtrupiano/capistrano-extensions
4
+
5
+ == DESCRIPTION/FEATURES:
6
+
7
+ This gem provides a base set of Capistrano extensions including the following:
8
+ * a new :gemfile RemoteDependency type
9
+ * tasks/helpers for handling public asset folders (e.g. created by the file_column plugin)
10
+ * tasks/helpers for auto-syncing server gems (via integration with Chad Wooley's GemInstaller gem)
11
+ * helpers for dealing with multiple deployable environments (e.g. staging, prodtest, production)
12
+ * tasks for working with remote logfiles
13
+ * tasks for database/asset synchronization from production back to local environments
14
+
15
+ == INCOMPLETE:
16
+ * Missing a detailed sample config file
17
+ * Describe the shortcomings (or rather my dissatisfaction) with the remote syncing executables for
18
+ assets/db. It works fine for now, but is a little wasteful.
19
+ * Database synchronization _only_ works for MySQL. (not sure if I intend to change this any time soon)
20
+ * This has really only been tested on single-server deployments, so I'm not sure how well it will work
21
+ on more complex environments -- I'll personally be able to test that in the coming month or two, but
22
+ that will be dictated by necessity.
23
+ * Still no support for user-uploaded assets stored outside of the public/ directory
24
+ * Need to automate the generation of this document: the descriptions for each attribute/task
25
+ should mirror the description in the deploy script (in other words, I should only have to update the
26
+ the documentation in one place).
27
+
28
+ == CAPISTRANO CODE EXTENSIONS:
29
+ * new RemoteDependency type :gemfile
30
+
31
+ depend(:remote, :gemfile, "config/geminstaller.yml")
32
+
33
+ Aliases the depend method (with depend_without_gemfile). Proxies all calls with :type != :gemfile
34
+ to the aliased method. When :type == :gemfile, the gems file is parsed (using geminstaller
35
+ codebase) to iteratively call depend_without_gemfile with each gem found in the YAML file.
36
+
37
+ This is still really only suitable for single-server deployments. The idea would be to add new
38
+ options to the geminstaller.yml config syntax that would allow us to reference specific
39
+ capistrano roles for a given gem. For instance, the database server won't need all of our rails
40
+ gems. A separate ferret server may require it's own set of gems, etc.
41
+
42
+ == NEW RECIPE PROPERTIES --> DEFAULTS
43
+ # Provides a way to specify which uploadable asset directories (that live in public/)
44
+ # should be retrievable via the local:copy_production_content and local:copy_production
45
+ # tasks described below. Note that this parameter is also utilized by the
46
+ # passenger-recipes gem to keep these uploadable assets in the shared/ context.
47
+ :content_directories --> []
48
+
49
+ # This property is similar to :content_directories, except it doesn't assume that the symlinks
50
+ # exist in the public/ directory (the default location for FileColumn file storage).
51
+ #
52
+ # This property is a hash of remote => local mappings, e.g.
53
+ #
54
+ # "feeds" => "content" (or "uploaded_assets/meal" => "public/meal")
55
+ #
56
+ # These examples will effectively create the following symlinks in a deployable environment:
57
+ # ln -sf \#{shared_path}/feeds RAILS_ROOT/content
58
+ # ln -sf \#{shared_path}/uploaded_assets/meal RAILS_ROOT/public/meal
59
+ #
60
+ # Each key (the "remote" directory) must be a directory found in \#{shared_path} (in a deployable environment)
61
+ # Each value (the "local" directory) must be a directory found in RAILS_ROOT (in a local environment)
62
+ :shared_content --> {}
63
+
64
+ # Which environments are deployable-- for each environment specified in this array,
65
+ # a helper function by the same name is created that is executed only if RAILS_ENV
66
+ # is set to that value. See examples/sample_deploy.rb for a code sample.
67
+ :deployable_environments --> [:production]
68
+
69
+ # We at SLS use a different config structure than rails does out of the box.
70
+ # Setting this value to :sls will alter some of the expected paths. Normally,
71
+ # you will not have to set this variable. To see a discussion of the SLS config
72
+ # file structure, see http://blog.smartlogicsolutions.com/2008/06/02/better-setup-for-environments-in-rails/
73
+ :config_structure --> :rails
74
+
75
+ == NEW RECIPES:
76
+ * deploy:create_shared_file_column_dirs
77
+
78
+ Creates shared filecolumn directories and symbolic links to them by
79
+ reading the :content_directories property. Note that this task is not invoked by default,
80
+ but rather is exposed to you as a helper. To utilize, you'll want to override
81
+ deploy:default and invoke this yourself.
82
+
83
+ * deploy:gem_update
84
+
85
+ Invokes geminstaller to ensure that the proper gem set is installed on the target server.
86
+ Note that this task is not invoked by default, but rather is exposed to you as a helper.
87
+
88
+ * log:pull
89
+
90
+ Tarballs deployable environment's rails logfile (identified by
91
+ RAILS_ENV environment variable, which defaults to 'production') and copies it to the local
92
+ filesystem
93
+
94
+ * local:backup_db
95
+
96
+ Backs up deployable environment's database (identified by the
97
+ RAILS_ENV environment variable, which defaults to 'production') and copies it to the local machine
98
+
99
+ * local:restore_db
100
+
101
+ Untars the backup file downloaded from local:backup_db (specified via the FROM env
102
+ variable, which defalts to RAILS_ENV), and imports (via mysql command line tool) it back into the database
103
+ defined in the RAILS_ENV env variable.
104
+
105
+ ToDo: implement proper rollback: currently, if the mysql import succeeds, but the rm fails,
106
+ the database won't be rolled back. Not sure this is even all that important or necessary, since
107
+ it's a local database that doesn't demand integrity (in other words, you're still going to have to
108
+ fix it, but it's not mission critical).
109
+
110
+ * local:backup_content
111
+
112
+ Downloads a tarball of uploaded content (that lives in public/ directory, as specified by
113
+ the :content_directories property) from the production site back to the local filesystem
114
+
115
+ * local:restore_content
116
+
117
+ Restores the backed up content (evn var FROM specifies which environment was backed up,
118
+ defaults to RAILS_ENV) to the local development environment app
119
+
120
+ * local:sync_db
121
+
122
+ Wrapper for local:backup_db and local:restore_db
123
+
124
+ $> cap local:sync_db RAILS_ENV=production RESTORE_ENV=development
125
+
126
+ * local:sync_content
127
+
128
+ Wrapper for local:backup_content and local:restore_content
129
+
130
+ $> cap local:sync_content RAILS_ENV=production RESTORE_ENV=development
131
+
132
+ * local:sync
133
+
134
+ Wrapper for local:sync_db and local:sync_content
135
+
136
+ $> cap local:sync RAILS_ENV=production RESTORE_ENV=development
137
+
138
+ * remote:restore_db
139
+
140
+ Uploads the backup file downloaded from local:backup_db (specified via the FROM env variable),
141
+ copies it to the remove environment specified by RAILS_ENV, and imports (via mysql command line
142
+ tool) it back into the remote database.
143
+
144
+ * remote:sync_db
145
+
146
+ Backs up target deployable environment's database (identified by the FROM environment variable,
147
+ which defaults to 'production') and restores it to the remote database identified by the TO
148
+ environment variable, which defaults to "staging."
149
+
150
+ Because multiple capistrano configurations must be loaded, an external executable
151
+ (capistrano-extensions-sync_db) is invoked, which independently calls capistrano. See the
152
+ executable at $GEM_HOME/capistrano-extensions-0.1.3/bin/capistrano-extensions-sync_db
153
+
154
+ $> cap remote:sync_db FROM=production TO=staging
155
+
156
+ * remote:restore_content
157
+
158
+ Uploads the backup file downloaded from local:backup_content (specified via the FROM env variable),
159
+ copies it to the remote environment specified by RAILS_ENV, and unpacks it into the shared/
160
+ directory.
161
+
162
+ * remote:sync_content
163
+
164
+ Backs up target deployable environment's shared content (identified by the FROM environment
165
+ variable, which defaults to 'production') and restores it to the remote environment identified
166
+ by the TO envrionment variable, which defaults to "staging."
167
+
168
+ Because multiple capistrano configurations must be loaded, an external executable
169
+ (capistrano-extensions-sync_content) is invoked, which independently calls capistrano. See the
170
+ executable at $GEM_HOME/capistrano-extensions-0.1.2/bin/capistrano-extensions-sync_content
171
+
172
+ $> cap remote:sync_content FROM=production TO=staging
173
+
174
+ * remote:sync
175
+
176
+ Wrapper fro remote:sync_db and remote:sync_content.
177
+
178
+ $> cap remote:sync FROM=production TO=staging
179
+
180
+ == SYNOPSIS:
181
+
182
+ FIX (code sample of usage)
183
+
184
+ == REQUIREMENTS:
185
+
186
+ * Capistrano = 2.4.3
187
+ * GemInstaller = 0.4.3
188
+
189
+ == INSTALL:
190
+
191
+ * rake gem
192
+ * sudo gem install pkg/capistrano-extensions-0.1.3.gem --local
193
+
194
+ == LICENSE:
195
+
196
+ (The MIT License)
197
+
198
+ Copyright (c) 2008 FIX
199
+
200
+ Permission is hereby granted, free of charge, to any person obtaining
201
+ a copy of this software and associated documentation files (the
202
+ 'Software'), to deal in the Software without restriction, including
203
+ without limitation the rights to use, copy, modify, merge, publish,
204
+ distribute, sublicense, and/or sell copies of the Software, and to
205
+ permit persons to whom the Software is furnished to do so, subject to
206
+ the following conditions:
207
+
208
+ The above copyright notice and this permission notice shall be
209
+ included in all copies or substantial portions of the Software.
210
+
211
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
212
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
213
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
214
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
215
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
216
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
217
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,47 @@
1
+ # GEM_SPEC = eval(File.read("#{File.dirname(__FILE__)}/#{PKG_NAME}.gemspec"))
2
+ #
3
+ # Rake::GemPackageTask.new(GEM_SPEC) do |p|
4
+ # p.gem_spec = GEM_SPEC
5
+ # p.need_tar = true
6
+ # p.need_zip = true
7
+ # end
8
+ #
9
+ # desc "Clean up generated directories and files"
10
+ # task :clean do
11
+ # rm_rf "pkg"
12
+ # end
13
+
14
+
15
+ # -*- ruby -*-
16
+
17
+ require 'rubygems'
18
+ require 'hoe'
19
+ require './lib/capistrano-extensions.rb'
20
+ require "./lib/capistrano-extensions/version"
21
+
22
+
23
+ PKG_NAME = "capistrano-extensions"
24
+ PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
25
+ PKG_VERSION = CapistranoExtensions::Version::STRING + PKG_BUILD
26
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
27
+
28
+
29
+ Hoe.new('capistrano-extensions', PKG_VERSION) do |p|
30
+ # p.rubyforge_name = 'capistrano-extensionsx' # if different than lowercase project name
31
+ # p.developer('FIX', 'FIX@example.com')
32
+ p.name = "capistrano-extensions"
33
+ p.version = PKG_VERSION
34
+ #p.platform = Gem::Platform::RUBY
35
+ p.author = "John Trupiano"
36
+ p.email = "jtrupiano@gmail.com"
37
+ p.description = %q(A base set of Capistrano extensions-- aids with the file_column plugin, the GemInstaller gem, multiple deployable environments, logfile helpers, and database/asset synchronization from production to local environment)
38
+ p.summary = p.description # More details later??
39
+ p.remote_rdoc_dir = 'capistrano-extensions' # Release to /capistrano-extensions
40
+ # p.changes = p.paragraphs_of('CHANGELOG', 0..1).join("\n\n")
41
+ p.extra_deps << ["capistrano", ">= 2.4.3"]
42
+ p.extra_deps << ["geminstaller", ">= 0.4.3"]
43
+ p.need_zip = true
44
+ p.need_tar = false
45
+ end
46
+
47
+ # vim: syntax=Ruby
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if ARGV.size < 2
4
+ puts "Improper invocation: capistrano-extensions-copy-production-db backup_env restore_env"
5
+ exit 1
6
+ end
7
+
8
+ system("cap local:backup_content RAILS_ENV=#{ARGV[0]}")
9
+ system("cap remote:restore_content RAILS_ENV=#{ARGV[1]} FROM=#{ARGV[0]}")
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if ARGV.size < 2
4
+ puts "Improper invocation: capistrano-extensions-copy-production-db backup_env restore_env"
5
+ exit 1
6
+ end
7
+
8
+ system("cap local:backup_db RAILS_ENV=#{ARGV[0]}")
9
+ system("cap remote:restore_db RAILS_ENV=#{ARGV[1]} FROM=#{ARGV[0]}")
@@ -0,0 +1,2 @@
1
+ gem 'capistrano', '>= 2.4.3' # load v2.4.3 or higher
2
+ gem 'geminstaller', '>= 0.4.3' # load v0.4.3 or higher
@@ -0,0 +1,324 @@
1
+ require 'capistrano-extensions/geminstaller_dependency'
2
+ require 'capistrano/server_definition'
3
+
4
+ # Overrides the majority of recipes from Capistrano's deploy recipe set.
5
+ Capistrano::Configuration.instance(:must_exist).load do
6
+ # Add sls_recipes to the load path
7
+ @load_paths << File.expand_path(File.dirname(__FILE__))
8
+
9
+ # ========================================================================
10
+ # These variables MUST be set in the client capfiles. If they are not set,
11
+ # the deploy will fail with an error.
12
+ # ========================================================================
13
+
14
+
15
+ # =========================================================================
16
+ # These variables may be set in the client capfile if their default values
17
+ # are not sufficient.
18
+ # =========================================================================
19
+
20
+ _cset(:content_directories, []) # I'd like to eventually remove this...
21
+ _cset(:shared_content, {})
22
+ _cset(:rails_env) { ENV['RAILS_ENV'].nil? ? fetch(:deployable_environments).first : ENV['RAILS_ENV'] }
23
+
24
+ # =========================================================================
25
+ # These variables should NOT be changed unless you are very confident in
26
+ # what you are doing. Make sure you understand all the implications of your
27
+ # changes if you do decide to muck with these!
28
+ # =========================================================================
29
+
30
+ set(:use_sudo, false) # we don't want to use sudo-- we don't have to!
31
+ set(:deploy_via, :export) # we don't want our .svn folders on the server!
32
+ _cset(:deploy_to) { "/var/www/vhosts/#{application}" }
33
+ _cset(:deployable_environments, [:production])
34
+
35
+ _cset(:rails_config_path) { File.join(latest_release, 'config') }
36
+ _cset(:db_conf) {
37
+ fetch(:config_structure, :rails).to_sym == :sls ?
38
+ File.join(rails_config_path, rails_env, 'database.yml') :
39
+ File.join(rails_config_path, 'database.yml')
40
+ }
41
+
42
+ # Where uploaded content is stored
43
+ _cset(:content_dir, "content")
44
+ _cset(:content_path) { File.join(shared_path, content_dir) }
45
+ _cset(:public_path) { File.join(latest_release, 'public') }
46
+ _cset(:log_path) { "/var/log/#{application}" }
47
+
48
+ # Allow recipes to ask for a certain local environment
49
+ def local_db_conf(env = nil)
50
+ env ||= fetch(:rails_env)
51
+ fetch(:config_structure, :rails).to_sym == :sls ?
52
+ File.join('config', env, 'database.yml') :
53
+ File.join('config', 'database.yml')
54
+ end
55
+
56
+ # Read from the local machine-- BE CAREFUL!!!
57
+ set(:db) { YAML.load_file(local_db_conf)[rails_env] }
58
+
59
+ # Let's define helpers for our deployable environments
60
+ # Can we possibly just infer this from the config directory structure?
61
+ deployable_environments.each do |env|
62
+ src = <<-CODE
63
+ def #{env.to_s}(&block)
64
+ if rails_env.to_s == '#{env.to_s}'
65
+ puts "*** Deploying to the \033[1;41m #{env.to_s.capitalize} \033[0m server!"
66
+ yield
67
+ puts <<-DEBUG
68
+ rails_env: \#{rails_env}
69
+ deploy_to: \#{deploy_to}
70
+ content_directories: \#{content_directories.join(', ')}
71
+ shared_content: \#{shared_content.keys.join(', ')}
72
+ DEBUG
73
+ end
74
+ end
75
+ CODE
76
+ eval src
77
+ end
78
+
79
+ # Now, let's actually include our common recipes!
80
+ namespace :deploy do
81
+ desc <<-DESC
82
+ [capistrano-extensions] Creates shared directories and symbolic links to them by the
83
+ :content_directories and :shared_content properties. See the README for
84
+ further explanation.
85
+ DESC
86
+ task :create_shared_file_column_dirs, :roles => :app, :except => { :no_release => true } do
87
+ mappings = content_directories.inject(shared_content) { |hsh, dir| hsh.merge({"content/#{dir}" => "public/#{dir}"}) }
88
+ mappings.each_pair do |remote, local|
89
+ run <<-CMD
90
+ mkdir -p #{shared_path}/#{remote} &&
91
+ ln -sf #{shared_path}/#{remote} #{latest_release}/#{local} &&
92
+ chmod 755 -R #{shared_path}/#{remote}
93
+ CMD
94
+ end
95
+ end
96
+
97
+ desc <<-DESC
98
+ [capistrano-extensions]: Invokes geminstaller to ensure that the proper gem set is installed on
99
+ the target server. Note that this task is not invoked by default, but rather is exposed to you
100
+ as a helper.
101
+ DESC
102
+ task :gem_update, :roles => :app do
103
+ run <<-CMD
104
+ gem sources -u &&
105
+ #{sudo} geminstaller -e -c #{rails_config_path}/geminstaller.yml
106
+ CMD
107
+ end
108
+
109
+ end
110
+
111
+ namespace :log do
112
+ desc <<-DESC
113
+ [capistrano-extensions]: Tarballs deployable environment's rails logfile (identified by
114
+ RAILS_ENV environment variable, which defaults to 'production') and copies it to the local
115
+ filesystem
116
+ DESC
117
+ task :pull do
118
+ tmp_location = "#{shared_path}/#{rails_env}.log.gz"
119
+ run "cp #{log_path}/#{rails_env}.log #{shared_path}/ && gzip #{shared_path}/#{rails_env}.log"
120
+ get "#{tmp_location}", "#{application}-#{rails_env}.log.gz"
121
+ run "rm #{tmp_location}"
122
+ end
123
+ end
124
+
125
+ namespace :remote do
126
+ desc <<-DESC
127
+ [capistrano-extensions] Uploads the backup file downloaded from local:backup_db (specified via the FROM env variable),
128
+ copies it to the remove environment specified by RAILS_ENV, and imports (via mysql command line tool) it back into the
129
+ remote database.
130
+ DESC
131
+ task :restore_db, :roles => :db do
132
+ env = ENV['FROM'] || 'production'
133
+
134
+ puts "\033[1;41m Restoring database backup to #{rails_env} environment \033[0m"
135
+ if deployable_environments.include?(rails_env.to_sym)
136
+ # remote environment
137
+ local_backup_file = "#{application}-#{env}-db.sql.gz"
138
+ remote_file = "#{shared_path}/restore_db.sql"
139
+ if !File.exists?(local_backup_file)
140
+ puts "Could not find backup file: #{local_backup_file}"
141
+ exit 1
142
+ end
143
+ upload(local_backup_file, "#{remote_file}.gz")
144
+
145
+ pass_str = pluck_pass_str(db)
146
+ run "gunzip -f #{remote_file}.gz"
147
+ run "mysql -u#{db['username']} #{pass_str} #{db['database']} < #{remote_file}"
148
+ run "rm -f #{remote_file}"
149
+ end
150
+ end
151
+
152
+ desc <<-DESC
153
+ [capistrano-extensions]: Backs up target deployable environment's database (identified
154
+ by the FROM environment variable, which defaults to 'production') and restores it to
155
+ the remote database identified by the TO environment variable, which defaults to "staging."
156
+ DESC
157
+ task :sync_db do
158
+ system("capistrano-extensions-sync-db #{ENV['FROM'] || 'production'} #{ENV['TO'] || 'staging'}")
159
+ end
160
+
161
+ desc <<-DESC
162
+ [capistrano-extensions]: Uploads the backup file downloaded from local:backup_content (specified via the
163
+ FROM env variable), copies it to the remote environment specified by RAILS_ENV, and unpacks it into the
164
+ shared/ directory.
165
+ DESC
166
+ task :restore_content do
167
+ from = ENV['FROM'] || 'production'
168
+
169
+ if deployable_environments.include?(rails_env.to_sym)
170
+ local_backup_file = "#{application}-#{from}-content_backup.tar.gz"
171
+ remote_file = "#{shared_path}/content_backup.tar.gz"
172
+
173
+ if !File.exists?(local_backup_file)
174
+ puts "Could not find backup file: #{local_backup_file}"
175
+ exit 1
176
+ end
177
+
178
+ upload(local_backup_file, "#{remote_file}")
179
+ remote_dirs = ["content"] + shared_content.keys
180
+
181
+ run("cd #{shared_path} && rm -rf #{remote_dirs.join(' ')} && tar xzf #{remote_file} -C #{shared_path}/")
182
+ end
183
+ end
184
+
185
+ desc <<-DESC
186
+ [capistrano-extensions]: Backs up target deployable environment's shared content (identified by the FROM environment
187
+ variable, which defaults to 'production') and restores it to the remote environment identified
188
+ by the TO envrionment variable, which defaults to "staging."
189
+
190
+ Because multiple capistrano configurations must be loaded, an external executable
191
+ (capistrano-extensions-sync_content) is invoked, which independently calls capistrano. See the
192
+ executable at $GEM_HOME/capistrano-extensions-0.1.2/bin/capistrano-extensions-sync_content
193
+
194
+ $> cap remote:sync_content FROM=production TO=staging
195
+ DESC
196
+ task :sync_content do
197
+ system("capistrano-extensions-sync-content #{ENV['FROM'] || 'production'} #{ENV['TO'] || 'staging'}")
198
+ end
199
+
200
+ desc <<-DESC
201
+ [capistrano-extensions]: Wrapper fro remote:sync_db and remote:sync_content.
202
+ $> cap remote:sync FROM=production TO=staging
203
+ DESC
204
+ task :sync do
205
+ sync_db
206
+ sync_content
207
+ end
208
+ end
209
+
210
+ namespace :local do
211
+ desc <<-DESC
212
+ [capistrano-extensions]: Backs up deployable environment's database (identified by the
213
+ RAILS_ENV environment variable, which defaults to 'production') and copies it to the local machine
214
+ DESC
215
+ task :backup_db, :roles => :db do
216
+ pass_str = pluck_pass_str(db)
217
+
218
+ run "mysqldump -u#{db['username']} #{pass_str} #{db['database']} > #{shared_path}/db_backup.sql"
219
+ run "gzip #{shared_path}/db_backup.sql"
220
+ get "#{shared_path}/db_backup.sql.gz", "#{application}-#{rails_env}-db.sql.gz"
221
+ run "rm -f #{shared_path}/db_backup.sql.gz #{shared_path}/db_backup.sql"
222
+ end
223
+
224
+ desc <<-DESC
225
+ [capistrano-extensions] Untars the backup file downloaded from local:backup_db (specified via the FROM env
226
+ variable, which defalts to RAILS_ENV), and imports (via mysql command line tool) it back into the database
227
+ defined in the RAILS_ENV env variable.
228
+
229
+ ToDo: implement proper rollback: currently, if the mysql import succeeds, but the rm fails,
230
+ the database won't be rolled back. Not sure this is even all that important or necessary, since
231
+ it's a local database that doesn't demand integrity (in other words, you're still going to have to
232
+ fix it, but it's not mission critical).
233
+ DESC
234
+ task :restore_db, :roles => :db do
235
+ on_rollback { "gzip #{application}-#{from}-db.sql"}
236
+
237
+ from = ENV['FROM'] || rails_env
238
+
239
+ env = ENV['RESTORE_ENV'] || 'development'
240
+ y = YAML.load_file(local_db_conf(env))[env]
241
+ db, user = y['database'], y['username'] # update me!
242
+
243
+ pass_str = pluck_pass_str(y)
244
+
245
+ puts "\033[1;41m Restoring database backup to #{env} environment \033[0m"
246
+ # local
247
+ system <<-CMD
248
+ gunzip #{application}-#{from}-db.sql.gz &&
249
+ mysql -u#{user} #{pass_str} #{db} < #{application}-#{from}-db.sql
250
+ CMD
251
+ end
252
+
253
+ desc <<-DESC
254
+ [capistrano-extensions]: Downloads a tarball of uploaded content (that lives in public/
255
+ directory, as specified by the :content_directories property) from the production site
256
+ back to the local filesystem
257
+ DESC
258
+ task :backup_content do
259
+ folders = ["content"] + shared_content.keys
260
+
261
+ run "cd #{shared_path} && tar czf #{shared_path}/content_backup.tar.gz #{folders.join(' ')}"
262
+
263
+ #run "cd #{content_path} && tar czf #{shared_path}/content_backup.tar.gz *"
264
+ get "#{shared_path}/content_backup.tar.gz", "#{application}-#{rails_env}-content_backup.tar.gz"
265
+ run "rm -f #{shared_path}/content_backup.tar.gz"
266
+ end
267
+
268
+ desc <<-DESC
269
+ [capistrano-extensions]: Restores the backed up content (evn var FROM specifies which environment
270
+ was backed up, defaults to RAILS_ENV) to the local development environment app
271
+ DESC
272
+ task :restore_content do
273
+ from = ENV['FROM'] || rails_env
274
+
275
+ system "tar xzf #{application}-#{from}-content_backup.tar.gz -C public/"
276
+ system "rm -f #{application}-#{from}-content_backup.tar.gz"
277
+
278
+ shared_content.each_pair do |remote, local|
279
+ system "rm -rf #{local} && mv public/#{remote} #{local}"
280
+ end
281
+
282
+ end
283
+
284
+ desc <<-DESC
285
+ [capistrano-extensions]: Wrapper for local:backup_db and local:restore_db.
286
+ $> cap local:sync_db RAILS_ENV=production RESTORE_ENV=development
287
+ DESC
288
+ task :sync_db do
289
+ transaction do
290
+ backup_db
291
+ ENV['FROM'] = rails_env
292
+ restore_db
293
+ end
294
+ end
295
+
296
+ desc <<-DESC
297
+ [capistrano-extensions]: Wrapper for local:backup_content and local:restore_content
298
+ $> cap local:sync_content RAILS_ENV=production RESTORE_ENV=development
299
+ DESC
300
+ task :sync_content do
301
+ transaction do
302
+ backup_content
303
+ restore_content
304
+ end
305
+ end
306
+
307
+ desc <<-DESC
308
+ [capistrano-extensions]: Wrapper for local:sync_db and local:sync_content
309
+ $> cap local:sync RAILS_ENV=production RESTORE_ENV=development
310
+ DESC
311
+ task :sync do
312
+ sync_db
313
+ sync_content
314
+ end
315
+ end
316
+ end
317
+
318
+ def pluck_pass_str(db_config)
319
+ pass_str = db_config['password']
320
+ if !pass_str.nil?
321
+ pass_str = "-p#{pass_str.gsub('$', '\$')}"
322
+ end
323
+ pass_str || ''
324
+ end
@@ -0,0 +1,35 @@
1
+ require 'geminstaller'
2
+
3
+ Capistrano::Configuration.instance(:must_exist).load do
4
+
5
+ def pluck_accessor_hash(obj, attrs = [])
6
+ ret = {}
7
+ attrs.each do |attr|
8
+ ret[attr] = obj.send(attr)
9
+ end
10
+ ret
11
+ end
12
+
13
+ alias :depend_without_gemfile :depend
14
+
15
+ # Auxiliary helper method for the `deploy:check' task. Lets you set up your
16
+ # own dependencies.
17
+ def depend(location, type, *args)
18
+ if type == :gemfile
19
+ registry = GemInstaller::Registry.new
20
+ config_builder = registry.config_builder
21
+ path = args.pop
22
+ config_builder.config_file_paths = path
23
+ config = config_builder.build_config
24
+ gems = config.gems
25
+
26
+ gems.each do |agem|
27
+ # gem() function defined in Capistrano's RemoteDependency class
28
+ options = pluck_accessor_hash(agem, [:platform, :install_options, :check_for_upgrade, :no_autogem, :fix_dependencies])
29
+ depend_without_gemfile(location, :gem, agem.name, agem.version, options)
30
+ end
31
+ else
32
+ depend_without_gemfile(location, type, *args)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,20 @@
1
+ module CapistranoExtensions
2
+ module Version #:nodoc:
3
+ # A method for comparing versions of required modules. It expects two
4
+ # arrays of integers as parameters, the first being the minimum version
5
+ # required, and the second being the actual version available. It returns
6
+ # true if the actual version is at least equal to the required version.
7
+ def self.check(required, actual) #:nodoc:
8
+ required = required.map { |v| "%06d" % v }.join(".")
9
+ actual = actual.map { |v| "%06d" % v }.join(".")
10
+ return actual >= required
11
+ end
12
+
13
+ MAJOR = 0
14
+ MINOR = 1
15
+ TINY = 3
16
+
17
+ STRING = [MAJOR, MINOR, TINY].join(".")
18
+ end
19
+ end
20
+
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jtrupiano-capistrano-extensions
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.3
5
+ platform: ruby
6
+ authors:
7
+ - John Trupiano
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-08-26 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: capistrano
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.4.3
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: geminstaller
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: 0.4.3
32
+ version:
33
+ - !ruby/object:Gem::Dependency
34
+ name: hoe
35
+ version_requirement:
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 1.7.0
41
+ version:
42
+ description: A base set of Capistrano extensions-- aids with the file_column plugin, the GemInstaller gem, multiple deployable environments, logfile helpers, and database/asset synchronization from production to local environment
43
+ email: jtrupiano@gmail.com
44
+ executables:
45
+ - capistrano-extensions-sync-content
46
+ - capistrano-extensions-sync-db
47
+ extensions: []
48
+
49
+ extra_rdoc_files:
50
+ - History.txt
51
+ - Manifest.txt
52
+ - README.txt
53
+ files:
54
+ - History.txt
55
+ - Manifest.txt
56
+ - README.txt
57
+ - Rakefile
58
+ - bin/capistrano-extensions-sync-content
59
+ - bin/capistrano-extensions-sync-db
60
+ - lib/capistrano-extensions.rb
61
+ - lib/capistrano-extensions/deploy.rb
62
+ - lib/capistrano-extensions/geminstaller_dependency.rb
63
+ - lib/capistrano-extensions/version.rb
64
+ has_rdoc: true
65
+ homepage: http://github.com/jtrupiano/capistrano-extensions
66
+ post_install_message:
67
+ rdoc_options:
68
+ - --main
69
+ - README.txt
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ version:
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: "0"
83
+ version:
84
+ requirements: []
85
+
86
+ rubyforge_project: capistrano-extensions
87
+ rubygems_version: 1.2.0
88
+ signing_key:
89
+ specification_version: 2
90
+ summary: A base set of Capistrano extensions-- aids with the file_column plugin, the GemInstaller gem, multiple deployable environments, logfile helpers, and database/asset synchronization from production to local environment
91
+ test_files: []
92
+