capistrano 3.4.0 → 3.17.1

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 (138) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +129 -0
  3. data/.github/issue_template.md +19 -0
  4. data/.github/pull_request_template.md +22 -0
  5. data/.github/release-drafter.yml +17 -0
  6. data/.github/workflows/push.yml +12 -0
  7. data/.gitignore +8 -5
  8. data/.rubocop.yml +62 -0
  9. data/CHANGELOG.md +1 -307
  10. data/CONTRIBUTING.md +63 -93
  11. data/DEVELOPMENT.md +127 -0
  12. data/Dangerfile +1 -0
  13. data/Gemfile +40 -3
  14. data/LICENSE.txt +1 -1
  15. data/README.md +127 -44
  16. data/RELEASING.md +17 -0
  17. data/Rakefile +13 -2
  18. data/UPGRADING-3.7.md +86 -0
  19. data/bin/cap +1 -1
  20. data/capistrano.gemspec +21 -24
  21. data/features/deploy.feature +35 -1
  22. data/features/doctor.feature +11 -0
  23. data/features/installation.feature +8 -3
  24. data/features/stage_failure.feature +9 -0
  25. data/features/step_definitions/assertions.rb +51 -18
  26. data/features/step_definitions/cap_commands.rb +9 -0
  27. data/features/step_definitions/setup.rb +53 -9
  28. data/features/subdirectory.feature +9 -0
  29. data/features/support/env.rb +5 -5
  30. data/features/support/remote_command_helpers.rb +12 -6
  31. data/features/support/vagrant_helpers.rb +17 -11
  32. data/lib/Capfile +1 -1
  33. data/lib/capistrano/all.rb +10 -10
  34. data/lib/capistrano/application.rb +47 -34
  35. data/lib/capistrano/configuration/empty_filter.rb +9 -0
  36. data/lib/capistrano/configuration/filter.rb +17 -47
  37. data/lib/capistrano/configuration/host_filter.rb +29 -0
  38. data/lib/capistrano/configuration/null_filter.rb +9 -0
  39. data/lib/capistrano/configuration/plugin_installer.rb +51 -0
  40. data/lib/capistrano/configuration/question.rb +31 -9
  41. data/lib/capistrano/configuration/role_filter.rb +29 -0
  42. data/lib/capistrano/configuration/scm_resolver.rb +149 -0
  43. data/lib/capistrano/configuration/server.rb +29 -23
  44. data/lib/capistrano/configuration/servers.rb +21 -14
  45. data/lib/capistrano/configuration/validated_variables.rb +110 -0
  46. data/lib/capistrano/configuration/variables.rb +112 -0
  47. data/lib/capistrano/configuration.rb +91 -44
  48. data/lib/capistrano/defaults.rb +26 -4
  49. data/lib/capistrano/deploy.rb +1 -1
  50. data/lib/capistrano/doctor/environment_doctor.rb +19 -0
  51. data/lib/capistrano/doctor/gems_doctor.rb +45 -0
  52. data/lib/capistrano/doctor/output_helpers.rb +79 -0
  53. data/lib/capistrano/doctor/servers_doctor.rb +105 -0
  54. data/lib/capistrano/doctor/variables_doctor.rb +74 -0
  55. data/lib/capistrano/doctor.rb +6 -0
  56. data/lib/capistrano/dotfile.rb +1 -2
  57. data/lib/capistrano/dsl/env.rb +9 -47
  58. data/lib/capistrano/dsl/paths.rb +11 -25
  59. data/lib/capistrano/dsl/stages.rb +14 -2
  60. data/lib/capistrano/dsl/task_enhancements.rb +7 -12
  61. data/lib/capistrano/dsl.rb +47 -16
  62. data/lib/capistrano/framework.rb +1 -1
  63. data/lib/capistrano/i18n.rb +32 -24
  64. data/lib/capistrano/immutable_task.rb +30 -0
  65. data/lib/capistrano/install.rb +1 -1
  66. data/lib/capistrano/plugin.rb +95 -0
  67. data/lib/capistrano/proc_helpers.rb +13 -0
  68. data/lib/capistrano/scm/git.rb +100 -0
  69. data/lib/capistrano/scm/hg.rb +55 -0
  70. data/lib/capistrano/scm/plugin.rb +13 -0
  71. data/lib/capistrano/scm/svn.rb +56 -0
  72. data/lib/capistrano/scm/tasks/git.rake +73 -0
  73. data/lib/capistrano/scm/tasks/hg.rake +53 -0
  74. data/lib/capistrano/scm/tasks/svn.rake +53 -0
  75. data/lib/capistrano/scm.rb +7 -20
  76. data/lib/capistrano/setup.rb +20 -6
  77. data/lib/capistrano/tasks/console.rake +4 -8
  78. data/lib/capistrano/tasks/deploy.rake +105 -73
  79. data/lib/capistrano/tasks/doctor.rake +24 -0
  80. data/lib/capistrano/tasks/framework.rake +13 -14
  81. data/lib/capistrano/tasks/install.rake +14 -15
  82. data/lib/capistrano/templates/Capfile +21 -10
  83. data/lib/capistrano/templates/deploy.rb.erb +17 -26
  84. data/lib/capistrano/templates/stage.rb.erb +9 -9
  85. data/lib/capistrano/upload_task.rb +1 -1
  86. data/lib/capistrano/version.rb +1 -1
  87. data/lib/capistrano/version_validator.rb +5 -10
  88. data/spec/integration/dsl_spec.rb +289 -240
  89. data/spec/integration_spec_helper.rb +3 -5
  90. data/spec/lib/capistrano/application_spec.rb +23 -39
  91. data/spec/lib/capistrano/configuration/empty_filter_spec.rb +17 -0
  92. data/spec/lib/capistrano/configuration/filter_spec.rb +83 -85
  93. data/spec/lib/capistrano/configuration/host_filter_spec.rb +71 -0
  94. data/spec/lib/capistrano/configuration/null_filter_spec.rb +17 -0
  95. data/spec/lib/capistrano/configuration/plugin_installer_spec.rb +98 -0
  96. data/spec/lib/capistrano/configuration/question_spec.rb +58 -26
  97. data/spec/lib/capistrano/configuration/role_filter_spec.rb +80 -0
  98. data/spec/lib/capistrano/configuration/scm_resolver_spec.rb +55 -0
  99. data/spec/lib/capistrano/configuration/server_spec.rb +106 -113
  100. data/spec/lib/capistrano/configuration/servers_spec.rb +129 -145
  101. data/spec/lib/capistrano/configuration_spec.rb +224 -63
  102. data/spec/lib/capistrano/doctor/environment_doctor_spec.rb +44 -0
  103. data/spec/lib/capistrano/doctor/gems_doctor_spec.rb +67 -0
  104. data/spec/lib/capistrano/doctor/output_helpers_spec.rb +47 -0
  105. data/spec/lib/capistrano/doctor/servers_doctor_spec.rb +86 -0
  106. data/spec/lib/capistrano/doctor/variables_doctor_spec.rb +89 -0
  107. data/spec/lib/capistrano/dsl/paths_spec.rb +97 -59
  108. data/spec/lib/capistrano/dsl/task_enhancements_spec.rb +57 -37
  109. data/spec/lib/capistrano/dsl_spec.rb +84 -11
  110. data/spec/lib/capistrano/immutable_task_spec.rb +31 -0
  111. data/spec/lib/capistrano/plugin_spec.rb +84 -0
  112. data/spec/lib/capistrano/scm/git_spec.rb +184 -0
  113. data/spec/lib/capistrano/scm/hg_spec.rb +109 -0
  114. data/spec/lib/capistrano/scm/svn_spec.rb +137 -0
  115. data/spec/lib/capistrano/scm_spec.rb +7 -8
  116. data/spec/lib/capistrano/upload_task_spec.rb +7 -7
  117. data/spec/lib/capistrano/version_validator_spec.rb +61 -46
  118. data/spec/lib/capistrano_spec.rb +2 -3
  119. data/spec/spec_helper.rb +21 -8
  120. data/spec/support/Vagrantfile +9 -10
  121. data/spec/support/tasks/database.rake +3 -3
  122. data/spec/support/tasks/fail.rake +4 -3
  123. data/spec/support/tasks/failed.rake +2 -2
  124. data/spec/support/tasks/plugin.rake +6 -0
  125. data/spec/support/tasks/root.rake +4 -4
  126. data/spec/support/test_app.rb +64 -39
  127. metadata +100 -55
  128. data/.travis.yml +0 -13
  129. data/features/remote_file_task.feature +0 -14
  130. data/lib/capistrano/git.rb +0 -46
  131. data/lib/capistrano/hg.rb +0 -43
  132. data/lib/capistrano/svn.rb +0 -38
  133. data/lib/capistrano/tasks/git.rake +0 -81
  134. data/lib/capistrano/tasks/hg.rake +0 -52
  135. data/lib/capistrano/tasks/svn.rake +0 -52
  136. data/spec/lib/capistrano/git_spec.rb +0 -81
  137. data/spec/lib/capistrano/hg_spec.rb +0 -81
  138. data/spec/lib/capistrano/svn_spec.rb +0 -79
