capistrano 2.9.0 → 2.11.2
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/.travis.yml +2 -0
- data/CHANGELOG +50 -0
- data/Gemfile +0 -2
- data/README.mdown +1 -1
- data/bin/capify +2 -1
- data/capistrano.gemspec +1 -0
- data/lib/capistrano.rb +2 -0
- data/lib/capistrano/command.rb +6 -1
- data/lib/capistrano/configuration.rb +2 -1
- data/lib/capistrano/configuration/alias_task.rb +25 -0
- data/lib/capistrano/configuration/callbacks.rb +2 -21
- data/lib/capistrano/configuration/execution.rb +1 -1
- data/lib/capistrano/configuration/namespaces.rb +13 -7
- data/lib/capistrano/configuration/roles.rb +4 -0
- data/lib/capistrano/ext/multistage.rb +62 -0
- data/lib/capistrano/fix_rake_deprecated_dsl.rb +8 -0
- data/lib/capistrano/recipes/deploy.rb +43 -15
- data/lib/capistrano/recipes/deploy/assets.rb +2 -0
- data/lib/capistrano/recipes/deploy/scm/bzr.rb +1 -1
- data/lib/capistrano/recipes/deploy/strategy/copy.rb +29 -3
- data/lib/capistrano/ssh.rb +0 -6
- data/lib/capistrano/task_definition.rb +12 -10
- data/lib/capistrano/transfer.rb +5 -3
- data/lib/capistrano/version.rb +2 -2
- data/test/command_test.rb +15 -1
- data/test/configuration/alias_task_test.rb +110 -0
- data/test/configuration/callbacks_test.rb +0 -43
- data/test/configuration/roles_test.rb +13 -0
- data/test/configuration_test.rb +0 -11
- data/test/deploy/strategy/copy_test.rb +21 -7
- data/test/task_definition_test.rb +10 -9
- data/test/transfer_test.rb +8 -0
- data/test/utils.rb +0 -1
- metadata +20 -17
- data/.rvmrc +0 -1
- data/rvmrc.sample +0 -1
data/.travis.yml
CHANGED
data/CHANGELOG
CHANGED
@@ -1,3 +1,53 @@
|
|
1
|
+
## 2.11.2 / Febuary 22 2012
|
2
|
+
|
3
|
+
Fixes some bugs with the now deprecated `deploy:symlink` fallback option.
|
4
|
+
|
5
|
+
## 2.11.0 / Febuary 20 2012
|
6
|
+
|
7
|
+
This release replaces and fixes a broken 2.10.0 release (see below for
|
8
|
+
information)
|
9
|
+
|
10
|
+
This release includes all fixes as documented for 2.10.0, plus additional code
|
11
|
+
cleanup (SHA: 3eecac2), as well as changing the public API from
|
12
|
+
`deploy:symlink`, to `deploy:create_symlink`
|
13
|
+
|
14
|
+
* Remove a testing dependency on `ruby-debug` (Lee Hambley, reported by Serg
|
15
|
+
Podtynnyi)
|
16
|
+
|
17
|
+
* Formerly deprecate `deploy:symlink`, this move was prompted by the Rake
|
18
|
+
namespace fiasco of their 0.9.0 release, and is replaced by
|
19
|
+
`deploy:create_symlink`. If you are looking for a place to hook asset related
|
20
|
+
tasks, please consider `deploy:finalize_update`. Replaced by
|
21
|
+
`deploy:create_symlink`, `deploy:symlink` now raises a deprecation warning,
|
22
|
+
and defers to `deploy:symlink`. (Lee Hambley)
|
23
|
+
|
24
|
+
* Update the 2.10.0 changelog. (Lee Hambley, reported by Jérémy Lecour)
|
25
|
+
|
26
|
+
## 2.10.0 / Febuary 19 2012
|
27
|
+
|
28
|
+
If you are reading this after Febuary 20th 2012, do not be surprised when you
|
29
|
+
cannot find 2.10.0 on Rubygems.org, it has been removed because of a breaking
|
30
|
+
API change. It is replaced logically enough by 2.11.0 where the API is still
|
31
|
+
changed, but now issues a warning and falls back to the expected behaviour.
|
32
|
+
|
33
|
+
The CHANGELOG for this release was updated retrospectively, I'm sorry I missed
|
34
|
+
that when releasing the gem, 2.10.0 apparently not my finest hour as a
|
35
|
+
maintainer.
|
36
|
+
|
37
|
+
Ths fixes in this release include
|
38
|
+
|
39
|
+
* Include sample NGinx config for `deploy:web:disable`(added by Roger Ertesvåg)
|
40
|
+
|
41
|
+
* Fix gemspec time format warning (reported by Tony Arcieri, fixed by building the Gem against Ruby-1.9.3)
|
42
|
+
|
43
|
+
* Finally removed deprecated `before_` and `after_` tasks. (Lee Hambley)
|
44
|
+
|
45
|
+
* Rake 0.9.x compatibility (reported by James Miller, fixed by Lee Hambley)
|
46
|
+
|
47
|
+
* More detailed logging output (fixed by Huang Liang)
|
48
|
+
|
49
|
+
* Includes multistage, without `capistrano-ext`. `require 'capistrano/ext/multistage'` (fixed by Lee Hambley)
|
50
|
+
|
1
51
|
## 2.9.0 / September 24 2011
|
2
52
|
|
3
53
|
A vairly heavy release, including some new features which most of you won't
|
data/Gemfile
CHANGED
data/README.mdown
CHANGED
@@ -67,7 +67,7 @@ tasks.
|
|
67
67
|
* Push to your branch - `git push origin my_branch`
|
68
68
|
* Create a Pull Request from your branch, include as much documentation
|
69
69
|
as you can in the commit message/pull request, following these
|
70
|
-
[
|
70
|
+
[guidelines on writing a good commit message](http://spheredev.org/wiki/Git_for_the_lazy#Writing_good_commit_messages)
|
71
71
|
* That's it!
|
72
72
|
|
73
73
|
|
data/bin/capify
CHANGED
data/capistrano.gemspec
CHANGED
data/lib/capistrano.rb
CHANGED
data/lib/capistrano/command.rb
CHANGED
@@ -219,6 +219,8 @@ module Capistrano
|
|
219
219
|
command_line = [environment, shell, cmd].compact.join(" ")
|
220
220
|
ch[:command] = command_line
|
221
221
|
|
222
|
+
logger.trace command_line, ch[:server] if logger
|
223
|
+
|
222
224
|
ch.exec(command_line)
|
223
225
|
ch.send_data(options[:data]) if options[:data]
|
224
226
|
else
|
@@ -261,7 +263,10 @@ module Capistrano
|
|
261
263
|
end
|
262
264
|
|
263
265
|
def replace_placeholders(command, channel)
|
264
|
-
|
266
|
+
roles = @tree.configuration && @tree.configuration.role_names_for_host(channel[:server])
|
267
|
+
command = command.gsub(/\$CAPISTRANO:HOST\$/, channel[:host])
|
268
|
+
command.gsub!(/\$CAPISTRANO:HOSTROLES\$/, roles.join(',')) if roles
|
269
|
+
command
|
265
270
|
end
|
266
271
|
|
267
272
|
# prepare a space-separated sequence of variables assignments
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'capistrano/logger'
|
2
2
|
|
3
|
+
require 'capistrano/configuration/alias_task'
|
3
4
|
require 'capistrano/configuration/callbacks'
|
4
5
|
require 'capistrano/configuration/connections'
|
5
6
|
require 'capistrano/configuration/execution'
|
@@ -33,7 +34,7 @@ module Capistrano
|
|
33
34
|
|
34
35
|
# The includes must come at the bottom, since they may redefine methods
|
35
36
|
# defined in the base class.
|
36
|
-
include Connections, Execution, Loading, Namespaces, Roles, Servers, Variables
|
37
|
+
include AliasTask, Connections, Execution, Loading, Namespaces, Roles, Servers, Variables
|
37
38
|
|
38
39
|
# Mix in the actions
|
39
40
|
include Actions::FileTransfer, Actions::Inspect, Actions::Invocation
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Capistrano
|
2
|
+
class Configuration
|
3
|
+
module AliasTask
|
4
|
+
# Attempts to find the task at the given fully-qualified path, and
|
5
|
+
# alias it. If arguments don't have correct task names, an ArgumentError
|
6
|
+
# wil be raised. If no such task exists, a Capistrano::NoSuchTaskError
|
7
|
+
# will be raised.
|
8
|
+
#
|
9
|
+
# Usage:
|
10
|
+
#
|
11
|
+
# alias_task :original_deploy, :deploy
|
12
|
+
#
|
13
|
+
def alias_task(new_name, old_name)
|
14
|
+
if !new_name.respond_to?(:to_sym) or !old_name.respond_to?(:to_sym)
|
15
|
+
raise ArgumentError, "expected a valid task name"
|
16
|
+
end
|
17
|
+
|
18
|
+
task = find_task(old_name) or raise NoSuchTaskError, "the task `#{old_name}' does not exist"
|
19
|
+
task.name = new_name
|
20
|
+
|
21
|
+
define_task(task)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -19,18 +19,13 @@ module Capistrano
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def invoke_task_directly_with_callbacks(task) #:nodoc:
|
22
|
-
|
23
|
-
execute_task(before) if before
|
24
|
-
|
22
|
+
|
25
23
|
trigger :before, task
|
26
24
|
|
27
25
|
result = invoke_task_directly_without_callbacks(task)
|
28
26
|
|
29
27
|
trigger :after, task
|
30
28
|
|
31
|
-
after = find_hook(task, :after)
|
32
|
-
execute_task(after) if after
|
33
|
-
|
34
29
|
return result
|
35
30
|
end
|
36
31
|
|
@@ -129,20 +124,6 @@ module Capistrano
|
|
129
124
|
end
|
130
125
|
end
|
131
126
|
|
132
|
-
private
|
133
|
-
|
134
|
-
# Looks for before_foo or after_foo tasks. This method of extending tasks
|
135
|
-
# is now discouraged (though not formally deprecated). You should use the
|
136
|
-
# before and after methods to declare hooks for such callbacks.
|
137
|
-
def find_hook(task, hook)
|
138
|
-
if task == task.namespace.default_task
|
139
|
-
result = task.namespace.search_task("#{hook}_#{task.namespace.name}")
|
140
|
-
return result if result
|
141
|
-
end
|
142
|
-
|
143
|
-
task.namespace.search_task("#{hook}_#{task.name}")
|
144
|
-
end
|
145
|
-
|
146
127
|
end
|
147
128
|
end
|
148
|
-
end
|
129
|
+
end
|
@@ -97,12 +97,17 @@ module Capistrano
|
|
97
97
|
raise ArgumentError, "defining a task named `#{name}' would shadow an existing #{thing} with that name"
|
98
98
|
end
|
99
99
|
|
100
|
-
tasks[name] = TaskDefinition.new(name, self, {:desc => next_description(:reset)}.merge(options), &block)
|
101
100
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
101
|
+
task = TaskDefinition.new(name, self, {:desc => next_description(:reset)}.merge(options), &block)
|
102
|
+
|
103
|
+
define_task(task)
|
104
|
+
end
|
105
|
+
|
106
|
+
def define_task(task)
|
107
|
+
tasks[task.name] = task
|
108
|
+
|
109
|
+
metaclass = class << self; self; end
|
110
|
+
metaclass.send(:define_method, task.name) { execute_task(tasks[task.name]) }
|
106
111
|
end
|
107
112
|
|
108
113
|
# Find the task with the given name, where name is the fully-qualified
|
@@ -151,7 +156,7 @@ module Capistrano
|
|
151
156
|
return nil if parent.nil?
|
152
157
|
return tasks[DEFAULT_TASK]
|
153
158
|
end
|
154
|
-
|
159
|
+
|
155
160
|
# Returns the tasks in this namespace as an array of TaskDefinition
|
156
161
|
# objects. If a non-false parameter is given, all tasks in all
|
157
162
|
# namespaces under this namespace will be returned as well.
|
@@ -189,9 +194,10 @@ module Capistrano
|
|
189
194
|
end
|
190
195
|
end
|
191
196
|
|
197
|
+
include Capistrano::Configuration::AliasTask
|
192
198
|
include Capistrano::Configuration::Namespaces
|
193
199
|
undef :desc, :next_description
|
194
200
|
end
|
195
201
|
end
|
196
202
|
end
|
197
|
-
end
|
203
|
+
end
|
@@ -68,6 +68,10 @@ module Capistrano
|
|
68
68
|
raise ArgumentError, "you must associate a server with at least one role" if roles.empty?
|
69
69
|
roles.each { |name| role(name, host, options) }
|
70
70
|
end
|
71
|
+
|
72
|
+
def role_names_for_host(host)
|
73
|
+
roles.map {|role_name, role| role_name if role.include?(host) }.compact || []
|
74
|
+
end
|
71
75
|
end
|
72
76
|
end
|
73
77
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
unless Capistrano::Configuration.respond_to?(:instance)
|
4
|
+
abort "capistrano/ext/multistage requires Capistrano 2"
|
5
|
+
end
|
6
|
+
|
7
|
+
Capistrano::Configuration.instance.load do
|
8
|
+
location = fetch(:stage_dir, "config/deploy")
|
9
|
+
|
10
|
+
unless exists?(:stages)
|
11
|
+
set :stages, Dir["#{location}/*.rb"].map { |f| File.basename(f, ".rb") }
|
12
|
+
end
|
13
|
+
|
14
|
+
stages.each do |name|
|
15
|
+
desc "Set the target stage to `#{name}'."
|
16
|
+
task(name) do
|
17
|
+
set :stage, name.to_sym
|
18
|
+
load "#{location}/#{stage}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
on :load do
|
23
|
+
if stages.include?(ARGV.first)
|
24
|
+
# Execute the specified stage so that recipes required in stage can contribute to task list
|
25
|
+
find_and_execute_task(ARGV.first) if ARGV.any?{ |option| option =~ /-T|--tasks|-e|--explain/ }
|
26
|
+
else
|
27
|
+
# Execute the default stage so that recipes required in stage can contribute tasks
|
28
|
+
find_and_execute_task(default_stage) if exists?(:default_stage)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
namespace :multistage do
|
33
|
+
desc "[internal] Ensure that a stage has been selected."
|
34
|
+
task :ensure do
|
35
|
+
if !exists?(:stage)
|
36
|
+
if exists?(:default_stage)
|
37
|
+
logger.important "Defaulting to `#{default_stage}'"
|
38
|
+
find_and_execute_task(default_stage)
|
39
|
+
else
|
40
|
+
abort "No stage specified. Please specify one of: #{stages.join(', ')} (e.g. `cap #{stages.first} #{ARGV.last}')"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "Stub out the staging config files."
|
46
|
+
task :prepare do
|
47
|
+
FileUtils.mkdir_p(location)
|
48
|
+
stages.each do |name|
|
49
|
+
file = File.join(location, name + ".rb")
|
50
|
+
unless File.exists?(file)
|
51
|
+
File.open(file, "w") do |f|
|
52
|
+
f.puts "# #{name.upcase}-specific deployment configuration"
|
53
|
+
f.puts "# please put general deployment config in config/deploy.rb"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
on :start, "multistage:ensure", :except => stages + ['multistage:prepare']
|
61
|
+
|
62
|
+
end
|
@@ -32,6 +32,7 @@ _cset :rails_env, "production"
|
|
32
32
|
_cset :rake, "rake"
|
33
33
|
|
34
34
|
_cset :maintenance_basename, "maintenance"
|
35
|
+
_cset(:maintenance_template_path) { File.join(File.dirname(__FILE__), "templates", "maintenance.rhtml") }
|
35
36
|
|
36
37
|
# =========================================================================
|
37
38
|
# These variables should NOT be changed unless you are very confident in
|
@@ -49,7 +50,7 @@ _cset(:release_name) { set :deploy_timestamped, true; Time.now.utc.strftime
|
|
49
50
|
|
50
51
|
_cset :version_dir, "releases"
|
51
52
|
_cset :shared_dir, "shared"
|
52
|
-
_cset :shared_children, %w(system log pids)
|
53
|
+
_cset :shared_children, %w(public/system log tmp/pids)
|
53
54
|
_cset :current_dir, "current"
|
54
55
|
|
55
56
|
_cset(:releases_path) { File.join(deploy_to, version_dir) }
|
@@ -184,7 +185,7 @@ namespace :deploy do
|
|
184
185
|
DESC
|
185
186
|
task :setup, :except => { :no_release => true } do
|
186
187
|
dirs = [deploy_to, releases_path, shared_path]
|
187
|
-
dirs += shared_children.map { |d| File.join(shared_path, d) }
|
188
|
+
dirs += shared_children.map { |d| File.join(shared_path, d.split('/').last) }
|
188
189
|
run "#{try_sudo} mkdir -p #{dirs.join(' ')}"
|
189
190
|
run "#{try_sudo} chmod g+w #{dirs.join(' ')}" if fetch(:group_writable, true)
|
190
191
|
end
|
@@ -200,7 +201,7 @@ namespace :deploy do
|
|
200
201
|
task :update do
|
201
202
|
transaction do
|
202
203
|
update_code
|
203
|
-
|
204
|
+
create_symlink
|
204
205
|
end
|
205
206
|
end
|
206
207
|
|
@@ -246,11 +247,11 @@ namespace :deploy do
|
|
246
247
|
run <<-CMD
|
247
248
|
rm -rf #{latest_release}/log #{latest_release}/public/system #{latest_release}/tmp/pids &&
|
248
249
|
mkdir -p #{latest_release}/public &&
|
249
|
-
mkdir -p #{latest_release}/tmp
|
250
|
-
ln -s #{shared_path}/log #{latest_release}/log &&
|
251
|
-
ln -s #{shared_path}/system #{latest_release}/public/system &&
|
252
|
-
ln -s #{shared_path}/pids #{latest_release}/tmp/pids
|
250
|
+
mkdir -p #{latest_release}/tmp
|
253
251
|
CMD
|
252
|
+
shared_children.map do |d|
|
253
|
+
run "ln -s #{shared_path}/#{d.split('/').last} #{latest_release}/#{d}"
|
254
|
+
end
|
254
255
|
|
255
256
|
if fetch(:normalize_asset_timestamps, true)
|
256
257
|
stamp = Time.now.utc.strftime("%Y%m%d%H%M.%S")
|
@@ -259,6 +260,13 @@ namespace :deploy do
|
|
259
260
|
end
|
260
261
|
end
|
261
262
|
|
263
|
+
desc <<-DESC
|
264
|
+
Deprecated API. This has become deploy:create_symlink, please update your recipes
|
265
|
+
DESC
|
266
|
+
task :symlink, :except => { :no_release => true } do
|
267
|
+
Kernel.warn "[Deprecation Warning] This API has changed, please hook `deploy:create_symlink` instead of `deploy:symlink`."
|
268
|
+
end
|
269
|
+
|
262
270
|
desc <<-DESC
|
263
271
|
Updates the symlink to the most recently deployed version. Capistrano works \
|
264
272
|
by putting each new release of your application in its own directory. When \
|
@@ -268,7 +276,10 @@ namespace :deploy do
|
|
268
276
|
deploy, including `restart') or the 'update' task (which does everything \
|
269
277
|
except `restart').
|
270
278
|
DESC
|
271
|
-
task :
|
279
|
+
task :create_symlink, :except => { :no_release => true } do
|
280
|
+
|
281
|
+
symlink # (Deprecated)
|
282
|
+
|
272
283
|
on_rollback do
|
273
284
|
if previous_release
|
274
285
|
run "rm -f #{current_path}; ln -s #{previous_release} #{current_path}; true"
|
@@ -375,6 +386,8 @@ namespace :deploy do
|
|
375
386
|
set :migrate_target, :latest
|
376
387
|
DESC
|
377
388
|
task :migrate, :roles => :db, :only => { :primary => true } do
|
389
|
+
rake = fetch(:rake, "rake")
|
390
|
+
rails_env = fetch(:rails_env, "production")
|
378
391
|
migrate_env = fetch(:migrate_env, "")
|
379
392
|
migrate_target = fetch(:migrate_target, :latest)
|
380
393
|
|
@@ -398,7 +411,7 @@ namespace :deploy do
|
|
398
411
|
set :migrate_target, :latest
|
399
412
|
update_code
|
400
413
|
migrate
|
401
|
-
|
414
|
+
create_symlink
|
402
415
|
restart
|
403
416
|
end
|
404
417
|
|
@@ -411,12 +424,12 @@ namespace :deploy do
|
|
411
424
|
DESC
|
412
425
|
task :cleanup, :except => { :no_release => true } do
|
413
426
|
count = fetch(:keep_releases, 5).to_i
|
414
|
-
|
427
|
+
local_releases = capture("ls -xt #{releases_path}").split.reverse
|
428
|
+
if count >= local_releases.length
|
415
429
|
logger.important "no old releases to clean up"
|
416
430
|
else
|
417
|
-
logger.info "keeping #{count} of #{
|
418
|
-
|
419
|
-
directories = (releases - releases.last(count)).map { |release|
|
431
|
+
logger.info "keeping #{count} of #{local_releases.length} deployed releases"
|
432
|
+
directories = (local_releases - local_releases.last(count)).map { |release|
|
420
433
|
File.join(releases_path, release) }.join(" ")
|
421
434
|
|
422
435
|
try_sudo "rm -rf #{directories}"
|
@@ -527,6 +540,10 @@ namespace :deploy do
|
|
527
540
|
REASON="hardware upgrade" \\
|
528
541
|
UNTIL="12pm Central Time"
|
529
542
|
|
543
|
+
You can use a different template for the maintenance page by setting the \
|
544
|
+
:maintenance_template_path variable in your deploy.rb file. The template file \
|
545
|
+
should either be a plaintext or an erb file.
|
546
|
+
|
530
547
|
Further customization will require that you write your own task.
|
531
548
|
DESC
|
532
549
|
task :disable, :roles => :web, :except => { :no_release => true } do
|
@@ -535,7 +552,7 @@ namespace :deploy do
|
|
535
552
|
|
536
553
|
warn <<-EOHTACCESS
|
537
554
|
|
538
|
-
# Please add something like this to your site's htaccess to redirect users to the maintenance page.
|
555
|
+
# Please add something like this to your site's Apache htaccess to redirect users to the maintenance page.
|
539
556
|
# More Info: http://www.shiftcommathree.com/articles/make-your-rails-maintenance-page-respond-with-a-503
|
540
557
|
|
541
558
|
ErrorDocument 503 /system/#{maintenance_basename}.html
|
@@ -544,12 +561,23 @@ namespace :deploy do
|
|
544
561
|
RewriteCond %{DOCUMENT_ROOT}/system/#{maintenance_basename}.html -f
|
545
562
|
RewriteCond %{SCRIPT_FILENAME} !#{maintenance_basename}.html
|
546
563
|
RewriteRule ^.*$ - [redirect=503,last]
|
564
|
+
|
565
|
+
# Or if you are using Nginx add this to your server config:
|
566
|
+
|
567
|
+
if (-f $document_root/system/maintenance.html) {
|
568
|
+
return 503;
|
569
|
+
}
|
570
|
+
error_page 503 @maintenance;
|
571
|
+
location @maintenance {
|
572
|
+
rewrite ^(.*)$ /system/maintenance.html last;
|
573
|
+
break;
|
574
|
+
}
|
547
575
|
EOHTACCESS
|
548
576
|
|
549
577
|
reason = ENV['REASON']
|
550
578
|
deadline = ENV['UNTIL']
|
551
579
|
|
552
|
-
template = File.read(
|
580
|
+
template = File.read(maintenance_template_path)
|
553
581
|
result = ERB.new(template).result(binding)
|
554
582
|
|
555
583
|
put result, "#{shared_path}/system/#{maintenance_basename}.html", :mode => 0644
|
@@ -3,6 +3,8 @@ load 'deploy' unless defined?(_cset)
|
|
3
3
|
_cset :asset_env, "RAILS_GROUPS=assets"
|
4
4
|
_cset :assets_prefix, "assets"
|
5
5
|
|
6
|
+
_cset :normalize_asset_timestamps, false
|
7
|
+
|
6
8
|
before 'deploy:finalize_update', 'deploy:assets:symlink'
|
7
9
|
after 'deploy:update_code', 'deploy:assets:precompile'
|
8
10
|
|
@@ -38,6 +38,16 @@ module Capistrano
|
|
38
38
|
# :copy_compression, which must be one of :gzip, :bz2, or
|
39
39
|
# :zip, and which specifies how the source should be compressed for
|
40
40
|
# transmission to each host.
|
41
|
+
#
|
42
|
+
# There is a possibility to pass a build command that will get
|
43
|
+
# executed if your code needs to be compiled or something needs to be
|
44
|
+
# done before the code is ready to run.
|
45
|
+
#
|
46
|
+
# set :build_script, "make all"
|
47
|
+
#
|
48
|
+
# Note that if you use :copy_cache, the :build_script is used on the
|
49
|
+
# cache and thus you get faster compilation if your script does not
|
50
|
+
# recompile everything.
|
41
51
|
class Copy < Base
|
42
52
|
# Obtains a copy of the source code locally (via the #command method),
|
43
53
|
# compresses it to a single file, copies that file to all target
|
@@ -58,6 +68,8 @@ module Capistrano
|
|
58
68
|
raise Capistrano::Error, "shell command failed with return code #{$?}"
|
59
69
|
end
|
60
70
|
|
71
|
+
build(copy_cache)
|
72
|
+
|
61
73
|
FileUtils.mkdir_p(destination)
|
62
74
|
|
63
75
|
logger.debug "copying cache to deployment staging area #{destination}"
|
@@ -84,6 +96,8 @@ module Capistrano
|
|
84
96
|
logger.debug "getting (via #{copy_strategy}) revision #{revision} to #{destination}"
|
85
97
|
system(command)
|
86
98
|
|
99
|
+
build(destination)
|
100
|
+
|
87
101
|
if copy_exclude.any?
|
88
102
|
logger.debug "processing exclusions..."
|
89
103
|
|
@@ -107,6 +121,18 @@ module Capistrano
|
|
107
121
|
FileUtils.rm_rf destination rescue nil
|
108
122
|
end
|
109
123
|
|
124
|
+
def build(directory)
|
125
|
+
return unless configuration[:build_script]
|
126
|
+
|
127
|
+
Dir.chdir(directory) do
|
128
|
+
self.system(configuration[:build_script])
|
129
|
+
# Check the return code of last system command and rollback if not 0
|
130
|
+
unless $? == 0
|
131
|
+
raise Capistrano::Error, "shell command failed with return code #{$?}"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
110
136
|
def check!
|
111
137
|
super.check do |d|
|
112
138
|
d.local.command(source.local.command) if source.local.command
|
@@ -191,9 +217,9 @@ module Capistrano
|
|
191
217
|
|
192
218
|
type = configuration[:copy_compression] || :gzip
|
193
219
|
case type
|
194
|
-
when :gzip, :gz then Compression.new("tar.gz", [local_tar, '
|
195
|
-
when :bzip2, :bz2 then Compression.new("tar.bz2", [local_tar, '
|
196
|
-
when :zip then Compression.new("zip", %w(zip -
|
220
|
+
when :gzip, :gz then Compression.new("tar.gz", [local_tar, 'czf'], [remote_tar, 'xzf'])
|
221
|
+
when :bzip2, :bz2 then Compression.new("tar.bz2", [local_tar, 'cjf'], [remote_tar, 'xjf'])
|
222
|
+
when :zip then Compression.new("zip", %w(zip -qyr), %w(unzip -q))
|
197
223
|
else raise ArgumentError, "invalid compression type #{type.inspect}"
|
198
224
|
end
|
199
225
|
end
|
data/lib/capistrano/ssh.rb
CHANGED
@@ -1,22 +1,18 @@
|
|
1
1
|
require 'capistrano/server_definition'
|
2
2
|
|
3
3
|
module Capistrano
|
4
|
-
|
4
|
+
|
5
5
|
class TaskDefinition
|
6
|
+
|
6
7
|
attr_reader :name, :namespace, :options, :body, :desc, :on_error, :max_hosts
|
7
8
|
|
8
9
|
def initialize(name, namespace, options={}, &block)
|
9
|
-
|
10
|
-
if name.to_s =~ /^(?:before_|after_)/
|
11
|
-
Kernel.warn("[Deprecation Warning] Naming tasks with before_ and after_ is deprecated, please see the new before() and after() methods. (Offending task name was #{name})")
|
12
|
-
end
|
13
|
-
|
14
10
|
@name, @namespace, @options = name, namespace, options
|
15
|
-
@desc
|
16
|
-
@on_error
|
11
|
+
@desc = @options.delete(:desc)
|
12
|
+
@on_error = options.delete(:on_error)
|
17
13
|
@max_hosts = options[:max_hosts] && options[:max_hosts].to_i
|
18
|
-
@body
|
19
|
-
@servers
|
14
|
+
@body = block or raise ArgumentError, "a task requires a block"
|
15
|
+
@servers = nil
|
20
16
|
end
|
21
17
|
|
22
18
|
# Returns the task's fully-qualified name, including the namespace
|
@@ -30,6 +26,11 @@ module Capistrano
|
|
30
26
|
end
|
31
27
|
end
|
32
28
|
|
29
|
+
def name=(value)
|
30
|
+
raise ArgumentError, "expected a valid task name" if !value.respond_to?(:to_sym)
|
31
|
+
@name = value.to_sym
|
32
|
+
end
|
33
|
+
|
33
34
|
# Returns the description for this task, with newlines collapsed and
|
34
35
|
# whitespace stripped. Returns the empty string if there is no
|
35
36
|
# description for this task.
|
@@ -71,5 +72,6 @@ module Capistrano
|
|
71
72
|
def continue_on_error?
|
72
73
|
@on_error == :continue
|
73
74
|
end
|
75
|
+
|
74
76
|
end
|
75
77
|
end
|
data/lib/capistrano/transfer.rb
CHANGED
@@ -117,7 +117,7 @@ module Capistrano
|
|
117
117
|
|
118
118
|
def prepare_scp_transfer(from, to, session)
|
119
119
|
real_callback = callback || Proc.new do |channel, name, sent, total|
|
120
|
-
logger.trace "
|
120
|
+
logger.trace "#{transport} #{operation} #{from} -> #{to}", channel[:host] if logger && sent == 0
|
121
121
|
end
|
122
122
|
|
123
123
|
channel = case direction
|
@@ -167,9 +167,9 @@ module Capistrano
|
|
167
167
|
if callback
|
168
168
|
callback.call(event, op, *args)
|
169
169
|
elsif event == :open
|
170
|
-
logger.trace "
|
170
|
+
logger.trace "#{transport} #{operation} #{from} -> #{to}", op[:host]
|
171
171
|
elsif event == :finish
|
172
|
-
logger.trace "
|
172
|
+
logger.trace "#{transport} #{operation} #{from} -> #{to} done", op[:host]
|
173
173
|
end
|
174
174
|
end
|
175
175
|
|
@@ -203,6 +203,8 @@ module Capistrano
|
|
203
203
|
end
|
204
204
|
|
205
205
|
def handle_error(error)
|
206
|
+
raise error if error.message.include?('expected a file to upload')
|
207
|
+
|
206
208
|
transfer = session_map[error.session]
|
207
209
|
transfer[:error] = error
|
208
210
|
transfer[:failed] = true
|
data/lib/capistrano/version.rb
CHANGED
data/test/command_test.rb
CHANGED
@@ -226,13 +226,27 @@ class CommandTest < Test::Unit::TestCase
|
|
226
226
|
Capistrano::Command.process("ls -l", %w(a b c), :foo => "bar")
|
227
227
|
end
|
228
228
|
|
229
|
-
def
|
229
|
+
def test_process_with_host_placeholder_should_substitute_host_placeholder_with_each_host
|
230
230
|
session = setup_for_extracting_channel_action do |ch|
|
231
231
|
ch.expects(:exec).with(%(sh -c 'echo capistrano'))
|
232
232
|
end
|
233
233
|
Capistrano::Command.new("echo $CAPISTRANO:HOST$", [session])
|
234
234
|
end
|
235
235
|
|
236
|
+
class MockConfig
|
237
|
+
include Capistrano::Configuration::Roles
|
238
|
+
end
|
239
|
+
|
240
|
+
def test_hostroles_substitution
|
241
|
+
@config = MockConfig.new
|
242
|
+
@config.server "capistrano", :db, :worker
|
243
|
+
server = @config.roles[:db].servers.first
|
244
|
+
channel = {:server => server, :host => 'capistrano'}
|
245
|
+
tree = Capistrano::Command::Tree.new(@config) { |t| t.else("echo $CAPISTRANO:HOSTROLES$") }
|
246
|
+
result = Capistrano::Command.new(tree, []).send(:replace_placeholders, "echo $CAPISTRANO:HOSTROLES$", channel)
|
247
|
+
assert result == "echo db,worker" || result == "echo worker,db"
|
248
|
+
end
|
249
|
+
|
236
250
|
def test_process_with_unknown_placeholder_should_not_replace_placeholder
|
237
251
|
session = setup_for_extracting_channel_action do |ch|
|
238
252
|
ch.expects(:exec).with(%(sh -c 'echo $CAPISTRANO:OTHER$'))
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'utils'
|
2
|
+
require 'capistrano/configuration/alias_task'
|
3
|
+
require 'capistrano/configuration/execution'
|
4
|
+
require 'capistrano/configuration/namespaces'
|
5
|
+
require 'capistrano/task_definition'
|
6
|
+
|
7
|
+
class AliasTaskTest < Test::Unit::TestCase
|
8
|
+
class MockConfig
|
9
|
+
attr_reader :options
|
10
|
+
attr_accessor :logger
|
11
|
+
|
12
|
+
def initialize(options={})
|
13
|
+
@options = {}
|
14
|
+
@logger = options.delete(:logger)
|
15
|
+
end
|
16
|
+
|
17
|
+
include Capistrano::Configuration::AliasTask
|
18
|
+
include Capistrano::Configuration::Execution
|
19
|
+
include Capistrano::Configuration::Namespaces
|
20
|
+
end
|
21
|
+
|
22
|
+
def setup
|
23
|
+
@config = MockConfig.new( :logger => stub(:debug => nil, :info => nil, :important => nil) )
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_makes_a_copy_of_the_task
|
27
|
+
@config.task(:foo) { 42 }
|
28
|
+
@config.alias_task 'new_foo', 'foo'
|
29
|
+
|
30
|
+
assert @config.tasks.key?(:new_foo)
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_aliased_task_do_the_same
|
34
|
+
@config.task(:foo) { 42 }
|
35
|
+
@config.alias_task 'new_foo', 'foo'
|
36
|
+
|
37
|
+
assert_equal 42, @config.find_and_execute_task('new_foo')
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_aliased_task_should_preserve_description
|
41
|
+
@config.task(:foo, :desc => "the Ultimate Question of Life, the Universe, and Everything" ) { 42 }
|
42
|
+
@config.alias_task 'new_foo', 'foo'
|
43
|
+
|
44
|
+
task = @config.find_task('foo')
|
45
|
+
new_task = @config.find_task('new_foo')
|
46
|
+
|
47
|
+
assert_equal task.description, new_task.description
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_aliased_task_should_preserve_on_error
|
51
|
+
@config.task(:foo, :on_error => :continue) { 42 }
|
52
|
+
@config.alias_task 'new_foo', 'foo'
|
53
|
+
|
54
|
+
task = @config.find_task('foo')
|
55
|
+
new_task = @config.find_task('new_foo')
|
56
|
+
|
57
|
+
assert_equal task.on_error, new_task.on_error
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_aliased_task_should_preserve_max_hosts
|
61
|
+
@config.task(:foo, :max_hosts => 5) { 42 }
|
62
|
+
@config.alias_task 'new_foo', 'foo'
|
63
|
+
|
64
|
+
task = @config.find_task('foo')
|
65
|
+
new_task = @config.find_task('new_foo')
|
66
|
+
|
67
|
+
assert_equal task.max_hosts, new_task.max_hosts
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_raise_exception_when_task_doesnt_exist
|
71
|
+
assert_raises(Capistrano::NoSuchTaskError) { @config.alias_task 'non_existant_task', 'fail_miserably' }
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_convert_task_names_using_to_str
|
75
|
+
@config.task(:foo, :role => :app) { 42 }
|
76
|
+
|
77
|
+
@config.alias_task 'one', 'foo'
|
78
|
+
@config.alias_task :two, 'foo'
|
79
|
+
@config.alias_task 'three', :foo
|
80
|
+
@config.alias_task :four, :foo
|
81
|
+
|
82
|
+
assert @config.tasks.key?(:one)
|
83
|
+
assert @config.tasks.key?(:two)
|
84
|
+
assert @config.tasks.key?(:three)
|
85
|
+
assert @config.tasks.key?(:four)
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_raise_an_exception_when_task_names_can_not_be_converted
|
89
|
+
@config.task(:foo, :role => :app) { 42 }
|
90
|
+
|
91
|
+
assert_raises(ArgumentError) { @config.alias_task mock('x'), :foo }
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_should_include_namespace
|
95
|
+
@config.namespace(:outer) do
|
96
|
+
task(:foo) { 42 }
|
97
|
+
alias_task 'new_foo', 'foo'
|
98
|
+
|
99
|
+
namespace(:inner) do
|
100
|
+
task(:foo) { 43 }
|
101
|
+
alias_task 'new_foo', 'foo'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
assert_equal 42, @config.find_and_execute_task('outer:new_foo')
|
106
|
+
assert_equal 42, @config.find_and_execute_task('outer:foo')
|
107
|
+
assert_equal 43, @config.find_and_execute_task('outer:inner:new_foo')
|
108
|
+
assert_equal 43, @config.find_and_execute_task('outer:inner:foo')
|
109
|
+
end
|
110
|
+
end
|
@@ -174,47 +174,4 @@ class ConfigurationCallbacksTest < Test::Unit::TestCase
|
|
174
174
|
assert_equal [task], @config.called
|
175
175
|
end
|
176
176
|
|
177
|
-
def test_execute_task_with_named_before_hook_should_call_named_before_hook
|
178
|
-
ns = stub("namespace", :default_task => nil, :name => "old", :fully_qualified_name => "any:old")
|
179
|
-
task = stub(:fully_qualified_name => "any:old:thing", :name => "thing", :namespace => ns)
|
180
|
-
before_task = stub(:fully_qualified_name => "any:old:before_thing", :name => "before_thing", :namespace => ns)
|
181
|
-
|
182
|
-
ns.stubs(:search_task).returns(nil)
|
183
|
-
ns.expects(:search_task).with("before_thing").returns(before_task)
|
184
|
-
|
185
|
-
@config.execute_task(task)
|
186
|
-
assert_equal [before_task, task], @config.called
|
187
|
-
end
|
188
|
-
|
189
|
-
def test_execute_task_with_named_after_hook_should_call_named_after_hook
|
190
|
-
ns = stub("namespace", :default_task => nil, :name => "old", :fully_qualified_name => "any:old")
|
191
|
-
task = stub(:fully_qualified_name => "any:old:thing", :name => "thing", :namespace => ns)
|
192
|
-
after_task = stub(:fully_qualified_name => "any:old:after_thing", :name => "after_thing", :namespace => ns)
|
193
|
-
|
194
|
-
ns.stubs(:search_task).returns(nil)
|
195
|
-
ns.expects(:search_task).with("after_thing").returns(after_task)
|
196
|
-
|
197
|
-
@config.execute_task(task)
|
198
|
-
assert_equal [task, after_task], @config.called
|
199
|
-
end
|
200
|
-
|
201
|
-
def test_execute_task_with_on_hooks_should_trigger_hooks_around_task
|
202
|
-
ns = stub("namespace", :default_task => nil, :name => "old", :fully_qualified_name => "any:old")
|
203
|
-
task = stub(:fully_qualified_name => "any:old:thing", :name => "thing", :namespace => ns)
|
204
|
-
before_task = stub(:fully_qualified_name => "any:old:before_thing", :name => "before_thing", :namespace => ns)
|
205
|
-
after_task = stub(:fully_qualified_name => "any:old:after_thing", :name => "after_thing", :namespace => ns)
|
206
|
-
|
207
|
-
ns.stubs(:search_task).returns(nil)
|
208
|
-
ns.expects(:search_task).with("before_thing").returns(before_task)
|
209
|
-
ns.expects(:search_task).with("after_thing").returns(after_task)
|
210
|
-
|
211
|
-
@config.before("any:old:thing", :first_this, :then_this)
|
212
|
-
@config.after("any:old:thing", :and_then_this, :lastly_this)
|
213
|
-
|
214
|
-
[:first_this, :then_this, :and_then_this, :lastly_this].each do |t|
|
215
|
-
@config.expects(:find_and_execute_task).with(t)
|
216
|
-
end
|
217
|
-
|
218
|
-
@config.execute_task(task)
|
219
|
-
end
|
220
177
|
end
|
@@ -21,6 +21,19 @@ class ConfigurationRolesTest < Test::Unit::TestCase
|
|
21
21
|
assert @config.original_initialize_called
|
22
22
|
assert @config.roles.empty?
|
23
23
|
end
|
24
|
+
|
25
|
+
def test_roles_for_host_with_one_role
|
26
|
+
@config.role :app, "app1.capistrano.test"
|
27
|
+
@config.role :not_app, "not-app.capistrano.test"
|
28
|
+
app_server = @config.roles[:app].servers.first
|
29
|
+
assert @config.role_names_for_host(app_server)==[ :app ]
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_roles_for_host_with_multiple_roles
|
33
|
+
@config.server "www.capistrano.test", :db, :worker
|
34
|
+
db_server = @config.roles[:db].servers.first
|
35
|
+
assert_equal @config.role_names_for_host(db_server).map(&:to_s).sort, [ 'db', 'worker' ]
|
36
|
+
end
|
24
37
|
|
25
38
|
def test_role_should_allow_empty_list
|
26
39
|
@config.role :app
|
data/test/configuration_test.rb
CHANGED
@@ -74,15 +74,4 @@ class ConfigurationTest < Test::Unit::TestCase
|
|
74
74
|
assert !@config[:called_inner_first]
|
75
75
|
end
|
76
76
|
|
77
|
-
def test_hooks_for_default_task_should_be_found_if_named_after_the_namespace
|
78
|
-
@config.namespace(:outer) do
|
79
|
-
task(:default) { set :called_default, true }
|
80
|
-
task(:before_outer) { set :called_before_outer, true }
|
81
|
-
task(:after_outer) { set :called_after_outer, true }
|
82
|
-
end
|
83
|
-
@config.outer.default
|
84
|
-
assert @config[:called_before_outer]
|
85
|
-
assert @config[:called_default]
|
86
|
-
assert @config[:called_after_outer]
|
87
|
-
end
|
88
77
|
end
|
@@ -23,7 +23,7 @@ class DeployStrategyCopyTest < Test::Unit::TestCase
|
|
23
23
|
@strategy.expects(:system).with(:local_checkout)
|
24
24
|
|
25
25
|
Dir.expects(:chdir).with("/temp/dir").yields
|
26
|
-
@strategy.expects(:system).with("tar
|
26
|
+
@strategy.expects(:system).with("tar czf 1234567890.tar.gz 1234567890")
|
27
27
|
@strategy.expects(:upload).with("/temp/dir/1234567890.tar.gz", "/tmp/1234567890.tar.gz")
|
28
28
|
@strategy.expects(:run).with("cd /u/apps/test/releases && gtar xzf /tmp/1234567890.tar.gz && rm /tmp/1234567890.tar.gz")
|
29
29
|
|
@@ -45,7 +45,7 @@ class DeployStrategyCopyTest < Test::Unit::TestCase
|
|
45
45
|
@strategy.expects(:system).with(:local_checkout)
|
46
46
|
|
47
47
|
Dir.expects(:chdir).with("/temp/dir").yields
|
48
|
-
@strategy.expects(:system).with("gtar
|
48
|
+
@strategy.expects(:system).with("gtar czf 1234567890.tar.gz 1234567890")
|
49
49
|
@strategy.expects(:upload).with("/temp/dir/1234567890.tar.gz", "/tmp/1234567890.tar.gz")
|
50
50
|
@strategy.expects(:run).with("cd /u/apps/test/releases && tar xzf /tmp/1234567890.tar.gz && rm /tmp/1234567890.tar.gz")
|
51
51
|
|
@@ -109,7 +109,7 @@ class DeployStrategyCopyTest < Test::Unit::TestCase
|
|
109
109
|
@source.expects(:checkout).with("154", "/temp/dir/1234567890").returns(:local_checkout)
|
110
110
|
|
111
111
|
@strategy.expects(:system).with(:local_checkout)
|
112
|
-
@strategy.expects(:system).with("zip -
|
112
|
+
@strategy.expects(:system).with("zip -qyr 1234567890.zip 1234567890")
|
113
113
|
@strategy.expects(:upload).with("/temp/dir/1234567890.zip", "/tmp/1234567890.zip")
|
114
114
|
@strategy.expects(:run).with("cd /u/apps/test/releases && unzip -q /tmp/1234567890.zip && rm /tmp/1234567890.zip")
|
115
115
|
|
@@ -130,7 +130,7 @@ class DeployStrategyCopyTest < Test::Unit::TestCase
|
|
130
130
|
@source.expects(:checkout).with("154", "/temp/dir/1234567890").returns(:local_checkout)
|
131
131
|
|
132
132
|
@strategy.expects(:system).with(:local_checkout)
|
133
|
-
@strategy.expects(:system).with("tar
|
133
|
+
@strategy.expects(:system).with("tar cjf 1234567890.tar.bz2 1234567890")
|
134
134
|
@strategy.expects(:upload).with("/temp/dir/1234567890.tar.bz2", "/tmp/1234567890.tar.bz2")
|
135
135
|
@strategy.expects(:run).with("cd /u/apps/test/releases && tar xjf /tmp/1234567890.tar.bz2 && rm /tmp/1234567890.tar.bz2")
|
136
136
|
|
@@ -161,7 +161,7 @@ class DeployStrategyCopyTest < Test::Unit::TestCase
|
|
161
161
|
@source.expects(:checkout).with("154", "/other/path/1234567890").returns(:local_checkout)
|
162
162
|
|
163
163
|
@strategy.expects(:system).with(:local_checkout)
|
164
|
-
@strategy.expects(:system).with("tar
|
164
|
+
@strategy.expects(:system).with("tar czf 1234567890.tar.gz 1234567890")
|
165
165
|
@strategy.expects(:upload).with("/other/path/1234567890.tar.gz", "/tmp/1234567890.tar.gz")
|
166
166
|
@strategy.expects(:run).with("cd /u/apps/test/releases && tar xzf /tmp/1234567890.tar.gz && rm /tmp/1234567890.tar.gz")
|
167
167
|
|
@@ -182,7 +182,7 @@ class DeployStrategyCopyTest < Test::Unit::TestCase
|
|
182
182
|
@source.expects(:checkout).returns(:local_checkout)
|
183
183
|
|
184
184
|
@strategy.expects(:system).with(:local_checkout)
|
185
|
-
@strategy.expects(:system).with("tar
|
185
|
+
@strategy.expects(:system).with("tar czf 1234567890.tar.gz 1234567890")
|
186
186
|
@strategy.expects(:upload).with("/temp/dir/1234567890.tar.gz", "/somewhere/else/1234567890.tar.gz")
|
187
187
|
@strategy.expects(:run).with("cd /u/apps/test/releases && tar xzf /somewhere/else/1234567890.tar.gz && rm /somewhere/else/1234567890.tar.gz")
|
188
188
|
|
@@ -288,6 +288,20 @@ class DeployStrategyCopyTest < Test::Unit::TestCase
|
|
288
288
|
@strategy.deploy!
|
289
289
|
end
|
290
290
|
|
291
|
+
def test_with_build_script_should_run_script
|
292
|
+
@config[:build_script] = "mkdir bin"
|
293
|
+
|
294
|
+
Dir.expects(:tmpdir).returns("/temp/dir")
|
295
|
+
@source.expects(:checkout).with("154", "/temp/dir/1234567890").returns(:local_checkout)
|
296
|
+
@strategy.expects(:system).with(:local_checkout)
|
297
|
+
|
298
|
+
Dir.expects(:chdir).with("/temp/dir/1234567890").yields
|
299
|
+
@strategy.expects(:system).with("mkdir bin")
|
300
|
+
|
301
|
+
prepare_standard_compress_and_copy!
|
302
|
+
@strategy.deploy!
|
303
|
+
end
|
304
|
+
|
291
305
|
private
|
292
306
|
|
293
307
|
def prepare_directory_tree!(cache, exclude=false)
|
@@ -307,7 +321,7 @@ class DeployStrategyCopyTest < Test::Unit::TestCase
|
|
307
321
|
|
308
322
|
def prepare_standard_compress_and_copy!
|
309
323
|
Dir.expects(:chdir).with("/temp/dir").yields
|
310
|
-
@strategy.expects(:system).with("tar
|
324
|
+
@strategy.expects(:system).with("tar czf 1234567890.tar.gz 1234567890")
|
311
325
|
@strategy.expects(:upload).with("/temp/dir/1234567890.tar.gz", "/tmp/1234567890.tar.gz")
|
312
326
|
@strategy.expects(:run).with("cd /u/apps/test/releases && tar xzf /tmp/1234567890.tar.gz && rm /tmp/1234567890.tar.gz")
|
313
327
|
|
@@ -25,16 +25,17 @@ class TaskDefinitionTest < Test::Unit::TestCase
|
|
25
25
|
assert_equal "default", task.fully_qualified_name
|
26
26
|
end
|
27
27
|
|
28
|
-
def
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
def test_name_should_change_task_name
|
29
|
+
task = new_task(:foo)
|
30
|
+
task.name = :bar
|
31
|
+
|
32
|
+
assert_equal :bar, task.name
|
32
33
|
end
|
33
34
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
def test_raise_an_exception_when_task_names_can_not_be_converted
|
36
|
+
task = new_task('valid task name')
|
37
|
+
|
38
|
+
assert_raises(ArgumentError) { task.name = ['invalid task name'] }
|
38
39
|
end
|
39
40
|
|
40
41
|
def test_fqn_in_namespace_when_default_should_be_namespace_fqn
|
@@ -113,4 +114,4 @@ class TaskDefinitionTest < Test::Unit::TestCase
|
|
113
114
|
task = new_task(:testing, @namespace, :desc => "Take file.txt and copy it. Then do something else.")
|
114
115
|
assert_equal "Take file.txt and copy it.", task.brief_description
|
115
116
|
end
|
116
|
-
end
|
117
|
+
end
|
data/test/transfer_test.rb
CHANGED
@@ -133,6 +133,14 @@ class TransferTest < Test::Unit::TestCase
|
|
133
133
|
transfer.process!
|
134
134
|
end
|
135
135
|
|
136
|
+
def test_uploading_a_non_existing_file_should_raise_an_understandable_error
|
137
|
+
s = session('app1')
|
138
|
+
error = Capistrano::Processable::SessionAssociation.on(ArgumentError.new('expected a file to upload'), s)
|
139
|
+
transfer = Capistrano::Transfer.new(:up, "from", "to", [], :via => :scp)
|
140
|
+
transfer.expects(:process_iteration).raises(error)
|
141
|
+
assert_raise(ArgumentError, 'expected a file to upload') { transfer.process! }
|
142
|
+
end
|
143
|
+
|
136
144
|
private
|
137
145
|
|
138
146
|
class ExceptionWithSession < ::Exception
|
data/test/utils.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capistrano
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.11.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2012-02-22 00:00:00.000000000Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: highline
|
17
|
-
requirement: &
|
17
|
+
requirement: &70157295072440 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: '0'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *70157295072440
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: net-ssh
|
28
|
-
requirement: &
|
28
|
+
requirement: &70157295071180 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ! '>='
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: 2.0.14
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *70157295071180
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: net-sftp
|
39
|
-
requirement: &
|
39
|
+
requirement: &70157295069420 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ! '>='
|
@@ -44,10 +44,10 @@ dependencies:
|
|
44
44
|
version: 2.0.0
|
45
45
|
type: :runtime
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *70157295069420
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: net-scp
|
50
|
-
requirement: &
|
50
|
+
requirement: &70157295068700 !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
52
52
|
requirements:
|
53
53
|
- - ! '>='
|
@@ -55,10 +55,10 @@ dependencies:
|
|
55
55
|
version: 1.0.0
|
56
56
|
type: :runtime
|
57
57
|
prerelease: false
|
58
|
-
version_requirements: *
|
58
|
+
version_requirements: *70157295068700
|
59
59
|
- !ruby/object:Gem::Dependency
|
60
60
|
name: net-ssh-gateway
|
61
|
-
requirement: &
|
61
|
+
requirement: &70157295058440 !ruby/object:Gem::Requirement
|
62
62
|
none: false
|
63
63
|
requirements:
|
64
64
|
- - ! '>='
|
@@ -66,10 +66,10 @@ dependencies:
|
|
66
66
|
version: 1.1.0
|
67
67
|
type: :runtime
|
68
68
|
prerelease: false
|
69
|
-
version_requirements: *
|
69
|
+
version_requirements: *70157295058440
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: mocha
|
72
|
-
requirement: &
|
72
|
+
requirement: &70157295056280 !ruby/object:Gem::Requirement
|
73
73
|
none: false
|
74
74
|
requirements:
|
75
75
|
- - ! '>='
|
@@ -77,7 +77,7 @@ dependencies:
|
|
77
77
|
version: '0'
|
78
78
|
type: :development
|
79
79
|
prerelease: false
|
80
|
-
version_requirements: *
|
80
|
+
version_requirements: *70157295056280
|
81
81
|
description: Capistrano is a utility and framework for executing commands in parallel
|
82
82
|
on multiple remote machines, via SSH.
|
83
83
|
email:
|
@@ -91,7 +91,6 @@ extra_rdoc_files:
|
|
91
91
|
- README.mdown
|
92
92
|
files:
|
93
93
|
- .gitignore
|
94
|
-
- .rvmrc
|
95
94
|
- .travis.yml
|
96
95
|
- CHANGELOG
|
97
96
|
- Gemfile
|
@@ -113,6 +112,7 @@ files:
|
|
113
112
|
- lib/capistrano/configuration/actions/file_transfer.rb
|
114
113
|
- lib/capistrano/configuration/actions/inspect.rb
|
115
114
|
- lib/capistrano/configuration/actions/invocation.rb
|
115
|
+
- lib/capistrano/configuration/alias_task.rb
|
116
116
|
- lib/capistrano/configuration/callbacks.rb
|
117
117
|
- lib/capistrano/configuration/connections.rb
|
118
118
|
- lib/capistrano/configuration/execution.rb
|
@@ -122,8 +122,10 @@ files:
|
|
122
122
|
- lib/capistrano/configuration/servers.rb
|
123
123
|
- lib/capistrano/configuration/variables.rb
|
124
124
|
- lib/capistrano/errors.rb
|
125
|
+
- lib/capistrano/ext/multistage.rb
|
125
126
|
- lib/capistrano/ext/string.rb
|
126
127
|
- lib/capistrano/extensions.rb
|
128
|
+
- lib/capistrano/fix_rake_deprecated_dsl.rb
|
127
129
|
- lib/capistrano/logger.rb
|
128
130
|
- lib/capistrano/processable.rb
|
129
131
|
- lib/capistrano/recipes/compat.rb
|
@@ -160,7 +162,6 @@ files:
|
|
160
162
|
- lib/capistrano/task_definition.rb
|
161
163
|
- lib/capistrano/transfer.rb
|
162
164
|
- lib/capistrano/version.rb
|
163
|
-
- rvmrc.sample
|
164
165
|
- test/cli/execute_test.rb
|
165
166
|
- test/cli/help_test.rb
|
166
167
|
- test/cli/options_test.rb
|
@@ -170,6 +171,7 @@ files:
|
|
170
171
|
- test/configuration/actions/file_transfer_test.rb
|
171
172
|
- test/configuration/actions/inspect_test.rb
|
172
173
|
- test/configuration/actions/invocation_test.rb
|
174
|
+
- test/configuration/alias_task_test.rb
|
173
175
|
- test/configuration/callbacks_test.rb
|
174
176
|
- test/configuration/connections_test.rb
|
175
177
|
- test/configuration/execution_test.rb
|
@@ -224,7 +226,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
224
226
|
version: '0'
|
225
227
|
requirements: []
|
226
228
|
rubyforge_project:
|
227
|
-
rubygems_version: 1.8.
|
229
|
+
rubygems_version: 1.8.10
|
228
230
|
signing_key:
|
229
231
|
specification_version: 3
|
230
232
|
summary: Capistrano - Welcome to easy deployment with Ruby over SSH
|
@@ -238,6 +240,7 @@ test_files:
|
|
238
240
|
- test/configuration/actions/file_transfer_test.rb
|
239
241
|
- test/configuration/actions/inspect_test.rb
|
240
242
|
- test/configuration/actions/invocation_test.rb
|
243
|
+
- test/configuration/alias_task_test.rb
|
241
244
|
- test/configuration/callbacks_test.rb
|
242
245
|
- test/configuration/connections_test.rb
|
243
246
|
- test/configuration/execution_test.rb
|
data/.rvmrc
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
rvm use 1.8.7
|
data/rvmrc.sample
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
rvm use 1.8.7@capistrano-devel --create
|