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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -0
  3. data/README.md +1 -1
  4. data/bin/cap +1 -1
  5. data/capistrano.gemspec +3 -0
  6. data/features/deploy.feature +52 -0
  7. data/features/installation.feature +16 -0
  8. data/features/remote_file_task.feature +14 -0
  9. data/features/step_definitions/assertions.rb +90 -0
  10. data/features/step_definitions/cap_commands.rb +8 -0
  11. data/features/step_definitions/setup.rb +25 -0
  12. data/features/support/env.rb +12 -0
  13. data/features/support/remote_command_helpers.rb +20 -0
  14. data/lib/Capfile +1 -0
  15. data/lib/capistrano.rb +0 -14
  16. data/lib/capistrano/all.rb +16 -0
  17. data/lib/capistrano/application.rb +1 -10
  18. data/lib/capistrano/configuration.rb +4 -0
  19. data/lib/capistrano/configuration/server.rb +44 -6
  20. data/lib/capistrano/configuration/servers.rb +14 -51
  21. data/lib/capistrano/configuration/servers/role_filter.rb +86 -0
  22. data/lib/capistrano/defaults.rb +0 -8
  23. data/lib/capistrano/dsl.rb +1 -1
  24. data/lib/capistrano/dsl/env.rb +6 -2
  25. data/lib/capistrano/dsl/paths.rb +7 -4
  26. data/lib/capistrano/dsl/task_enhancements.rb +38 -0
  27. data/lib/capistrano/hg.rb +1 -0
  28. data/lib/capistrano/i18n.rb +1 -1
  29. data/lib/capistrano/setup.rb +7 -3
  30. data/lib/capistrano/tasks/deploy.rake +39 -9
  31. data/lib/capistrano/tasks/framework.rake +0 -2
  32. data/lib/capistrano/tasks/git.rake +3 -6
  33. data/lib/capistrano/tasks/hg.rake +39 -0
  34. data/lib/capistrano/templates/Capfile +2 -23
  35. data/lib/capistrano/templates/deploy.rb.erb +23 -0
  36. data/lib/capistrano/templates/stage.rb.erb +1 -1
  37. data/lib/capistrano/version.rb +1 -1
  38. data/spec/integration/dsl_spec.rb +71 -0
  39. data/spec/lib/capistrano/configuration/server_spec.rb +69 -0
  40. data/spec/lib/capistrano/configuration/servers/role_filter_spec.rb +140 -0
  41. data/spec/lib/capistrano/configuration/servers_spec.rb +46 -9
  42. data/spec/lib/capistrano/configuration_spec.rb +11 -0
  43. data/spec/spec_helper.rb +1 -2
  44. data/spec/support/.gitignore +1 -0
  45. data/spec/support/Vagrantfile +13 -0
  46. data/spec/support/tasks/database.cap +11 -0
  47. data/spec/support/test_app.rb +55 -6
  48. metadata +74 -16
  49. data/lib/capistrano/bundler.rb +0 -1
  50. data/lib/capistrano/tasks/bundler.rake +0 -13
  51. data/spec/integration/deploy_finalize_spec.rb +0 -34
  52. data/spec/integration/deploy_finished_spec.rb +0 -36
  53. data/spec/integration/deploy_started_spec.rb +0 -74
  54. data/spec/integration/deploy_update_spec.rb +0 -45
  55. 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(names, options)
44
- if Array(names).flatten.map(&:to_sym).include?(:all)
45
- filter(servers, options)
46
- else
47
- role_servers = Array(names).flat_map { |name| fetch name }.uniq
48
- filter(role_servers, options)
49
- end
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 filter(servers, options)
53
- Filter.new(servers, options).filtered_servers
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
@@ -11,11 +11,3 @@ set :log_level, :debug
11
11
 
12
12
  set :pty, true
13
13
 
14
- namespace :deploy do
15
- task :ensure_stage do
16
- unless stage_set?
17
- puts t(:stage_not_set)
18
- exit 1
19
- end
20
- end
21
- end
@@ -32,7 +32,7 @@ module Capistrano
32
32
  end
33
33
 
34
34
  def rollback_log_message
35
- t(:rollback_log_message, user: local_user, release: release_timestamp)
35
+ t(:rollback_log_message, user: local_user, release: fetch(:rollback_timestamp))
36
36
  end
37
37
 
38
38
  def local_user
@@ -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
@@ -20,7 +20,11 @@ module Capistrano
20
20
  end
21
21
 
22
22
  def release_path
23
- releases_path.join(release_timestamp)
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 release_timestamp
56
- fetch(:rollback_release_timestamp,
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__)
@@ -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'
@@ -1,10 +1,15 @@
1
1
  include Capistrano::DSL
2
2
 
3
- load 'capistrano/defaults.rb'
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 "config/deploy.rb"
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))).map { |release|
133
- releases_path.join(release) }.join(" ")
134
- execute :rm, '-rf', directories
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
@@ -44,8 +44,6 @@ namespace :deploy do
44
44
  task :finished do
45
45
  end
46
46
 
47
- before :starting, :ensure_stage
48
-
49
47
  desc 'Rollback to previous release.'
50
48
  task :rollback do
51
49
  %w{ starting started
@@ -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
- execute :git, :'ls-remote', repo_url
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 :git, :clone, '--branch', fetch(:branch), \
56
- '--depth 1', \
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