@@ -1,5 +1,4 @@
1
1
  module Capistrano
2
-
3
2
  # Base class for SCM strategy providers.
4
3
  #
5
4
  # @abstract
@@ -25,7 +24,7 @@ module Capistrano
25
24
 
26
25
  # Call test in context
27
26
  def test!(*args)
28
- context.test *args
27
+ context.test(*args)
29
28
  end
30
29
 
31
30
  # The repository URL according to the context
@@ -59,9 +58,7 @@ module Capistrano
59
58
  # @return [Boolean]
60
59
  #
61
60
  def test
62
- raise NotImplementedError.new(
63
- "Your SCM strategy module should provide a #test method"
64
- )
61
+ raise NotImplementedError, "Your SCM strategy module should provide a #test method"
65
62
  end
66
63
 
67
64
  # @abstract
@@ -72,9 +69,7 @@ module Capistrano
72
69
  # @return [Boolean]
73
70
  #
74
71
  def check
75
- raise NotImplementedError.new(
76
- "Your SCM strategy module should provide a #check method"
77
- )
72
+ raise NotImplementedError, "Your SCM strategy module should provide a #check method"
78
73
  end
79
74
 
80
75
  # @abstract
@@ -84,9 +79,7 @@ module Capistrano
84
79
  # @return void
