capistrano 2.9.0 → 2.11.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|