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 +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
|
+
|