85
80
  #
86
81
  def clone
87
- raise NotImplementedError.new(
88
- "Your SCM strategy module should provide a #clone method"
89
- )
82
+ raise NotImplementedError, "Your SCM strategy module should provide a #clone method"
90
83
  end
91
84
 
92
85
  # @abstract
@@ -96,9 +89,7 @@ module Capistrano
96
89
  # @return void
97
90
  #
98
91
  def update
99
- raise NotImplementedError.new(
100
- "Your SCM strategy module should provide a #update method"
101
- )
92
+ raise NotImplementedError, "Your SCM strategy module should provide a #update method"
102
93
  end
103
94
 
104
95
  # @abstract
@@ -108,9 +99,7 @@ module Capistrano
108
99
  # @return void
109
100
  #
110
101
  def release
111
- raise NotImplementedError.new(
112
- "Your SCM strategy module should provide a #release method"
113
- )
102
+ raise NotImplementedError, "Your SCM strategy module should provide a #release method"
114
103
  end
115
104
 
116
105
  # @abstract
@@ -120,9 +109,7 @@ module Capistrano
120
109
  # @return void
121
110
  #
122
111
  def fetch_revision
123
- raise NotImplementedError.new(
124
- "Your SCM strategy module should provide a #fetch_revision method"
125
- )
112
+ raise NotImplementedError, "Your SCM strategy module should provide a #fetch_revision method"
126
113
  end
127
114
  end
128
115
  end
@@ -1,22 +1,36 @@
1
+ require "capistrano/doctor"
2
+ require "capistrano/immutable_task"
1
3
  include Capistrano::DSL
2
4
 
3
5
  namespace :load do
4
6
  task :defaults do
5
- load 'capistrano/defaults.rb'
7
+ load "capistrano/defaults.rb"
6
8
  end
7
9
  end
8
10
 
11
+ require "airbrussh/capistrano"
12
+ # We don't need to show the "using Airbrussh" banner announcement since
13
+ # Airbrussh is now the built-in formatter. Also enable command output by
14
+ # default; hiding the output might be confusing to users new to Capistrano.
15
+ Airbrussh.configure do |airbrussh|
16
+ airbrussh.banner = false
17
+ airbrussh.command_output = true
18
+ end
19
+
9
20
  stages.each do |stage|
10
21
  Rake::Task.define_task(stage) do
11
22
  set(:stage, stage.to_sym)
12
23
 
