capistrano 3.0.0.pre14 → 3.0.0
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/CHANGELOG.md +42 -0
- data/README.md +1 -1
- data/bin/cap +1 -1
- data/capistrano.gemspec +3 -0
- data/features/deploy.feature +52 -0
- data/features/installation.feature +16 -0
- data/features/remote_file_task.feature +14 -0
- data/features/step_definitions/assertions.rb +90 -0
- data/features/step_definitions/cap_commands.rb +8 -0
- data/features/step_definitions/setup.rb +25 -0
- data/features/support/env.rb +12 -0
- data/features/support/remote_command_helpers.rb +20 -0
- data/lib/Capfile +1 -0
- data/lib/capistrano.rb +0 -14
- data/lib/capistrano/all.rb +16 -0
- data/lib/capistrano/application.rb +1 -10
- data/lib/capistrano/configuration.rb +4 -0
- data/lib/capistrano/configuration/server.rb +44 -6
- data/lib/capistrano/configuration/servers.rb +14 -51
- data/lib/capistrano/configuration/servers/role_filter.rb +86 -0
- data/lib/capistrano/defaults.rb +0 -8
- data/lib/capistrano/dsl.rb +1 -1
- data/lib/capistrano/dsl/env.rb +6 -2
- data/lib/capistrano/dsl/paths.rb +7 -4
- data/lib/capistrano/dsl/task_enhancements.rb +38 -0
- data/lib/capistrano/hg.rb +1 -0
- data/lib/capistrano/i18n.rb +1 -1
- data/lib/capistrano/setup.rb +7 -3
- data/lib/capistrano/tasks/deploy.rake +39 -9
- data/lib/capistrano/tasks/framework.rake +0 -2
- data/lib/capistrano/tasks/git.rake +3 -6
- data/lib/capistrano/tasks/hg.rake +39 -0
- data/lib/capistrano/templates/Capfile +2 -23
- data/lib/capistrano/templates/deploy.rb.erb +23 -0
- data/lib/capistrano/templates/stage.rb.erb +1 -1
- data/lib/capistrano/version.rb +1 -1
- data/spec/integration/dsl_spec.rb +71 -0
- data/spec/lib/capistrano/configuration/server_spec.rb +69 -0
- data/spec/lib/capistrano/configuration/servers/role_filter_spec.rb +140 -0
- data/spec/lib/capistrano/configuration/servers_spec.rb +46 -9
- data/spec/lib/capistrano/configuration_spec.rb +11 -0
- data/spec/spec_helper.rb +1 -2
- data/spec/support/.gitignore +1 -0
- data/spec/support/Vagrantfile +13 -0
- data/spec/support/tasks/database.cap +11 -0
- data/spec/support/test_app.rb +55 -6
- metadata +74 -16
- data/lib/capistrano/bundler.rb +0 -1
- data/lib/capistrano/tasks/bundler.rake +0 -13
- data/spec/integration/deploy_finalize_spec.rb +0 -34
- data/spec/integration/deploy_finished_spec.rb +0 -36
- data/spec/integration/deploy_started_spec.rb +0 -74
- data/spec/integration/deploy_update_spec.rb +0 -45
- data/spec/integration/installation_spec.rb +0 -76
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'set'
|
2
|
+
require_relative 'servers/role_filter'
|
2
3
|
module Capistrano
|
3
4
|
class Configuration
|
4
5
|
class Servers
|
@@ -40,17 +41,21 @@ module Capistrano
|
|
40
41
|
servers.find_all { |server| server.has_role? role}
|
41
42
|
end
|
42
43
|
|
43
|
-
def fetch_roles(
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
44
|
+
def fetch_roles(required, options)
|
45
|
+
filter_roles = RoleFilter.for(required, available_roles)
|
46
|
+
select(servers_with_roles(filter_roles), options)
|
47
|
+
end
|
48
|
+
|
49
|
+
def servers_with_roles(roles)
|
50
|
+
roles.flat_map { |role| fetch role }.uniq
|
51
|
+
end
|
52
|
+
|
53
|
+
def select(servers, options)
|
54
|
+
servers.select { |server| server.select?(options) }
|
50
55
|
end
|
51
56
|
|
52
|
-
def
|
53
|
-
|
57
|
+
def available_roles
|
58
|
+
servers.flat_map { |server| server.roles_array }.uniq
|
54
59
|
end
|
55
60
|
|
56
61
|
def servers
|
@@ -60,48 +65,6 @@ module Capistrano
|
|
60
65
|
def extract_options(array)
|
61
66
|
array.last.is_a?(::Hash) ? array.pop : {}
|
62
67
|
end
|
63
|
-
|
64
|
-
class Filter
|
65
|
-
def initialize(servers, options)
|
66
|
-
@servers, @options = servers, options
|
67
|
-
end
|
68
|
-
|
69
|
-
def filtered_servers
|
70
|
-
if servers_with_filter.any?
|
71
|
-
servers_with_filter
|
72
|
-
else
|
73
|
-
fail I18n.t(:filter_removes_all_servers, scope: :capistrano, filter: key || '(no filter)' )
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
private
|
78
|
-
attr_reader :options, :servers
|
79
|
-
|
80
|
-
def servers_with_filter
|
81
|
-
@servers_with_filter ||= servers.select(&filter)
|
82
|
-
end
|
83
|
-
|
84
|
-
def key
|
85
|
-
options[:filter] || options[:select]
|
86
|
-
end
|
87
|
-
|
88
|
-
def filter_option
|
89
|
-
key || all
|
90
|
-
end
|
91
|
-
|
92
|
-
def filter
|
93
|
-
if filter_option.respond_to?(:call)
|
94
|
-
filter_option
|
95
|
-
else
|
96
|
-
lambda { |server| server.fetch(filter_option) }
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def all
|
101
|
-
lambda { |server| :all }
|
102
|
-
end
|
103
|
-
|
104
|
-
end
|
105
68
|
end
|
106
69
|
end
|
107
70
|
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Capistrano
|
2
|
+
class Configuration
|
3
|
+
class Servers
|
4
|
+
class RoleFilter
|
5
|
+
|
6
|
+
def initialize(required, available)
|
7
|
+
@required, @available = required, available
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.for(required, available)
|
11
|
+
new(required, available).roles
|
12
|
+
end
|
13
|
+
|
14
|
+
def roles
|
15
|
+
if required.include?(:all)
|
16
|
+
available
|
17
|
+
else
|
18
|
+
required.select { |name| available.include? name }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def required
|
25
|
+
Array(@required).flat_map(&:to_sym)
|
26
|
+
end
|
27
|
+
|
28
|
+
def available
|
29
|
+
if role_filter.any?
|
30
|
+
role_filter
|
31
|
+
else
|
32
|
+
@available
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def role_filter
|
37
|
+
env_filter | configuration_filter
|
38
|
+
end
|
39
|
+
|
40
|
+
def configuration_filter
|
41
|
+
ConfigurationFilter.new.roles
|
42
|
+
end
|
43
|
+
|
44
|
+
def env_filter
|
45
|
+
EnvFilter.new.roles
|
46
|
+
end
|
47
|
+
|
48
|
+
class ConfigurationFilter
|
49
|
+
|
50
|
+
def roles
|
51
|
+
if filter
|
52
|
+
Array(filter.fetch(:roles, [])).map(&:to_sym)
|
53
|
+
else
|
54
|
+
[]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def config
|
59
|
+
Configuration.env
|
60
|
+
end
|
61
|
+
|
62
|
+
def filter
|
63
|
+
config.fetch(:filter) || config.fetch(:select)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
class EnvFilter
|
69
|
+
|
70
|
+
def roles
|
71
|
+
if filter
|
72
|
+
filter.split(',').map(&:to_sym)
|
73
|
+
else
|
74
|
+
[]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def filter
|
79
|
+
ENV['ROLES']
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/capistrano/defaults.rb
CHANGED
data/lib/capistrano/dsl.rb
CHANGED
data/lib/capistrano/dsl/env.rb
CHANGED
@@ -6,8 +6,8 @@ module Capistrano
|
|
6
6
|
env.configure_backend
|
7
7
|
end
|
8
8
|
|
9
|
-
def fetch(key, default=nil)
|
10
|
-
env.fetch(key, default)
|
9
|
+
def fetch(key, default=nil, &block)
|
10
|
+
env.fetch(key, default, &block)
|
11
11
|
end
|
12
12
|
|
13
13
|
def any?(key)
|
@@ -23,6 +23,10 @@ module Capistrano
|
|
23
23
|
env.set(key, value)
|
24
24
|
end
|
25
25
|
|
26
|
+
def delete(key)
|
27
|
+
env.delete(key)
|
28
|
+
end
|
29
|
+
|
26
30
|
def ask(key, value)
|
27
31
|
env.ask(key, value)
|
28
32
|
end
|
data/lib/capistrano/dsl/paths.rb
CHANGED
@@ -20,7 +20,11 @@ module Capistrano
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def release_path
|
23
|
-
|
23
|
+
fetch(:release_path, current_path)
|
24
|
+
end
|
25
|
+
|
26
|
+
def set_release_path(timestamp=now)
|
27
|
+
set(:release_path, releases_path.join(timestamp))
|
24
28
|
end
|
25
29
|
|
26
30
|
def repo_url
|
@@ -52,9 +56,8 @@ module Capistrano
|
|
52
56
|
deploy_path.join('revisions.log')
|
53
57
|
end
|
54
58
|
|
55
|
-
def
|
56
|
-
|
57
|
-
env.timestamp.strftime("%Y%m%d%H%M%S"))
|
59
|
+
def now
|
60
|
+
env.timestamp.strftime("%Y%m%d%H%M%S")
|
58
61
|
end
|
59
62
|
|
60
63
|
def asset_timestamp
|
@@ -11,5 +11,43 @@ module Capistrano
|
|
11
11
|
invoke(post_task)
|
12
12
|
end
|
13
13
|
end
|
14
|
+
|
15
|
+
def remote_file(task)
|
16
|
+
target_roles = task.delete(:roles) { :all }
|
17
|
+
define_remote_file_task(task, target_roles)
|
18
|
+
end
|
19
|
+
|
20
|
+
def define_remote_file_task(task, target_roles)
|
21
|
+
Rake::Task.define_task(task) do |t|
|
22
|
+
prerequisite_file = t.prerequisites.first
|
23
|
+
file = shared_path.join(t.name)
|
24
|
+
|
25
|
+
on roles(target_roles) do
|
26
|
+
unless test "[ -f #{file} ]"
|
27
|
+
info "Uploading #{prerequisite_file} to #{file}"
|
28
|
+
upload! File.open(prerequisite_file), file
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def ensure_stage
|
36
|
+
Rake::Task.define_task(:ensure_stage) do
|
37
|
+
unless stage_set?
|
38
|
+
puts t(:stage_not_set)
|
39
|
+
exit 1
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def tasks_without_stage_dependency
|
45
|
+
stages + default_tasks
|
46
|
+
end
|
47
|
+
|
48
|
+
def default_tasks
|
49
|
+
%w{install}
|
50
|
+
end
|
51
|
+
|
14
52
|
end
|
15
53
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
load File.expand_path("../tasks/hg.rake", __FILE__)
|
data/lib/capistrano/i18n.rb
CHANGED
@@ -14,11 +14,11 @@ en = {
|
|
14
14
|
written_file: 'create %{file}',
|
15
15
|
question: 'Please enter %{key}: |%{default_value}|',
|
16
16
|
keeping_releases: 'Keeping %{keep_releases} of %{releases} deployed releases on %{host}',
|
17
|
+
no_old_releases: 'No old releases (keeping newest %{keep_releases}) on %{host}',
|
17
18
|
linked_file_does_not_exist: 'linked file %{file} does not exist on %{host}',
|
18
19
|
mirror_exists: "The repository mirror is at %{at}",
|
19
20
|
revision_log_message: 'Branch %{branch} deployed as release %{release} by %{user}',
|
20
21
|
rollback_log_message: '%{user} rolled back to release %{release}',
|
21
|
-
filter_removes_all_servers: 'Your filter `%{filter}` would remove all matching servers',
|
22
22
|
console: {
|
23
23
|
welcome: 'capistrano console - enter command to execute on %{stage}',
|
24
24
|
bye: 'bye'
|
data/lib/capistrano/setup.rb
CHANGED
@@ -1,10 +1,15 @@
|
|
1
1
|
include Capistrano::DSL
|
2
2
|
|
3
|
-
load
|
3
|
+
namespace :load do
|
4
|
+
task :defaults do
|
5
|
+
load 'capistrano/defaults.rb'
|
6
|
+
end
|
7
|
+
end
|
4
8
|
|
5
9
|
stages.each do |stage|
|
6
10
|
Rake::Task.define_task(stage) do
|
7
|
-
load
|
11
|
+
invoke 'load:defaults'
|
12
|
+
load 'config/deploy.rb'
|
8
13
|
load "config/deploy/#{stage}.rb"
|
9
14
|
load "capistrano/#{fetch(:scm)}.rb"
|
10
15
|
set(:stage, stage.to_sym)
|
@@ -13,5 +18,4 @@ stages.each do |stage|
|
|
13
18
|
end
|
14
19
|
end
|
15
20
|
|
16
|
-
|
17
21
|
require 'capistrano/dotfile'
|
@@ -4,7 +4,7 @@ namespace :deploy do
|
|
4
4
|
invoke 'deploy:check'
|
5
5
|
end
|
6
6
|
|
7
|
-
task :updating do
|
7
|
+
task :updating => :new_release_path do
|
8
8
|
invoke "#{scm}:create_release"
|
9
9
|
invoke 'deploy:symlink:shared'
|
10
10
|
end
|
@@ -35,6 +35,7 @@ namespace :deploy do
|
|
35
35
|
invoke "#{scm}:check"
|
36
36
|
invoke 'deploy:check:directories'
|
37
37
|
invoke 'deploy:check:linked_dirs'
|
38
|
+
invoke 'deploy:check:make_linked_dirs'
|
38
39
|
invoke 'deploy:check:linked_files'
|
39
40
|
end
|
40
41
|
|
@@ -53,12 +54,19 @@ namespace :deploy do
|
|
53
54
|
execute :mkdir, '-pv', linked_dirs(shared_path)
|
54
55
|
end
|
55
56
|
end
|
57
|
+
|
58
|
+
desc 'Check directories of files to be linked exist in shared'
|
59
|
+
task :make_linked_dirs do
|
60
|
+
next unless any? :linked_files
|
61
|
+
on roles :app do |host|
|
62
|
+
execute :mkdir, '-pv', linked_file_dirs(shared_path)
|
63
|
+
end
|
64
|
+
end
|
56
65
|
|
57
66
|
desc 'Check files to be linked exist in shared'
|
58
67
|
task :linked_files do
|
59
68
|
next unless any? :linked_files
|
60
69
|
on roles :app do |host|
|
61
|
-
execute :mkdir, '-pv', linked_file_dirs(shared_path)
|
62
70
|
linked_files(shared_path).each do |file|
|
63
71
|
unless test "[ -f #{file} ]"
|
64
72
|
error t(:linked_file_does_not_exist, file: file, host: host)
|
@@ -129,9 +137,15 @@ namespace :deploy do
|
|
129
137
|
releases = capture(:ls, '-x', releases_path).split
|
130
138
|
if releases.count >= fetch(:keep_releases)
|
131
139
|
info t(:keeping_releases, host: host.to_s, keep_releases: fetch(:keep_releases), releases: releases.count)
|
132
|
-
directories = (releases - releases.last(fetch(:keep_releases)))
|
133
|
-
|
134
|
-
|
140
|
+
directories = (releases - releases.last(fetch(:keep_releases)))
|
141
|
+
if directories.any?
|
142
|
+
directories_str = directories.map do |release|
|
143
|
+
releases_path.join(release)
|
144
|
+
end.join(" ")
|
145
|
+
execute :rm, '-rf', directories_str
|
146
|
+
else
|
147
|
+
info t(:no_old_releases, host: host.to_s, keep_releases: fetch(:keep_releases))
|
148
|
+
end
|
135
149
|
end
|
136
150
|
end
|
137
151
|
end
|
@@ -162,13 +176,29 @@ namespace :deploy do
|
|
162
176
|
end
|
163
177
|
|
164
178
|
desc 'Revert to previous release timestamp'
|
165
|
-
task :revert_release do
|
179
|
+
task :revert_release => :rollback_release_path do
|
166
180
|
on roles(:all) do
|
167
|
-
last_release = capture(:ls, '-xr', releases_path).split[1]
|
168
|
-
set(:rollback_release_timestamp, last_release)
|
169
|
-
set(:branch, last_release)
|
170
181
|
set(:revision_log_message, rollback_log_message)
|
171
182
|
end
|
172
183
|
end
|
173
184
|
|
185
|
+
task :new_release_path do
|
186
|
+
set_release_path
|
187
|
+
end
|
188
|
+
|
189
|
+
task :last_release_path do
|
190
|
+
on roles(:all) do
|
191
|
+
last_release = capture(:ls, '-xr', releases_path).split[1]
|
192
|
+
set_release_path(last_release)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
task :rollback_release_path do
|
197
|
+
on roles(:all) do
|
198
|
+
last_release = capture(:ls, '-xr', releases_path).split[1]
|
199
|
+
set_release_path(last_release)
|
200
|
+
set(:rollback_timestamp, last_release)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
174
204
|
end
|
@@ -18,7 +18,7 @@ namespace :git do
|
|
18
18
|
fetch(:branch)
|
19
19
|
on roles :all do
|
20
20
|
with git_environmental_variables do
|
21
|
-
|
21
|
+
exit 1 unless test :git, :'ls-remote', repo_url
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -52,11 +52,8 @@ namespace :git do
|
|
52
52
|
on roles :all do
|
53
53
|
with git_environmental_variables do
|
54
54
|
within repo_path do
|
55
|
-
execute :
|
56
|
-
|
57
|
-
'--recursive', \
|
58
|
-
'--no-hardlinks', \
|
59
|
-
repo_path, release_path
|
55
|
+
execute :mkdir, '-p', release_path
|
56
|
+
execute :git, :archive, fetch(:branch), '| tar -x -C', release_path
|
60
57
|
end
|
61
58
|
end
|
62
59
|
end
|