capistrano-extensions 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +22 -0
- data/Manifest.txt +11 -0
- data/README.txt +217 -0
- data/Rakefile +47 -0
- data/bin/capistrano-extensions-sync-content +9 -0
- data/bin/capistrano-extensions-sync-db +9 -0
- data/lib/capistrano-extensions.rb +2 -0
- data/lib/capistrano-extensions/deploy.rb +324 -0
- data/lib/capistrano-extensions/geminstaller_dependency.rb +35 -0
- data/lib/capistrano-extensions/version.rb +20 -0
- metadata +95 -0
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 = 'environmentaliz' # 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,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'] || 'root') # 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,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: 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-09-11 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: capistrano
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.4.3
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: geminstaller
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.4.3
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: hoe
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.7.0
|
44
|
+
version:
|
45
|
+
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
|
46
|
+
email: jtrupiano@gmail.com
|
47
|
+
executables:
|
48
|
+
- capistrano-extensions-sync-content
|
49
|
+
- capistrano-extensions-sync-db
|
50
|
+
extensions: []
|
51
|
+
|
52
|
+
extra_rdoc_files:
|
53
|
+
- History.txt
|
54
|
+
- Manifest.txt
|
55
|
+
- README.txt
|
56
|
+
files:
|
57
|
+
- History.txt
|
58
|
+
- Manifest.txt
|
59
|
+
- README.txt
|
60
|
+
- Rakefile
|
61
|
+
- bin/capistrano-extensions-sync-content
|
62
|
+
- bin/capistrano-extensions-sync-db
|
63
|
+
- lib/capistrano-extensions.rb
|
64
|
+
- lib/capistrano-extensions/deploy.rb
|
65
|
+
- lib/capistrano-extensions/geminstaller_dependency.rb
|
66
|
+
- lib/capistrano-extensions/version.rb
|
67
|
+
has_rdoc: true
|
68
|
+
homepage: http://github.com/jtrupiano/capistrano-extensions
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options:
|
71
|
+
- --main
|
72
|
+
- README.txt
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: "0"
|
80
|
+
version:
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: "0"
|
86
|
+
version:
|
87
|
+
requirements: []
|
88
|
+
|
89
|
+
rubyforge_project: environmentaliz
|
90
|
+
rubygems_version: 1.2.0
|
91
|
+
signing_key:
|
92
|
+
specification_version: 2
|
93
|
+
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
|
94
|
+
test_files: []
|
95
|
+
|