capistrano 3.2.1 → 3.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +5 -3
- data/CHANGELOG.md +92 -2
- data/Gemfile +1 -5
- data/README.md +84 -3
- data/Rakefile +5 -1
- data/capistrano.gemspec +5 -1
- data/features/configuration.feature +9 -7
- data/features/deploy.feature +9 -8
- data/features/step_definitions/assertions.rb +15 -17
- data/features/step_definitions/cap_commands.rb +1 -1
- data/features/step_definitions/setup.rb +11 -7
- data/features/support/env.rb +8 -9
- data/features/support/remote_command_helpers.rb +2 -3
- data/features/support/vagrant_helpers.rb +35 -0
- data/lib/capistrano/all.rb +2 -1
- data/lib/capistrano/application.rb +52 -7
- data/lib/capistrano/configuration.rb +39 -10
- data/lib/capistrano/configuration/filter.rb +56 -0
- data/lib/capistrano/configuration/question.rb +23 -11
- data/lib/capistrano/configuration/server.rb +14 -5
- data/lib/capistrano/configuration/servers.rb +12 -29
- data/lib/capistrano/defaults.rb +11 -9
- data/lib/capistrano/deploy.rb +1 -0
- data/lib/capistrano/dsl.rb +13 -2
- data/lib/capistrano/dsl/env.rb +6 -2
- data/lib/capistrano/dsl/task_enhancements.rb +5 -3
- data/lib/capistrano/git.rb +8 -2
- data/lib/capistrano/hg.rb +7 -1
- data/lib/capistrano/svn.rb +2 -2
- data/lib/capistrano/tasks/deploy.rake +12 -10
- data/lib/capistrano/tasks/git.rake +1 -1
- data/lib/capistrano/tasks/install.rake +17 -14
- data/lib/capistrano/templates/Capfile +6 -4
- data/lib/capistrano/templates/deploy.rb.erb +5 -15
- data/lib/capistrano/upload_task.rb +9 -0
- data/lib/capistrano/version.rb +1 -1
- data/spec/integration/dsl_spec.rb +129 -10
- data/spec/lib/capistrano/application_spec.rb +24 -6
- data/spec/lib/capistrano/configuration/filter_spec.rb +105 -0
- data/spec/lib/capistrano/configuration/question_spec.rb +18 -12
- data/spec/lib/capistrano/configuration/server_spec.rb +19 -19
- data/spec/lib/capistrano/configuration/servers_spec.rb +101 -20
- data/spec/lib/capistrano/configuration_spec.rb +24 -3
- data/spec/lib/capistrano/dsl/task_enhancements_spec.rb +88 -0
- data/spec/lib/capistrano/dsl_spec.rb +2 -13
- data/spec/lib/capistrano/git_spec.rb +15 -4
- data/spec/lib/capistrano/hg_spec.rb +13 -2
- data/spec/lib/capistrano/scm_spec.rb +3 -3
- data/spec/lib/capistrano/svn_spec.rb +11 -1
- data/spec/lib/capistrano/upload_task_spec.rb +19 -0
- data/spec/lib/capistrano/version_validator_spec.rb +4 -4
- data/spec/spec_helper.rb +2 -1
- data/spec/support/Vagrantfile +1 -1
- data/spec/support/test_app.rb +2 -0
- metadata +45 -26
- data/lib/capistrano/configuration/servers/host_filter.rb +0 -82
- data/lib/capistrano/configuration/servers/role_filter.rb +0 -86
- data/spec/lib/capistrano/configuration/servers/host_filter_spec.rb +0 -84
- data/spec/lib/capistrano/configuration/servers/role_filter_spec.rb +0 -140
@@ -1,26 +1,29 @@
|
|
1
1
|
require 'set'
|
2
|
-
|
3
|
-
|
2
|
+
require 'capistrano/configuration'
|
3
|
+
require 'capistrano/configuration/filter'
|
4
|
+
|
4
5
|
module Capistrano
|
5
6
|
class Configuration
|
6
7
|
class Servers
|
7
8
|
include Enumerable
|
8
9
|
|
9
10
|
def add_host(host, properties={})
|
10
|
-
servers.add server(host).with(properties)
|
11
|
+
servers.add server(host, properties).with(properties)
|
11
12
|
end
|
12
13
|
|
13
14
|
def add_role(role, hosts, options={})
|
14
|
-
|
15
|
+
options_deepcopy = Marshal.dump(options.merge(roles: role))
|
16
|
+
Array(hosts).each { |host| add_host(host, Marshal.load(options_deepcopy)) }
|
15
17
|
end
|
16
18
|
|
17
19
|
def roles_for(names)
|
18
20
|
options = extract_options(names)
|
19
|
-
|
21
|
+
s = Filter.new(:role, names).filter(servers)
|
22
|
+
s.select { |server| server.select?(options) }
|
20
23
|
end
|
21
24
|
|
22
25
|
def fetch_primary(role)
|
23
|
-
hosts =
|
26
|
+
hosts = roles_for([role])
|
24
27
|
hosts.find(&:primary) || hosts.first
|
25
28
|
end
|
26
29
|
|
@@ -30,29 +33,9 @@ module Capistrano
|
|
30
33
|
|
31
34
|
private
|
32
35
|
|
33
|
-
def server(host)
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
def fetch(role)
|
38
|
-
servers.find_all { |server| server.has_role? role}
|
39
|
-
end
|
40
|
-
|
41
|
-
def fetch_roles(required, options)
|
42
|
-
filter_roles = RoleFilter.for(required, available_roles)
|
43
|
-
HostFilter.for(select(servers_with_roles(filter_roles), options))
|
44
|
-
end
|
45
|
-
|
46
|
-
def servers_with_roles(roles)
|
47
|
-
roles.flat_map { |role| fetch role }.uniq
|
48
|
-
end
|
49
|
-
|
50
|
-
def select(servers, options)
|
51
|
-
servers.select { |server| server.select?(options) }
|
52
|
-
end
|
53
|
-
|
54
|
-
def available_roles
|
55
|
-
servers.flat_map { |server| server.roles_array }.uniq
|
36
|
+
def server(host, properties)
|
37
|
+
new_host = Server[host].with(properties)
|
38
|
+
servers.find { |server| server.matches? new_host } || new_host
|
56
39
|
end
|
57
40
|
|
58
41
|
def servers
|
data/lib/capistrano/defaults.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
set_if_empty :scm, :git
|
2
|
+
set_if_empty :branch, :master
|
3
|
+
set_if_empty :deploy_to, -> { "/var/www/#{fetch(:application)}" }
|
4
|
+
set_if_empty :tmp_dir, "/tmp"
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
set_if_empty :default_env, {}
|
7
|
+
set_if_empty :keep_releases, 5
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
set_if_empty :format, :pretty
|
10
|
+
set_if_empty :log_level, :debug
|
11
11
|
|
12
|
-
|
12
|
+
set_if_empty :pty, false
|
13
|
+
|
14
|
+
set_if_empty :local_user, -> { Etc.getlogin }
|
data/lib/capistrano/deploy.rb
CHANGED
data/lib/capistrano/dsl.rb
CHANGED
@@ -3,6 +3,7 @@ require 'capistrano/dsl/task_enhancements'
|
|
3
3
|
require 'capistrano/dsl/paths'
|
4
4
|
require 'capistrano/dsl/stages'
|
5
5
|
require 'capistrano/dsl/env'
|
6
|
+
require 'capistrano/configuration/filter'
|
6
7
|
|
7
8
|
module Capistrano
|
8
9
|
module DSL
|
@@ -33,7 +34,7 @@ module Capistrano
|
|
33
34
|
branch: fetch(:branch),
|
34
35
|
user: local_user,
|
35
36
|
sha: fetch(:current_revision),
|
36
|
-
release: release_timestamp)
|
37
|
+
release: fetch(:release_timestamp))
|
37
38
|
)
|
38
39
|
end
|
39
40
|
|
@@ -42,12 +43,22 @@ module Capistrano
|
|
42
43
|
end
|
43
44
|
|
44
45
|
def local_user
|
45
|
-
|
46
|
+
fetch(:local_user)
|
46
47
|
end
|
47
48
|
|
48
49
|
def lock(locked_version)
|
49
50
|
VersionValidator.new(locked_version).verify
|
50
51
|
end
|
52
|
+
|
53
|
+
def on(hosts, options={}, &block)
|
54
|
+
subset = Configuration.env.filter hosts
|
55
|
+
SSHKit::Coordinator.new(subset).each(options, &block)
|
56
|
+
end
|
57
|
+
|
58
|
+
def run_locally(&block)
|
59
|
+
SSHKit::Backend::Local.new(&block).run
|
60
|
+
end
|
61
|
+
|
51
62
|
end
|
52
63
|
end
|
53
64
|
self.extend Capistrano::DSL
|
data/lib/capistrano/dsl/env.rb
CHANGED
@@ -23,12 +23,16 @@ module Capistrano
|
|
23
23
|
env.set(key, value)
|
24
24
|
end
|
25
25
|
|
26
|
+
def set_if_empty(key, value)
|
27
|
+
env.set_if_empty(key, value)
|
28
|
+
end
|
29
|
+
|
26
30
|
def delete(key)
|
27
31
|
env.delete(key)
|
28
32
|
end
|
29
33
|
|
30
|
-
def ask(key, value)
|
31
|
-
env.ask(key, value)
|
34
|
+
def ask(key, value, options={})
|
35
|
+
env.ask(key, value, options)
|
32
36
|
end
|
33
37
|
|
34
38
|
def role(name, servers, options={})
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'capistrano/upload_task'
|
2
|
+
|
1
3
|
module Capistrano
|
2
4
|
module TaskEnhancements
|
3
5
|
def before(task, prerequisite, *args, &block)
|
@@ -19,12 +21,12 @@ module Capistrano
|
|
19
21
|
end
|
20
22
|
|
21
23
|
def define_remote_file_task(task, target_roles)
|
22
|
-
|
24
|
+
Capistrano::UploadTask.define_task(task) do |t|
|
23
25
|
prerequisite_file = t.prerequisites.first
|
24
26
|
file = shared_path.join(t.name)
|
25
27
|
|
26
28
|
on roles(target_roles) do
|
27
|
-
unless test "[ -f #{file} ]"
|
29
|
+
unless test "[ -f #{file.to_s.shellescape} ]"
|
28
30
|
info "Uploading #{prerequisite_file} to #{file}"
|
29
31
|
upload! File.open(prerequisite_file), file
|
30
32
|
end
|
@@ -51,7 +53,7 @@ module Capistrano
|
|
51
53
|
end
|
52
54
|
|
53
55
|
def exit_deploy_because_of_exception(ex)
|
54
|
-
warn t(:deploy_failed, ex: ex.
|
56
|
+
warn t(:deploy_failed, ex: ex.message)
|
55
57
|
invoke 'deploy:failed'
|
56
58
|
exit(false)
|
57
59
|
end
|
data/lib/capistrano/git.rb
CHANGED
@@ -18,7 +18,7 @@ class Capistrano::Git < Capistrano::SCM
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def check
|
21
|
-
|
21
|
+
git :'ls-remote -h', repo_url
|
22
22
|
end
|
23
23
|
|
24
24
|
def clone
|
@@ -30,7 +30,13 @@ class Capistrano::Git < Capistrano::SCM
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def release
|
33
|
-
|
33
|
+
if tree = fetch(:repo_tree)
|
34
|
+
tree = tree.slice %r#^/?(.*?)/?$#, 1
|
35
|
+
components = tree.split('/').size
|
36
|
+
git :archive, fetch(:branch), tree, "| tar -x --strip-components #{components} -f - -C", release_path
|
37
|
+
else
|
38
|
+
git :archive, fetch(:branch), '| tar -x -f - -C', release_path
|
39
|
+
end
|
34
40
|
end
|
35
41
|
|
36
42
|
def fetch_revision
|
data/lib/capistrano/hg.rb
CHANGED
@@ -27,7 +27,13 @@ class Capistrano::Hg < Capistrano::SCM
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def release
|
30
|
-
|
30
|
+
if tree = fetch(:repo_tree)
|
31
|
+
tree = tree.slice %r#^/?(.*?)/?$#, 1
|
32
|
+
components = tree.split('/').size
|
33
|
+
hg "archive --type tgz -p . -I", tree, "--rev", fetch(:branch), "| tar -x --strip-components #{components} -f - -C", release_path
|
34
|
+
else
|
35
|
+
hg "archive", release_path, "--rev", fetch(:branch)
|
36
|
+
end
|
31
37
|
end
|
32
38
|
|
33
39
|
def fetch_revision
|
data/lib/capistrano/svn.rb
CHANGED
@@ -28,11 +28,11 @@ class Capistrano::Svn < Capistrano::SCM
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def release
|
31
|
-
svn :export, '.', release_path
|
31
|
+
svn :export, '--force', '.', release_path
|
32
32
|
end
|
33
33
|
|
34
34
|
def fetch_revision
|
35
|
-
context.capture(:
|
35
|
+
context.capture(:svnversion, repo_path)
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
namespace :deploy do
|
2
2
|
|
3
3
|
task :starting do
|
4
|
+
invoke 'metrics:collect'
|
4
5
|
invoke 'deploy:check'
|
5
6
|
invoke 'deploy:set_previous_revision'
|
6
7
|
end
|
@@ -44,7 +45,7 @@ namespace :deploy do
|
|
44
45
|
desc 'Check shared and release directories exist'
|
45
46
|
task :directories do
|
46
47
|
on release_roles :all do
|
47
|
-
execute :mkdir, '-
|
48
|
+
execute :mkdir, '-p', shared_path, releases_path
|
48
49
|
end
|
49
50
|
end
|
50
51
|
|
@@ -52,7 +53,7 @@ namespace :deploy do
|
|
52
53
|
task :linked_dirs do
|
53
54
|
next unless any? :linked_dirs
|
54
55
|
on release_roles :all do
|
55
|
-
execute :mkdir, '-
|
56
|
+
execute :mkdir, '-p', linked_dirs(shared_path)
|
56
57
|
end
|
57
58
|
end
|
58
59
|
|
@@ -60,7 +61,7 @@ namespace :deploy do
|
|
60
61
|
task :make_linked_dirs do
|
61
62
|
next unless any? :linked_files
|
62
63
|
on release_roles :all do |host|
|
63
|
-
execute :mkdir, '-
|
64
|
+
execute :mkdir, '-p', linked_file_dirs(shared_path)
|
64
65
|
end
|
65
66
|
end
|
66
67
|
|
@@ -82,8 +83,9 @@ namespace :deploy do
|
|
82
83
|
desc 'Symlink release to current'
|
83
84
|
task :release do
|
84
85
|
on release_roles :all do
|
85
|
-
|
86
|
-
execute :ln, '-s', release_path,
|
86
|
+
tmp_current_path = release_path.parent.join(current_path.basename)
|
87
|
+
execute :ln, '-s', release_path, tmp_current_path
|
88
|
+
execute :mv, tmp_current_path, current_path.parent
|
87
89
|
end
|
88
90
|
end
|
89
91
|
|
@@ -97,7 +99,7 @@ namespace :deploy do
|
|
97
99
|
task :linked_dirs do
|
98
100
|
next unless any? :linked_dirs
|
99
101
|
on release_roles :all do
|
100
|
-
execute :mkdir, '-
|
102
|
+
execute :mkdir, '-p', linked_dir_parents(release_path)
|
101
103
|
|
102
104
|
fetch(:linked_dirs).each do |dir|
|
103
105
|
target = release_path.join(dir)
|
@@ -116,7 +118,7 @@ namespace :deploy do
|
|
116
118
|
task :linked_files do
|
117
119
|
next unless any? :linked_files
|
118
120
|
on release_roles :all do
|
119
|
-
execute :mkdir, '-
|
121
|
+
execute :mkdir, '-p', linked_file_dirs(release_path)
|
120
122
|
|
121
123
|
fetch(:linked_files).each do |file|
|
122
124
|
target = release_path.join(file)
|
@@ -135,7 +137,7 @@ namespace :deploy do
|
|
135
137
|
desc 'Clean up old releases'
|
136
138
|
task :cleanup do
|
137
139
|
on release_roles :all do |host|
|
138
|
-
releases = capture(:ls, '-
|
140
|
+
releases = capture(:ls, '-xtr', releases_path).split
|
139
141
|
if releases.count >= fetch(:keep_releases)
|
140
142
|
info t(:keeping_releases, host: host.to_s, keep_releases: fetch(:keep_releases), releases: releases.count)
|
141
143
|
directories = (releases - releases.last(fetch(:keep_releases)))
|
@@ -154,7 +156,7 @@ namespace :deploy do
|
|
154
156
|
desc 'Remove and archive rolled-back release.'
|
155
157
|
task :cleanup_rollback do
|
156
158
|
on release_roles(:all) do
|
157
|
-
last_release = capture(:ls, '-
|
159
|
+
last_release = capture(:ls, '-xt', releases_path).split.first
|
158
160
|
last_release_path = releases_path.join(last_release)
|
159
161
|
if test "[ `readlink #{current_path}` != #{last_release_path} ]"
|
160
162
|
execute :tar, '-czf',
|
@@ -189,7 +191,7 @@ namespace :deploy do
|
|
189
191
|
|
190
192
|
task :rollback_release_path do
|
191
193
|
on release_roles(:all) do
|
192
|
-
releases = capture(:ls, '-
|
194
|
+
releases = capture(:ls, '-xt', releases_path).split
|
193
195
|
if releases.count < 2
|
194
196
|
error t(:cannot_rollback)
|
195
197
|
exit 1
|
@@ -14,25 +14,28 @@ task :install do
|
|
14
14
|
|
15
15
|
mkdir_p deploy_dir
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
f.write(ERB.new(template).result(binding))
|
29
|
-
puts I18n.t(:written_file, scope: :capistrano, file: file)
|
17
|
+
entries = [{template: deploy_rb, file: config_dir.join('deploy.rb')}]
|
18
|
+
entries += envs.split(',').map { |stage| {template: stage_rb, file: deploy_dir.join("#{stage}.rb")} }
|
19
|
+
|
20
|
+
entries.each do |entry|
|
21
|
+
if File.exists?(entry[:file])
|
22
|
+
warn "[skip] #{entry[:file]} already exists"
|
23
|
+
else
|
24
|
+
File.open(entry[:file], 'w+') do |f|
|
25
|
+
f.write(ERB.new(File.read(entry[:template])).result(binding))
|
26
|
+
puts I18n.t(:written_file, scope: :capistrano, file: entry[:file])
|
27
|
+
end
|
30
28
|
end
|
31
29
|
end
|
32
30
|
|
33
31
|
mkdir_p tasks_dir
|
34
32
|
|
35
|
-
|
33
|
+
if File.exists?('Capfile')
|
34
|
+
warn "[skip] Capfile already exists"
|
35
|
+
else
|
36
|
+
FileUtils.cp(capfile, 'Capfile')
|
37
|
+
puts I18n.t(:written_file, scope: :capistrano, file: 'Capfile')
|
38
|
+
end
|
36
39
|
|
37
40
|
|
38
41
|
puts I18n.t :capified, scope: :capistrano
|
@@ -1,10 +1,10 @@
|
|
1
|
-
# Load DSL and
|
1
|
+
# Load DSL and set up stages
|
2
2
|
require 'capistrano/setup'
|
3
3
|
|
4
|
-
#
|
4
|
+
# Include default deployment tasks
|
5
5
|
require 'capistrano/deploy'
|
6
6
|
|
7
|
-
#
|
7
|
+
# Include tasks from other gems included in your Gemfile
|
8
8
|
#
|
9
9
|
# For documentation on these, see for example:
|
10
10
|
#
|
@@ -13,6 +13,7 @@ require 'capistrano/deploy'
|
|
13
13
|
# https://github.com/capistrano/chruby
|
14
14
|
# https://github.com/capistrano/bundler
|
15
15
|
# https://github.com/capistrano/rails
|
16
|
+
# https://github.com/capistrano/passenger
|
16
17
|
#
|
17
18
|
# require 'capistrano/rvm'
|
18
19
|
# require 'capistrano/rbenv'
|
@@ -20,6 +21,7 @@ require 'capistrano/deploy'
|
|
20
21
|
# require 'capistrano/bundler'
|
21
22
|
# require 'capistrano/rails/assets'
|
22
23
|
# require 'capistrano/rails/migrations'
|
24
|
+
# require 'capistrano/passenger'
|
23
25
|
|
24
|
-
#
|
26
|
+
# Load custom tasks from `lib/capistrano/tasks' if you have any defined
|
25
27
|
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# config valid only for Capistrano
|
1
|
+
# config valid only for current version of Capistrano
|
2
2
|
lock '<%= Capistrano::VERSION %>'
|
3
3
|
|
4
4
|
set :application, 'my_app_name'
|
@@ -7,8 +7,8 @@ set :repo_url, 'git@example.com:me/my_repo.git'
|
|
7
7
|
# Default branch is :master
|
8
8
|
# ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }.call
|
9
9
|
|
10
|
-
# Default deploy_to directory is /var/www/
|
11
|
-
# set :deploy_to, '/var/www/
|
10
|
+
# Default deploy_to directory is /var/www/my_app_name
|
11
|
+
# set :deploy_to, '/var/www/my_app_name'
|
12
12
|
|
13
13
|
# Default value for :scm is :git
|
14
14
|
# set :scm, :git
|
@@ -23,10 +23,10 @@ set :repo_url, 'git@example.com:me/my_repo.git'
|
|
23
23
|
# set :pty, true
|
24
24
|
|
25
25
|
# Default value for :linked_files is []
|
26
|
-
# set :linked_files,
|
26
|
+
# set :linked_files, fetch(:linked_files, []).push('config/database.yml')
|
27
27
|
|
28
28
|
# Default value for linked_dirs is []
|
29
|
-
# set :linked_dirs,
|
29
|
+
# set :linked_dirs, fetch(:linked_dirs, []).push('bin', 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system')
|
30
30
|
|
31
31
|
# Default value for default_env is {}
|
32
32
|
# set :default_env, { path: "/opt/ruby/bin:$PATH" }
|
@@ -36,16 +36,6 @@ set :repo_url, 'git@example.com:me/my_repo.git'
|
|
36
36
|
|
37
37
|
namespace :deploy do
|
38
38
|
|
39
|
-
desc 'Restart application'
|
40
|
-
task :restart do
|
41
|
-
on roles(:app), in: :sequence, wait: 5 do
|
42
|
-
# Your restart mechanism here, for example:
|
43
|
-
# execute :touch, release_path.join('tmp/restart.txt')
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
after :publishing, :restart
|
48
|
-
|
49
39
|
after :restart, :clear_cache do
|
50
40
|
on roles(:web), in: :groups, limit: 3, wait: 10 do
|
51
41
|
# Here we can do anything such as:
|