13
- invoke 'load:defaults'
14
- load deploy_config_path
15
- load stage_config_path.join("#{stage}.rb")
16
- load "capistrano/#{fetch(:scm)}.rb"
24
+ invoke "load:defaults"
25
+ Rake.application["load:defaults"].extend(Capistrano::ImmutableTask)
26
+ env.variables.untrusted! do
27
+ load deploy_config_path
28
+ load stage_config_path.join("#{stage}.rb")
29
+ end
30
+ configure_scm
17
31
  I18n.locale = fetch(:locale, :en)
18
32
  configure_backend
19
33
  end
20
34
  end
21
35
 
22
- require 'capistrano/dotfile'
36
+ require "capistrano/dotfile"
@@ -1,20 +1,16 @@
1
- desc 'Execute remote commands'
1
+ desc "Execute remote commands"
2
2
  task :console do
3
3
  stage = fetch(:stage)
4
- puts I18n.t('console.welcome', scope: :capistrano, stage: stage)
4
+ puts I18n.t("console.welcome", scope: :capistrano, stage: stage)
5
5
  loop do
6
6
  print "#{stage}> "
7
7
 
8
- if input = $stdin.gets
9
- command = input.chomp
10
- else
11
- command = 'exit'
12
- end
8
+ command = (input = $stdin.gets) ? input.chomp : "exit"
13
9
 
14
10
  next if command.empty?
15
11
 
16
12
  if %w{quit exit q}.include? command
17
- puts t('console.bye')
13
+ puts t("console.bye")
18
14
  break
19
15
  else
20
16
  begin
@@ -1,70 +1,88 @@
1
1
  namespace :deploy do
2
-
3
2
  task :starting do
4
- invoke 'deploy:check'
5
- invoke 'deploy:set_previous_revision'
3
+ invoke "deploy:print_config_variables" if fetch(:print_config_variables, false)
4
+ invoke "deploy:check"
5
+ invoke "deploy:set_previous_revision"
6
+ end
7
+
8
+ task :print_config_variables do
9
+ puts
10
+ puts "------- Printing current config variables -------"
11
+ env.keys.each do |config_variable_key|
12
+ if is_question?(config_variable_key)
13
+ puts "#{config_variable_key.inspect} => Question (awaits user input on next fetch(#{config_variable_key.inspect}))"
14
+ else
15
+ puts "#{config_variable_key.inspect} => #{fetch(config_variable_key).inspect}"
16
+ end
17
+ end
18
+
19
+ puts
20
+ puts "------- Printing current config variables of SSHKit mechanism -------"
21
+ puts env.backend.config.inspect
22
+ # puts env.backend.config.backend.config.ssh_options.inspect
23
+ # puts env.backend.config.command_map.defaults.inspect
24
+
25
+ puts
6
26
  end
7
27
 
8
- task :updating => :new_release_path do
9
- invoke "#{scm}:create_release"
28
+ task updating: :new_release_path do
10
29
  invoke "deploy:set_current_revision"
11
- invoke 'deploy:symlink:shared'
30
+ invoke "deploy:symlink:shared"
12
31
  end
13
32
 
14
33
  task :reverting do
15
- invoke 'deploy:revert_release'
34
+ invoke "deploy:revert_release"
16
35
  end
17
36
 
18
37
  task :publishing do
19
- invoke 'deploy:symlink:release'
38
+ invoke "deploy:symlink:release"
20
39
  end
21
40
 
22
41
  task :finishing do
23
- invoke 'deploy:cleanup'
42
+ invoke "deploy:cleanup"
24
43
  end
25
44
 
26
45
  task :finishing_rollback do
27
- invoke 'deploy:cleanup_rollback'
46
+ invoke "deploy:cleanup_rollback"
28
47
  end
29
48
 
30
49
  task :finished do
31
- invoke 'deploy:log_revision'
50
+ invoke "deploy:log_revision"
32
51
  end
33
52
 
34
- desc 'Check required files and directories exist'
53
+ desc "Check required files and directories exist"
35
54
  task :check do
36
- invoke "#{scm}:check"
37
- invoke 'deploy:check:directories'
38
- invoke 'deploy:check:linked_dirs'
39
- invoke 'deploy:check:make_linked_dirs'
40
- invoke 'deploy:check:linked_files'
55
+ invoke "deploy:check:directories"
56
+ invoke "deploy:check:linked_dirs"
57
+ invoke "deploy:check:make_linked_dirs"
58
+ invoke "deploy:check:linked_files"
41
59
  end
42
60
 
43
61
  namespace :check do
44
- desc 'Check shared and release directories exist'
62
+ desc "Check shared and release directories exist"
45
63
  task :directories do
46
64
  on release_roles :all do
47
- execute :mkdir, '-p', shared_path, releases_path
65
+ execute :mkdir, "-p", shared_path, releases_path
48
66
  end
49
67
  end
50
68
 
51
- desc 'Check directories to be linked exist in shared'
69
+ desc "Check directories to be linked exist in shared"
52
70
  task :linked_dirs do
53
71
  next unless any? :linked_dirs
54
72
  on release_roles :all do
55
- execute :mkdir, '-p', linked_dirs(shared_path)
73
+ execute :mkdir, "-p", linked_dirs(shared_path)
56
74
  end
57
75
  end
58
76
 
59
- desc 'Check directories of files to be linked exist in shared'
77
+ desc "Check directories of files to be linked exist in shared"
60
78
  task :make_linked_dirs do
61
79
  next unless any? :linked_files
62
- on release_roles :all do |host|
63
- execute :mkdir, '-p', linked_file_dirs(shared_path)
80
+ on release_roles :all do |_host|
81
+ execute :mkdir, "-p", linked_file_dirs(shared_path)
64
82
  end
65
83
  end
66
84
 
67
- desc 'Check files to be linked exist in shared'
85
+ desc "Check files to be linked exist in shared"
68
86
  task :linked_files do
69
87
  next unless any? :linked_files
70
88
  on release_roles :all do |host|
@@ -79,72 +97,80 @@ namespace :deploy do
79
97
  end
80
98
 
81
99
  namespace :symlink do
82
- desc 'Symlink release to current'
100
+ desc "Symlink release to current"
83
101
  task :release do
84
102
  on release_roles :all do
85
103
  tmp_current_path = release_path.parent.join(current_path.basename)
86
- execute :ln, '-s', release_path, tmp_current_path
104
+ execute :ln, "-s", release_path, tmp_current_path
87
105
  execute :mv, tmp_current_path, current_path.parent
88
106
  end
89
107
  end
90
108
 
91
- desc 'Symlink files and directories from shared to release'
109
+ desc "Symlink files and directories from shared to release"
92
110
  task :shared do
93
- invoke 'deploy:symlink:linked_files'
94
- invoke 'deploy:symlink:linked_dirs'
111
+ invoke "deploy:symlink:linked_files"
112
+ invoke "deploy:symlink:linked_dirs"
95
113
  end
96
114
 
97
- desc 'Symlink linked directories'
115
+ desc "Symlink linked directories"
98
116
  task :linked_dirs do
99
117
  next unless any? :linked_dirs
100
118
  on release_roles :all do
101
- execute :mkdir, '-p', linked_dir_parents(release_path)
119
+ execute :mkdir, "-p", linked_dir_parents(release_path)
102
120
 
103
121
  fetch(:linked_dirs).each do |dir|
104
122
  target = release_path.join(dir)
105
123
  source = shared_path.join(dir)
106
- unless test "[ -L #{target} ]"
107
- if test "[ -d #{target} ]"
108
- execute :rm, '-rf', target
109
- end
110
- execute :ln, '-s', source, target
111
- end
124
+ next if test "[ -L #{target} ]"
125
+ execute :rm, "-rf", target if test "[ -d #{target} ]"
126
+ execute :ln, "-s", source, target
112
127
  end
113
128
  end
114
129
  end
115
130
 
116
- desc 'Symlink linked files'
131
+ desc "Symlink linked files"
117
132
  task :linked_files do
118
133
  next unless any? :linked_files
119
134
  on release_roles :all do
120
- execute :mkdir, '-p', linked_file_dirs(release_path)
135
+ execute :mkdir, "-p", linked_file_dirs(release_path)
121
136
 
122
137
  fetch(:linked_files).each do |file|
123
138
  target = release_path.join(file)
124
139
  source = shared_path.join(file)
125
- unless test "[ -L #{target} ]"
126
- if test "[ -f #{target} ]"
127
- execute :rm, target
128
- end
129
- execute :ln, '-s', source, target
130
- end
140
+ next if test "[ -L #{target} ]"
141
+ execute :rm, target if test "[ -f #{target} ]"
142
+ execute :ln, "-s", source, target
131
143
  end
132
144
  end
133
145
  end
134
146
  end
135
147
 
136
- desc 'Clean up old releases'
148
+ desc "Clean up old releases"
137
149
  task :cleanup do
138
150
  on release_roles :all do |host|
139
- releases = capture(:ls, '-xtr', releases_path).split
140
- if releases.count >= fetch(:keep_releases)
141
- info t(:keeping_releases, host: host.to_s, keep_releases: fetch(:keep_releases), releases: releases.count)
142
- directories = (releases - releases.last(fetch(:keep_releases)))
151
+ releases = capture(:ls, "-x", releases_path).split
152
+ valid, invalid = releases.partition { |e| /^\d{14}$/ =~ e }
153
+
154
+ warn t(:skip_cleanup, host: host.to_s) if invalid.any?
155
+
156
+ if valid.count >= fetch(:keep_releases)
157
+ info t(:keeping_releases, host: host.to_s, keep_releases: fetch(:keep_releases), releases: valid.count)
158
+ directories = (valid - valid.last(fetch(:keep_releases))).map do |release|
159
+ releases_path.join(release).to_s
160
+ end
161
+ if test("[ -d #{current_path} ]")
162
+ current_release = capture(:readlink, current_path).to_s
163
+ if directories.include?(current_release)
164
+ warn t(:wont_delete_current_release, host: host.to_s)
165
+ directories.delete(current_release)
166
+ end
167
+ else
168
+ debug t(:no_current_release, host: host.to_s)
169
+ end
143
170
  if directories.any?
144
- directories_str = directories.map do |release|
145
- releases_path.join(release)
146
- end.join(" ")
147
- execute :rm, '-rf', directories_str
171
+ directories.each_slice(100) do |directories_batch|
172
+ execute :rm, "-rf", *directories_batch
173
+ end
148
174
  else
149
175
  info t(:no_old_releases, host: host.to_s, keep_releases: fetch(:keep_releases))
150
176
  end
@@ -152,33 +178,33 @@ namespace :deploy do
152
178
  end
153
179
  end
154
180
 
155
- desc 'Remove and archive rolled-back release.'
181
+ desc "Remove and archive rolled-back release."
156
182
  task :cleanup_rollback do
157
183
  on release_roles(:all) do
158
- last_release = capture(:ls, '-xt', releases_path).split.first
184
+ last_release = capture(:ls, "-xt", releases_path).split.first
159
185
  last_release_path = releases_path.join(last_release)
160
186
  if test "[ `readlink #{current_path}` != #{last_release_path} ]"
161
- execute :tar, '-czf',
162
- deploy_path.join("rolled-back-release-#{last_release}.tar.gz"),
163
- last_release_path
164
- execute :rm, '-rf', last_release_path
187
+ execute :tar, "-czf",
188
+ deploy_path.join("rolled-back-release-#{last_release}.tar.gz"),
189
+ last_release_path
190
+ execute :rm, "-rf", last_release_path
165
191
  else
166
- debug 'Last release is the current release, skip cleanup_rollback.'
192
+ debug "Last release is the current release, skip cleanup_rollback."
167
193
  end
168
194
  end
169
195
  end
170
196
 
171
- desc 'Log details of the deploy'
197
+ desc "Log details of the deploy"
172
198
  task :log_revision do
173
199
  on release_roles(:all) do
174
200
  within releases_path do
175
- execute %{echo "#{revision_log_message}" >> #{revision_log}}
201
+ execute :echo, %Q{"#{revision_log_message}" >> #{revision_log}}
176
202
  end
177
203
  end
178
204
  end
179
205
 
180
- desc 'Revert to previous release timestamp'
181
- task :revert_release => :rollback_release_path do
206
+ desc "Revert to previous release timestamp"
207
+ task revert_release: :rollback_release_path do
182
208
  on release_roles(:all) do
183
209
  set(:revision_log_message, rollback_log_message)
184
210
  end
@@ -190,12 +216,20 @@ namespace :deploy do
190
216
 
191
217
  task :rollback_release_path do
192
218
  on release_roles(:all) do
193
- releases = capture(:ls, '-xt', releases_path).split
219
+ releases = capture(:ls, "-xt", releases_path).split
194
220
  if releases.count < 2
195
221
  error t(:cannot_rollback)
196
222
  exit 1
197
223
  end
198
- last_release = releases[1]
224
+
225
+ rollback_release = ENV["ROLLBACK_RELEASE"]
226
+ index = rollback_release.nil? ? 1 : releases.index(rollback_release)
227
+ if index.nil?
228
+ error t(:cannot_found_rollback_release, release: rollback_release)
229
+ exit 1
230
+ end
231
+
232
+ last_release = releases[index]
199
233
  set_release_path(last_release)
200
234
  set(:rollback_timestamp, last_release)
201
235
  end
@@ -203,24 +237,22 @@ namespace :deploy do
203
237
 
204
238
  desc "Place a REVISION file with the current revision SHA in the current release path"
205
239
  task :set_current_revision do
206
- invoke "#{scm}:set_current_revision"
207
240
  on release_roles(:all) do
208
241
  within release_path do
209
- execute :echo, "\"#{fetch(:current_revision)}\" >> REVISION"
242
+ execute :echo, "\"#{fetch(:current_revision)}\" > REVISION"
210
243
  end
211
244
  end
212
245
  end
213
246
 
214
247
  task :set_previous_revision do
215
248
  on release_roles(:all) do
216
- target = release_path.join('REVISION')
249
+ target = release_path.join("REVISION")
217
250
  if test "[ -f #{target} ]"
218
- set(:previous_revision, capture(:cat, target, '2>/dev/null'))
251
+ set(:previous_revision, capture(:cat, target, "2>/dev/null"))
219
252
  end
220
253
  end
221
254
  end
222
255
 
223
256
  task :restart
224
257
  task :failed
225
-
226
258
  end
@@ -0,0 +1,24 @@
1
+ desc "Display a Capistrano troubleshooting report (all doctor: tasks)"
2
+ task doctor: ["doctor:environment", "doctor:gems", "doctor:variables", "doctor:servers"]
3
+
4
+ namespace :doctor do
5
+ desc "Display Ruby environment details"
6
+ task :environment do
7
+ Capistrano::Doctor::EnvironmentDoctor.new.call
8
+ end
9
+
10
+ desc "Display Capistrano gem versions"
11
+ task :gems do
12
+ Capistrano::Doctor::GemsDoctor.new.call
13
+ end
14
+
15
+ desc "Display the values of all Capistrano variables"
16
+ task :variables do
17
+ Capistrano::Doctor::VariablesDoctor.new.call
18
+ end
19
+
20
+ desc "Display the effective servers configuration"
21
+ task :servers do
22
+ Capistrano::Doctor::ServersDoctor.new.call
23
+ end
24
+ end
@@ -1,50 +1,49 @@
1
1
  namespace :deploy do
2
-
3
- desc 'Start a deployment, make sure server(s) ready.'
2
+ desc "Start a deployment, make sure server(s) ready."
4
3
  task :starting do
5
4
  end
6
5
 
7
- desc 'Started'
6
+ desc "Started"
8
7
  task :started do
9
8
  end
10
9
 
11
- desc 'Update server(s) by setting up a new release.'
10
+ desc "Update server(s) by setting up a new release."
12
11
  task :updating do
13
12
  end
14
13
 
15
- desc 'Updated'
14
+ desc "Updated"
16
15
  task :updated do
17
16
  end
18
17
 
19
- desc 'Revert server(s) to previous release.'
18
+ desc "Revert server(s) to previous release."
20
19
  task :reverting do
21
20
  end
22
21
 
23
- desc 'Reverted'
22
+ desc "Reverted"
24
23
  task :reverted do
25
24
  end
26
25
 
27
- desc 'Publish the release.'
26
+ desc "Publish the release."
28
27
  task :publishing do
29
28
  end
30
29
 
31
- desc 'Published'
30
+ desc "Published"
32
31
  task :published do
33
32
  end
34
33
 
35
- desc 'Finish the deployment, clean up server(s).'
34
+ desc "Finish the deployment, clean up server(s)."
36
35
  task :finishing do
37
36
  end
38
37
 
39
- desc 'Finish the rollback, clean up server(s).'
38
+ desc "Finish the rollback, clean up server(s)."
40
39
  task :finishing_rollback do
41
40
  end
42
41
 
43
- desc 'Finished'
42
+ desc "Finished"
44
43
  task :finished do
45
44
  end
46
45
 
47
- desc 'Rollback to previous release.'
46
+ desc "Rollback to previous release."
48
47
  task :rollback do
49
48
  %w{ starting started
50
49
  reverting reverted
@@ -55,7 +54,7 @@ namespace :deploy do
55
54
  end
56
55
  end
57
56
 
58
- desc 'Deploy a new release.'
57
+ desc "Deploy a new release."
59
58
  task :deploy do
60
59
  set(:deploying, true)
61
60
  %w{ starting started
@@ -1,12 +1,12 @@
1
- require 'erb'
2
- require 'pathname'
3
- desc 'Install Capistrano, cap install STAGES=staging,production'
1
+ require "erb"
2
+ require "pathname"
3
+ desc "Install Capistrano, cap install STAGES=staging,production"
4
4
  task :install do
5
- envs = ENV['STAGES'] || 'staging,production'
5
+ envs = ENV["STAGES"] || "staging,production"
6
6
 
7
- tasks_dir = Pathname.new('lib/capistrano/tasks')
8
- config_dir = Pathname.new('config')
9
- deploy_dir = config_dir.join('deploy')
7
+ tasks_dir = Pathname.new("lib/capistrano/tasks")
8
+ config_dir = Pathname.new("config")
9
+ deploy_dir = config_dir.join("deploy")
10
10
 
11
11
  deploy_rb = File.expand_path("../../templates/deploy.rb.erb", __FILE__)
12
12
  stage_rb = File.expand_path("../../templates/stage.rb.erb", __FILE__)
@@ -14,14 +14,14 @@ task :install do
14
14
 
15
15
  mkdir_p deploy_dir
16
16
 
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")} }
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
19
 
20
20
  entries.each do |entry|
21
- if File.exists?(entry[:file])
21
+ if File.exist?(entry[:file])
22
22
  warn "[skip] #{entry[:file]} already exists"
23
23
  else
24
- File.open(entry[:file], 'w+') do |f|
24
+ File.open(entry[:file], "w+") do |f|
25
25
  f.write(ERB.new(File.read(entry[:template])).result(binding))
26
26
  puts I18n.t(:written_file, scope: :capistrano, file: entry[:file])
27
27
  end
@@ -30,13 +30,12 @@ task :install do
30
30
 
31
31
  mkdir_p tasks_dir
32
32
 
33
- if File.exists?('Capfile')
33
+ if File.exist?("Capfile")
34
34
  warn "[skip] Capfile already exists"
35
35
  else
36
- FileUtils.cp(capfile, 'Capfile')
37
- puts I18n.t(:written_file, scope: :capistrano, file: 'Capfile')
36
+ FileUtils.cp(capfile, "Capfile")
37
+ puts I18n.t(:written_file, scope: :capistrano, file: "Capfile")
38
38
  end
39
39
 
40
-
41
40
  puts I18n.t :capified, scope: :capistrano
42
41
  end
@@ -1,8 +1,19 @@
1
1
  # Load DSL and set up stages
2
- require 'capistrano/setup'
2
+ require "capistrano/setup"
3
3
 
4
4
  # Include default deployment tasks
5
- require 'capistrano/deploy'
5
+ require "capistrano/deploy"
6
+
7
+ # Load the SCM plugin appropriate to your project:
8
+ #
9
+ # require "capistrano/scm/hg"
10
+ # install_plugin Capistrano::SCM::Hg
11
+ # or
12
+ # require "capistrano/scm/svn"
13
+ # install_plugin Capistrano::SCM::Svn
14
+ # or
15
+ require "capistrano/scm/git"
16
+ install_plugin Capistrano::SCM::Git
6
17
 
7
18
  # Include tasks from other gems included in your Gemfile
8
19
  #
@@ -15,13 +26,13 @@ require 'capistrano/deploy'
15
26
  # https://github.com/capistrano/rails
16
27
  # https://github.com/capistrano/passenger
17
28
  #
18
- # require 'capistrano/rvm'
19
- # require 'capistrano/rbenv'
20
- # require 'capistrano/chruby'
21
- # require 'capistrano/bundler'
22
- # require 'capistrano/rails/assets'
23
- # require 'capistrano/rails/migrations'
24
- # require 'capistrano/passenger'
29
+ # require "capistrano/rvm"
30
+ # require "capistrano/rbenv"
31
+ # require "capistrano/chruby"
32
+ # require "capistrano/bundler"
33
+ # require "capistrano/rails/assets"
34
+ # require "capistrano/rails/migrations"
35
+ # require "capistrano/passenger"
25
36
 
26
37
  # Load custom tasks from `lib/capistrano/tasks` if you have any defined
27
- Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
38
+ Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }