capistrano 2.8.0 → 3.19.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 (239) hide show
  1. checksums.yaml +7 -0
  2. data/.docker/Dockerfile +7 -0
  3. data/.docker/ssh_key_rsa +49 -0
  4. data/.docker/ssh_key_rsa.pub +1 -0
  5. data/.docker/ubuntu_setup.sh +23 -0
  6. data/.github/issue_template.md +19 -0
  7. data/.github/pull_request_template.md +22 -0
  8. data/.github/release-drafter.yml +25 -0
  9. data/.github/workflows/ci.yml +80 -0
  10. data/.github/workflows/release-drafter.yml +18 -0
  11. data/.gitignore +23 -8
  12. data/.rubocop.yml +62 -0
  13. data/CHANGELOG.md +1 -0
  14. data/CONTRIBUTING.md +63 -0
  15. data/DEVELOPMENT.md +112 -0
  16. data/Gemfile +42 -9
  17. data/LICENSE.txt +21 -0
  18. data/README.md +221 -0
  19. data/RELEASING.md +17 -0
  20. data/Rakefile +17 -8
  21. data/UPGRADING-3.7.md +86 -0
  22. data/bin/cap +2 -3
  23. data/bin/capify +7 -89
  24. data/capistrano.gemspec +29 -43
  25. data/docker-compose.yml +8 -0
  26. data/features/configuration.feature +28 -0
  27. data/features/deploy.feature +92 -0
  28. data/features/deploy_failure.feature +17 -0
  29. data/features/doctor.feature +11 -0
  30. data/features/installation.feature +21 -0
  31. data/features/sshconnect.feature +11 -0
  32. data/features/stage_failure.feature +9 -0
  33. data/features/step_definitions/assertions.rb +162 -0
  34. data/features/step_definitions/cap_commands.rb +21 -0
  35. data/features/step_definitions/setup.rb +91 -0
  36. data/features/subdirectory.feature +9 -0
  37. data/features/support/docker_gateway.rb +53 -0
  38. data/features/support/env.rb +1 -0
  39. data/features/support/remote_command_helpers.rb +29 -0
  40. data/features/support/remote_ssh_helpers.rb +33 -0
  41. data/lib/Capfile +3 -0
  42. data/lib/capistrano/all.rb +17 -0
  43. data/lib/capistrano/application.rb +153 -0
  44. data/lib/capistrano/configuration/empty_filter.rb +9 -0
  45. data/lib/capistrano/configuration/filter.rb +26 -0
  46. data/lib/capistrano/configuration/host_filter.rb +29 -0
  47. data/lib/capistrano/configuration/null_filter.rb +9 -0
  48. data/lib/capistrano/configuration/plugin_installer.rb +51 -0
  49. data/lib/capistrano/configuration/question.rb +76 -0
  50. data/lib/capistrano/configuration/role_filter.rb +29 -0
  51. data/lib/capistrano/configuration/scm_resolver.rb +149 -0
  52. data/lib/capistrano/configuration/server.rb +137 -0
  53. data/lib/capistrano/configuration/servers.rb +56 -96
  54. data/lib/capistrano/configuration/validated_variables.rb +110 -0
  55. data/lib/capistrano/configuration/variables.rb +79 -94
  56. data/lib/capistrano/configuration.rb +178 -33
  57. data/lib/capistrano/console.rb +1 -0
  58. data/lib/capistrano/defaults.rb +36 -0
  59. data/lib/capistrano/deploy.rb +3 -0
  60. data/lib/capistrano/doctor/environment_doctor.rb +19 -0
  61. data/lib/capistrano/doctor/gems_doctor.rb +45 -0
  62. data/lib/capistrano/doctor/output_helpers.rb +79 -0
  63. data/lib/capistrano/doctor/servers_doctor.rb +105 -0
  64. data/lib/capistrano/doctor/variables_doctor.rb +74 -0
  65. data/lib/capistrano/doctor.rb +6 -0
  66. data/lib/capistrano/dotfile.rb +2 -0
  67. data/lib/capistrano/dsl/env.rb +43 -0
  68. data/lib/capistrano/dsl/paths.rb +89 -0
  69. data/lib/capistrano/dsl/stages.rb +31 -0
  70. data/lib/capistrano/dsl/task_enhancements.rb +61 -0
  71. data/lib/capistrano/dsl.rb +95 -0
  72. data/lib/capistrano/framework.rb +2 -0
  73. data/lib/capistrano/i18n.rb +46 -0
  74. data/lib/capistrano/immutable_task.rb +30 -0
  75. data/lib/capistrano/install.rb +1 -0
  76. data/lib/capistrano/plugin.rb +95 -0
  77. data/lib/capistrano/proc_helpers.rb +13 -0
  78. data/lib/capistrano/scm/git.rb +105 -0
  79. data/lib/capistrano/scm/hg.rb +55 -0
  80. data/lib/capistrano/scm/plugin.rb +13 -0
  81. data/lib/capistrano/scm/svn.rb +56 -0
  82. data/lib/capistrano/scm/tasks/git.rake +84 -0
  83. data/lib/capistrano/scm/tasks/hg.rake +53 -0
  84. data/lib/capistrano/scm/tasks/svn.rake +53 -0
  85. data/lib/capistrano/scm.rb +115 -0
  86. data/lib/capistrano/setup.rb +36 -0
  87. data/lib/capistrano/tasks/console.rake +25 -0
  88. data/lib/capistrano/tasks/deploy.rake +280 -0
  89. data/lib/capistrano/tasks/doctor.rake +24 -0
  90. data/lib/capistrano/tasks/framework.rake +67 -0
  91. data/lib/capistrano/tasks/install.rake +41 -0
  92. data/lib/capistrano/templates/Capfile +38 -0
  93. data/lib/capistrano/templates/deploy.rb.erb +39 -0
  94. data/lib/capistrano/templates/stage.rb.erb +61 -0
  95. data/lib/capistrano/upload_task.rb +9 -0
  96. data/lib/capistrano/version.rb +1 -14
  97. data/lib/capistrano/version_validator.rb +32 -0
  98. data/lib/capistrano.rb +0 -3
  99. data/spec/integration/dsl_spec.rb +632 -0
  100. data/spec/integration_spec_helper.rb +5 -0
  101. data/spec/lib/capistrano/application_spec.rb +60 -0
  102. data/spec/lib/capistrano/configuration/empty_filter_spec.rb +17 -0
  103. data/spec/lib/capistrano/configuration/filter_spec.rb +109 -0
  104. data/spec/lib/capistrano/configuration/host_filter_spec.rb +71 -0
  105. data/spec/lib/capistrano/configuration/null_filter_spec.rb +17 -0
  106. data/spec/lib/capistrano/configuration/plugin_installer_spec.rb +98 -0
  107. data/spec/lib/capistrano/configuration/question_spec.rb +92 -0
  108. data/spec/lib/capistrano/configuration/role_filter_spec.rb +80 -0
  109. data/spec/lib/capistrano/configuration/scm_resolver_spec.rb +56 -0
  110. data/spec/lib/capistrano/configuration/server_spec.rb +309 -0
  111. data/spec/lib/capistrano/configuration/servers_spec.rb +331 -0
  112. data/spec/lib/capistrano/configuration_spec.rb +357 -0
  113. data/spec/lib/capistrano/doctor/environment_doctor_spec.rb +44 -0
  114. data/spec/lib/capistrano/doctor/gems_doctor_spec.rb +67 -0
  115. data/spec/lib/capistrano/doctor/output_helpers_spec.rb +47 -0
  116. data/spec/lib/capistrano/doctor/servers_doctor_spec.rb +86 -0
  117. data/spec/lib/capistrano/doctor/variables_doctor_spec.rb +89 -0
  118. data/spec/lib/capistrano/dsl/paths_spec.rb +228 -0
  119. data/spec/lib/capistrano/dsl/task_enhancements_spec.rb +108 -0
  120. data/spec/lib/capistrano/dsl_spec.rb +125 -0
  121. data/spec/lib/capistrano/immutable_task_spec.rb +31 -0
  122. data/spec/lib/capistrano/plugin_spec.rb +84 -0
  123. data/spec/lib/capistrano/scm/git_spec.rb +194 -0
  124. data/spec/lib/capistrano/scm/hg_spec.rb +109 -0
  125. data/spec/lib/capistrano/scm/svn_spec.rb +137 -0
  126. data/spec/lib/capistrano/scm_spec.rb +103 -0
  127. data/spec/lib/capistrano/upload_task_spec.rb +19 -0
  128. data/spec/lib/capistrano/version_validator_spec.rb +118 -0
  129. data/spec/lib/capistrano_spec.rb +7 -0
  130. data/spec/spec_helper.rb +29 -0
  131. data/spec/support/matchers.rb +5 -0
  132. data/spec/support/tasks/database.rake +11 -0
  133. data/spec/support/tasks/fail.rake +8 -0
  134. data/spec/support/tasks/failed.rake +5 -0
  135. data/spec/support/tasks/plugin.rake +6 -0
  136. data/spec/support/tasks/root.rake +11 -0
  137. data/spec/support/test_app.rb +205 -0
  138. metadata +234 -208
  139. data/.rvmrc +0 -1
  140. data/CHANGELOG +0 -954
  141. data/README.mdown +0 -76
  142. data/lib/capistrano/callback.rb +0 -45
  143. data/lib/capistrano/cli/execute.rb +0 -85
  144. data/lib/capistrano/cli/help.rb +0 -125
  145. data/lib/capistrano/cli/help.txt +0 -81
  146. data/lib/capistrano/cli/options.rb +0 -243
  147. data/lib/capistrano/cli/ui.rb +0 -40
  148. data/lib/capistrano/cli.rb +0 -47
  149. data/lib/capistrano/command.rb +0 -286
  150. data/lib/capistrano/configuration/actions/file_transfer.rb +0 -51
  151. data/lib/capistrano/configuration/actions/inspect.rb +0 -46
  152. data/lib/capistrano/configuration/actions/invocation.rb +0 -298
  153. data/lib/capistrano/configuration/callbacks.rb +0 -148
  154. data/lib/capistrano/configuration/connections.rb +0 -230
  155. data/lib/capistrano/configuration/execution.rb +0 -143
  156. data/lib/capistrano/configuration/loading.rb +0 -197
  157. data/lib/capistrano/configuration/namespaces.rb +0 -197
  158. data/lib/capistrano/configuration/roles.rb +0 -73
  159. data/lib/capistrano/errors.rb +0 -19
  160. data/lib/capistrano/ext/string.rb +0 -5
  161. data/lib/capistrano/extensions.rb +0 -57
  162. data/lib/capistrano/logger.rb +0 -59
  163. data/lib/capistrano/processable.rb +0 -53
  164. data/lib/capistrano/recipes/compat.rb +0 -32
  165. data/lib/capistrano/recipes/deploy/assets.rb +0 -57
  166. data/lib/capistrano/recipes/deploy/dependencies.rb +0 -44
  167. data/lib/capistrano/recipes/deploy/local_dependency.rb +0 -54
  168. data/lib/capistrano/recipes/deploy/remote_dependency.rb +0 -111
  169. data/lib/capistrano/recipes/deploy/scm/accurev.rb +0 -169
  170. data/lib/capistrano/recipes/deploy/scm/base.rb +0 -196
  171. data/lib/capistrano/recipes/deploy/scm/bzr.rb +0 -86
  172. data/lib/capistrano/recipes/deploy/scm/cvs.rb +0 -153
  173. data/lib/capistrano/recipes/deploy/scm/darcs.rb +0 -96
  174. data/lib/capistrano/recipes/deploy/scm/git.rb +0 -282
  175. data/lib/capistrano/recipes/deploy/scm/mercurial.rb +0 -137
  176. data/lib/capistrano/recipes/deploy/scm/none.rb +0 -44
  177. data/lib/capistrano/recipes/deploy/scm/perforce.rb +0 -138
  178. data/lib/capistrano/recipes/deploy/scm/subversion.rb +0 -121
  179. data/lib/capistrano/recipes/deploy/scm.rb +0 -19
  180. data/lib/capistrano/recipes/deploy/strategy/base.rb +0 -88
  181. data/lib/capistrano/recipes/deploy/strategy/checkout.rb +0 -20
  182. data/lib/capistrano/recipes/deploy/strategy/copy.rb +0 -224
  183. data/lib/capistrano/recipes/deploy/strategy/export.rb +0 -20
  184. data/lib/capistrano/recipes/deploy/strategy/remote.rb +0 -52
  185. data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +0 -57
  186. data/lib/capistrano/recipes/deploy/strategy.rb +0 -19
  187. data/lib/capistrano/recipes/deploy/templates/maintenance.rhtml +0 -53
  188. data/lib/capistrano/recipes/deploy.rb +0 -568
  189. data/lib/capistrano/recipes/standard.rb +0 -37
  190. data/lib/capistrano/recipes/templates/maintenance.rhtml +0 -53
  191. data/lib/capistrano/role.rb +0 -102
  192. data/lib/capistrano/server_definition.rb +0 -56
  193. data/lib/capistrano/shell.rb +0 -260
  194. data/lib/capistrano/ssh.rb +0 -101
  195. data/lib/capistrano/task_definition.rb +0 -75
  196. data/lib/capistrano/transfer.rb +0 -216
  197. data/rvmrc.sample +0 -1
  198. data/test/cli/execute_test.rb +0 -132
  199. data/test/cli/help_test.rb +0 -165
  200. data/test/cli/options_test.rb +0 -329
  201. data/test/cli/ui_test.rb +0 -28
  202. data/test/cli_test.rb +0 -17
  203. data/test/command_test.rb +0 -289
  204. data/test/configuration/actions/file_transfer_test.rb +0 -61
  205. data/test/configuration/actions/inspect_test.rb +0 -65
  206. data/test/configuration/actions/invocation_test.rb +0 -247
  207. data/test/configuration/callbacks_test.rb +0 -220
  208. data/test/configuration/connections_test.rb +0 -420
  209. data/test/configuration/execution_test.rb +0 -175
  210. data/test/configuration/loading_test.rb +0 -132
  211. data/test/configuration/namespace_dsl_test.rb +0 -311
  212. data/test/configuration/roles_test.rb +0 -144
  213. data/test/configuration/servers_test.rb +0 -183
  214. data/test/configuration/variables_test.rb +0 -190
  215. data/test/configuration_test.rb +0 -88
  216. data/test/deploy/local_dependency_test.rb +0 -76
  217. data/test/deploy/remote_dependency_test.rb +0 -135
  218. data/test/deploy/scm/accurev_test.rb +0 -23
  219. data/test/deploy/scm/base_test.rb +0 -55
  220. data/test/deploy/scm/bzr_test.rb +0 -51
  221. data/test/deploy/scm/darcs_test.rb +0 -37
  222. data/test/deploy/scm/git_test.rb +0 -184
  223. data/test/deploy/scm/mercurial_test.rb +0 -134
  224. data/test/deploy/scm/none_test.rb +0 -35
  225. data/test/deploy/scm/subversion_test.rb +0 -32
  226. data/test/deploy/strategy/copy_test.rb +0 -321
  227. data/test/extensions_test.rb +0 -69
  228. data/test/fixtures/cli_integration.rb +0 -5
  229. data/test/fixtures/config.rb +0 -5
  230. data/test/fixtures/custom.rb +0 -3
  231. data/test/logger_test.rb +0 -123
  232. data/test/recipes_test.rb +0 -25
  233. data/test/role_test.rb +0 -11
  234. data/test/server_definition_test.rb +0 -121
  235. data/test/shell_test.rb +0 -90
  236. data/test/ssh_test.rb +0 -113
  237. data/test/task_definition_test.rb +0 -116
  238. data/test/transfer_test.rb +0 -160
  239. data/test/utils.rb +0 -37
@@ -0,0 +1,95 @@
1
+ require "capistrano/all"
2
+ require "rake/tasklib"
3
+
4
+ # IMPORTANT: The Capistrano::Plugin system is not yet considered a stable,
5
+ # public API, and is subject to change without notice. Eventually it will be
6
+ # officially documented and supported, but for now, use it at your own risk.
7
+ #
8
+ # Base class for Capistrano plugins. Makes building a Capistrano plugin as easy
9
+ # as writing a `Capistrano::Plugin` subclass and overriding any or all of its
10
+ # three template methods:
11
+ #
12
+ # * set_defaults
13
+ # * register_hooks
14
+ # * define_tasks
15
+ #
16
+ # Within the plugin you can use any methods of the Rake or Capistrano DSLs, like
17
+ # `fetch`, `invoke`, etc. In cases when you need to use SSHKit's backend outside
18
+ # of an `on` block, use the `backend` convenience method. E.g. `backend.test`,
19
+ # `backend.execute`, or `backend.capture`.
20
+ #
21
+ # Package up and distribute your plugin class as a gem and you're good to go!
22
+ #
23
+ # To use a plugin, all a user has to do is install it in the Capfile, like this:
24
+ #
25
+ # # Capfile
26
+ # require "capistrano/superfancy"
27
+ # install_plugin Capistrano::Superfancy
28
+ #
29
+ # Or, to install the plugin without its hooks:
30
+ #
31
+ # # Capfile
32
+ # require "capistrano/superfancy"
33
+ # install_plugin Capistrano::Superfancy, load_hooks: false
34
+ #
35
+ class Capistrano::Plugin < Rake::TaskLib
36
+ include Capistrano::DSL
37
+
38
+ # Implemented by subclasses to provide default values for settings needed by
39
+ # this plugin. Typically done using the `set_if_empty` Capistrano DSL method.
40
+ #
41
+ # Example:
42
+ #
43
+ # def set_defaults
44
+ # set_if_empty :my_plugin_option, true
45
+ # end
46
+ #
47
+ def set_defaults; end
48
+
49
+ # Implemented by subclasses to hook into Capistrano's deployment flow using
50
+ # using the `before` and `after` DSL methods. Note that `register_hooks` will
51
+ # not be called if the user has opted-out of hooks when installing the plugin.
52
+ #
53
+ # Example:
54
+ #
55
+ # def register_hooks
56
+ # after "deploy:updated", "my_plugin:do_something"
57
+ # end
58
+ #
59
+ def register_hooks; end
60
+
61
+ # Implemented by subclasses to define Rake tasks. Typically a plugin will call
62
+ # `eval_rakefile` to load Rake tasks from a separate .rake file.
63
+ #
64
+ # Example:
65
+ #
66
+ # def define_tasks
67
+ # eval_rakefile File.expand_path("../tasks.rake", __FILE__)
68
+ # end
69
+ #
70
+ # For simple tasks, you can define them inline. No need for a separate file.
71
+ #
72
+ # def define_tasks
73
+ # desc "Do something fantastic."
74
+ # task "my_plugin:fantastic" do
75
+ # ...
76
+ # end
77
+ # end
78
+ #
79
+ def define_tasks; end
80
+
81
+ private
82
+
83
+ # Read and eval a .rake file in such a way that `self` within the .rake file
84
+ # refers to this plugin instance. This gives the tasks in the file access to
85
+ # helper methods defined by the plugin.
86
+ def eval_rakefile(path)
87
+ contents = IO.read(path)
88
+ instance_eval(contents, path, 1)
89
+ end
90
+
91
+ # Convenience to access the current SSHKit backend outside of an `on` block.
92
+ def backend
93
+ SSHKit::Backend.current
94
+ end
95
+ end
@@ -0,0 +1,13 @@
1
+ module Capistrano
2
+ module ProcHelpers
3
+ module_function
4
+
5
+ # Tests whether the given object appears to respond to `call` with
6
+ # zero parameters. In Capistrano, such a proc is used to represent a
7
+ # "deferred value". That is, a value that is resolved by invoking `call` at
8
+ # the time it is first needed.
9
+ def callable_without_parameters?(x)
10
+ x.respond_to?(:call) && (!x.respond_to?(:arity) || x.arity.zero?)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,105 @@
1
+ require "capistrano/scm/plugin"
2
+ require "cgi"
3
+ require "securerandom"
4
+ require "shellwords"
5
+ require "uri"
6
+
7
+ class Capistrano::SCM::Git < Capistrano::SCM::Plugin
8
+ def set_defaults
9
+ set_if_empty :git_shallow_clone, false
10
+ set_if_empty :git_wrapper_path, lambda {
11
+ # Use a unique name that won't collide with other deployments, and
12
+ # that cannot be guessed by other processes that have access to /tmp.
13
+ "#{fetch(:tmp_dir)}/git-ssh-#{SecureRandom.hex(10)}.sh"
14
+ }
15
+ set_if_empty :git_environmental_variables, lambda {
16
+ {
17
+ git_askpass: "/bin/echo",
18
+ git_ssh: fetch(:git_wrapper_path)
19
+ }
20
+ }
21
+ set_if_empty :git_max_concurrent_connections, 10
22
+ set_if_empty :git_wait_interval, 0
23
+ end
24
+
25
+ def register_hooks
26
+ after "deploy:new_release_path", "git:create_release"
27
+ before "deploy:check", "git:check"
28
+ before "deploy:set_current_revision", "git:set_current_revision"
29
+ before "deploy:set_current_revision_time", "git:set_current_revision_time"
30
+ end
31
+
32
+ def define_tasks
33
+ eval_rakefile File.expand_path("../tasks/git.rake", __FILE__)
34
+ end
35
+
36
+ def repo_mirror_exists?
37
+ backend.test " [ -f #{repo_path}/HEAD ] "
38
+ end
39
+
40
+ def check_repo_is_reachable
41
+ git :'ls-remote', git_repo_url, "HEAD"
42
+ end
43
+
44
+ def clone_repo
45
+ if (depth = fetch(:git_shallow_clone))
46
+ git :clone, "--mirror", "--depth", depth, "--no-single-branch", git_repo_url, repo_path.to_s
47
+ else
48
+ git :clone, "--mirror", git_repo_url, repo_path.to_s
49
+ end
50
+ end
51
+
52
+ def update_mirror
53
+ # Update the origin URL if necessary.
54
+ git :remote, "set-url", "origin", git_repo_url
55
+
56
+ # Note: Requires git version 1.9 or greater
57
+ if (depth = fetch(:git_shallow_clone))
58
+ git :fetch, "--depth", depth, "origin", fetch(:branch)
59
+ else
60
+ git :remote, :update, "--prune"
61
+ end
62
+ end
63
+
64
+ def verify_commit
65
+ git :"verify-commit", fetch_revision
66
+ end
67
+
68
+ def archive_to_release_path
69
+ if (tree = fetch(:repo_tree))
70
+ tree = tree.slice %r#^/?(.*?)/?$#, 1
71
+ components = tree.split("/").size
72
+ git :archive, fetch(:branch), tree, "| #{SSHKit.config.command_map[:tar]} -x --strip-components #{components} -f - -C", release_path
73
+ else
74
+ git :archive, fetch(:branch), "| #{SSHKit.config.command_map[:tar]} -x -f - -C", release_path
75
+ end
76
+ end
77
+
78
+ def fetch_revision
79
+ backend.capture(:git, "rev-list --max-count=1 #{fetch(:branch)}")
80
+ end
81
+
82
+ def fetch_revision_time
83
+ backend.capture(:git, "log -1 --pretty=format:\"%ct\" #{fetch(:branch)}")
84
+ end
85
+
86
+ def git(*args)
87
+ args.unshift :git
88
+ backend.execute(*args)
89
+ end
90
+
91
+ def git_repo_url
92
+ if fetch(:git_http_username) && fetch(:git_http_password)
93
+ URI.parse(repo_url).tap do |repo_uri|
94
+ repo_uri.user = fetch(:git_http_username)
95
+ repo_uri.password = CGI.escape(fetch(:git_http_password))
96
+ end.to_s
97
+ elsif fetch(:git_http_username)
98
+ URI.parse(repo_url).tap do |repo_uri|
99
+ repo_uri.user = fetch(:git_http_username)
100
+ end.to_s
101
+ else
102
+ repo_url
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,55 @@
1
+ require "capistrano/scm/plugin"
2
+ require "securerandom"
3
+
4
+ class Capistrano::SCM::Hg < Capistrano::SCM::Plugin
5
+ def register_hooks
6
+ after "deploy:new_release_path", "hg:create_release"
7
+ before "deploy:check", "hg:check"
8
+ before "deploy:set_current_revision", "hg:set_current_revision"
9
+ end
10
+
11
+ def define_tasks
12
+ eval_rakefile File.expand_path("../tasks/hg.rake", __FILE__)
13
+ end
14
+
15
+ def hg(*args)
16
+ args.unshift(:hg)
17
+ backend.execute(*args)
18
+ end
19
+
20
+ def repo_mirror_exists?
21
+ backend.test " [ -d #{repo_path}/.hg ] "
22
+ end
23
+
24
+ def check_repo_is_reachable
25
+ hg "id", repo_url
26
+ end
27
+
28
+ def clone_repo
29
+ hg "clone", "--noupdate", repo_url, repo_path.to_s
30
+ end
31
+
32
+ def update_mirror
33
+ hg "pull"
34
+ end
35
+
36
+ def archive_to_release_path
37
+ if (tree = fetch(:repo_tree))
38
+ tree = tree.slice %r#^/?(.*?)/?$#, 1
39
+ components = tree.split("/").size
40
+ temp_tar = "#{fetch(:tmp_dir)}/#{SecureRandom.hex(10)}.tar"
41
+
42
+ hg "archive -p . -I", tree, "--rev", fetch(:branch), temp_tar
43
+
44
+ backend.execute :mkdir, "-p", release_path
45
+ backend.execute :tar, "-x --strip-components #{components} -f", temp_tar, "-C", release_path
46
+ backend.execute :rm, temp_tar
47
+ else
48
+ hg "archive", release_path, "--rev", fetch(:branch)
49
+ end
50
+ end
51
+
52
+ def fetch_revision
53
+ backend.capture(:hg, "log --rev #{fetch(:branch)} --template \"{node}\n\"")
54
+ end
55
+ end
@@ -0,0 +1,13 @@
1
+ require "capistrano/plugin"
2
+ require "capistrano/scm"
3
+
4
+ # Base class for all built-in and third-party SCM plugins. Notice that this
5
+ # class doesn't really do anything other than provide an `scm?` predicate. This
6
+ # tells Capistrano that the plugin provides SCM functionality. All other plugin
7
+ # features are inherited from Capistrano::Plugin.
8
+ #
9
+ class Capistrano::SCM::Plugin < Capistrano::Plugin
10
+ def scm?
11
+ true
12
+ end
13
+ end
@@ -0,0 +1,56 @@
1
+ require "capistrano/scm/plugin"
2
+
3
+ class Capistrano::SCM::Svn < Capistrano::SCM::Plugin
4
+ def register_hooks
5
+ after "deploy:new_release_path", "svn:create_release"
6
+ before "deploy:check", "svn:check"
7
+ before "deploy:set_current_revision", "svn:set_current_revision"
8
+ end
9
+
10
+ def define_tasks
11
+ eval_rakefile File.expand_path("../tasks/svn.rake", __FILE__)
12
+ end
13
+
14
+ def svn(*args)
15
+ args.unshift(:svn)
16
+ args.push "--username #{fetch(:svn_username)}" if fetch(:svn_username)
17
+ args.push "--password #{fetch(:svn_password)}" if fetch(:svn_password)
18
+ args.push "--revision #{fetch(:svn_revision)}" if fetch(:svn_revision)
19
+ backend.execute(*args)
20
+ end
21
+
22
+ def repo_mirror_exists?
23
+ backend.test " [ -d #{repo_path}/.svn ] "
24
+ end
25
+
26
+ def check_repo_is_reachable
27
+ svn_username = fetch(:svn_username) ? "--username #{fetch(:svn_username)}" : ""
28
+ svn_password = fetch(:svn_password) ? "--password #{fetch(:svn_password)}" : ""
29
+ backend.test :svn, :info, repo_url, svn_username, svn_password
30
+ end
31
+
32
+ def clone_repo
33
+ svn :checkout, repo_url, repo_path.to_s
34
+ end
35
+
36
+ def update_mirror
37
+ # Switch the repository URL if necessary.
38
+ repo_mirror_url = fetch_repo_mirror_url
39
+ svn :switch, repo_url unless repo_mirror_url == repo_url
40
+ svn :update
41
+ end
42
+
43
+ def archive_to_release_path
44
+ svn :export, "--force", ".", release_path
45
+ end
46
+
47
+ def fetch_revision
48
+ backend.capture(:svnversion, repo_path.to_s)
49
+ end
50
+
51
+ def fetch_repo_mirror_url
52
+ backend.capture(:svn, :info, repo_path.to_s).each_line do |line|
53
+ return $1 if /\AURL: (.*)\n\z/ =~ line
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,84 @@
1
+ # This trick lets us access the Git plugin within `on` blocks.
2
+ git_plugin = self
3
+
4
+ namespace :git do
5
+ desc "Upload the git wrapper script, this script guarantees that we can script git without getting an interactive prompt"
6
+ task :wrapper do
7
+ on release_roles(:all), in: :groups, limit: fetch(:git_max_concurrent_connections), wait: fetch(:git_wait_interval) do
8
+ execute :mkdir, "-p", File.dirname(fetch(:git_wrapper_path)).shellescape
9
+ upload! StringIO.new("#!/bin/sh -e\nexec /usr/bin/env ssh -o PasswordAuthentication=no -o StrictHostKeyChecking=no \"$@\"\n"), fetch(:git_wrapper_path)
10
+ execute :chmod, "700", fetch(:git_wrapper_path).shellescape
11
+ end
12
+ end
13
+
14
+ desc "Check that the repository is reachable"
15
+ task check: :'git:wrapper' do
16
+ fetch(:branch)
17
+ on release_roles(:all), in: :groups, limit: fetch(:git_max_concurrent_connections), wait: fetch(:git_wait_interval) do
18
+ with fetch(:git_environmental_variables) do
19
+ git_plugin.check_repo_is_reachable
20
+ end
21
+ end
22
+ end
23
+
24
+ desc "Clone the repo to the cache"
25
+ task clone: :'git:wrapper' do
26
+ on release_roles(:all), in: :groups, limit: fetch(:git_max_concurrent_connections), wait: fetch(:git_wait_interval) do
27
+ if git_plugin.repo_mirror_exists?
28
+ info t(:mirror_exists, at: repo_path)
29
+ else
30
+ within deploy_path do
31
+ with fetch(:git_environmental_variables) do
32
+ git_plugin.clone_repo
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ desc "Update the repo mirror to reflect the origin state"
40
+ task update: :'git:clone' do
41
+ on release_roles(:all), in: :groups, limit: fetch(:git_max_concurrent_connections), wait: fetch(:git_wait_interval) do
42
+ within repo_path do
43
+ with fetch(:git_environmental_variables) do
44
+ git_plugin.update_mirror
45
+ git_plugin.verify_commit if fetch(:git_verify_commit)
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ desc "Copy repo to releases"
52
+ task create_release: :'git:update' do
53
+ on release_roles(:all), in: :groups, limit: fetch(:git_max_concurrent_connections), wait: fetch(:git_wait_interval) do
54
+ with fetch(:git_environmental_variables) do
55
+ within repo_path do
56
+ execute :mkdir, "-p", release_path
57
+ git_plugin.archive_to_release_path
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ desc "Determine the revision that will be deployed"
64
+ task :set_current_revision do
65
+ on release_roles(:all), in: :groups, limit: fetch(:git_max_concurrent_connections), wait: fetch(:git_wait_interval) do
66
+ within repo_path do
67
+ with fetch(:git_environmental_variables) do
68
+ set :current_revision, git_plugin.fetch_revision
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ desc "Determine the unix timestamp that the revision that will be deployed was created"
75
+ task :set_current_revision_time do
76
+ on release_roles(:all), in: :groups, limit: fetch(:git_max_concurrent_connections), wait: fetch(:git_wait_interval) do
77
+ within repo_path do
78
+ with fetch(:git_environmental_variables) do
79
+ set :current_revision_time, git_plugin.fetch_revision_time
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,53 @@
1
+ # TODO: this is nearly identical to git.rake. DRY up?
2
+
3
+ # This trick lets us access the Hg plugin within `on` blocks.
4
+ hg_plugin = self
5
+
6
+ namespace :hg do
7
+ desc "Check that the repo is reachable"
8
+ task :check do
9
+ on release_roles :all do
10
+ hg_plugin.check_repo_is_reachable
11
+ end
12
+ end
13
+
14
+ desc "Clone the repo to the cache"
15
+ task :clone do
16
+ on release_roles :all do
17
+ if hg_plugin.repo_mirror_exists?
18
+ info t(:mirror_exists, at: repo_path)
19
+ else
20
+ within deploy_path do
21
+ hg_plugin.clone_repo
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ desc "Pull changes from the remote repo"
28
+ task update: :'hg:clone' do
29
+ on release_roles :all do
30
+ within repo_path do
31
+ hg_plugin.update_mirror
32
+ end
33
+ end
34
+ end
35
+
36
+ desc "Copy repo to releases"
37
+ task create_release: :'hg:update' do
38
+ on release_roles :all do
39
+ within repo_path do
40
+ hg_plugin.archive_to_release_path
41
+ end
42
+ end
43
+ end
44
+
45
+ desc "Determine the revision that will be deployed"
46
+ task :set_current_revision do
47
+ on release_roles :all do
48
+ within repo_path do
49
+ set :current_revision, hg_plugin.fetch_revision
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,53 @@
1
+ # TODO: this is nearly identical to git.rake. DRY up?
2
+
3
+ # This trick lets us access the Svn plugin within `on` blocks.
4
+ svn_plugin = self
5
+
6
+ namespace :svn do
7
+ desc "Check that the repo is reachable"
8
+ task :check do
9
+ on release_roles :all do
10
+ svn_plugin.check_repo_is_reachable
11
+ end
12
+ end
13
+
14
+ desc "Clone the repo to the cache"
15
+ task :clone do
16
+ on release_roles :all do
17
+ if svn_plugin.repo_mirror_exists?
18
+ info t(:mirror_exists, at: repo_path)
19
+ else
20
+ within deploy_path do
21
+ svn_plugin.clone_repo
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ desc "Pull changes from the remote repo"
28
+ task update: :'svn:clone' do
29
+ on release_roles :all do
30
+ within repo_path do
31
+ svn_plugin.update_mirror
32
+ end
33
+ end
34
+ end
35
+
36
+ desc "Copy repo to releases"
37
+ task create_release: :'svn:update' do
38
+ on release_roles :all do
39
+ within repo_path do
40
+ svn_plugin.archive_to_release_path
41
+ end
42
+ end
43
+ end
44
+
45
+ desc "Determine the revision that will be deployed"
46
+ task :set_current_revision do
47
+ on release_roles :all do
48
+ within repo_path do
49
+ set :current_revision, svn_plugin.fetch_revision
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,115 @@
1
+ module Capistrano
2
+ # Base class for SCM strategy providers.
3
+ #
4
+ # @abstract
5
+ #
6
+ # @attr_reader [Rake] context
7
+ #
8
+ # @author Hartog de Mik
9
+ #
10
+ class SCM
11
+ attr_reader :context
12
+
13
+ # Provide a wrapper for the SCM that loads a strategy for the user.
14
+ #
15
+ # @param [Rake] context The context in which the strategy should run
16
+ # @param [Module] strategy A module to include into the SCM instance. The
17
+ # module should provide the abstract methods of Capistrano::SCM
18
+ #
19
+ def initialize(context, strategy)
20
+ @context = context
21
+ singleton = class << self; self; end
22
+ singleton.send(:include, strategy)
23
+ end
24
+
25
+ # Call test in context
26
+ def test!(*args)
27
+ context.test(*args)
28
+ end
29
+
30
+ # The repository URL according to the context
31
+ def repo_url
32
+ context.repo_url
33
+ end
34
+
35
+ # The repository path according to the context
36
+ def repo_path
37
+ context.repo_path
38
+ end
39
+
40
+ # The release path according to the context
41
+ def release_path
42
+ context.release_path
43
+ end
44
+
45
+ # Fetch a var from the context
46
+ # @param [Symbol] variable The variable to fetch
47
+ # @param [Object] default The default value if not found
48
+ #
49
+ def fetch(*args)
50
+ context.fetch(*args)
51
+ end
52
+
53
+ # @abstract
54
+ #
55
+ # Your implementation should check the existence of a cache repository on
56
+ # the deployment target
57
+ #
58
+ # @return [Boolean]
59
+ #
60
+ def test
61
+ raise NotImplementedError, "Your SCM strategy module should provide a #test method"
62
+ end
63
+
64
+ # @abstract
65
+ #
66
+ # Your implementation should check if the specified remote-repository is
67
+ # available.
68
+ #
69
+ # @return [Boolean]
70
+ #
71
+ def check
72
+ raise NotImplementedError, "Your SCM strategy module should provide a #check method"
73
+ end
74
+
75
+ # @abstract
76
+ #
77
+ # Create a (new) clone of the remote-repository on the deployment target
78
+ #
79
+ # @return void
80
+ #
81
+ def clone
82
+ raise NotImplementedError, "Your SCM strategy module should provide a #clone method"
83
+ end
84
+
85
+ # @abstract
86
+ #
87
+ # Update the clone on the deployment target
88
+ #
89
+ # @return void
90
+ #
91
+ def update
92
+ raise NotImplementedError, "Your SCM strategy module should provide a #update method"
93
+ end
94
+
95
+ # @abstract
96
+ #
97
+ # Copy the contents of the cache-repository onto the release path
98
+ #
99
+ # @return void
100
+ #
101
+ def release
102
+ raise NotImplementedError, "Your SCM strategy module should provide a #release method"
103
+ end
104
+
105
+ # @abstract
106
+ #
107
+ # Identify the SHA of the commit that will be deployed. This will most likely involve SshKit's capture method.
108
+ #
109
+ # @return void
110
+ #
111
+ def fetch_revision
112
+ raise NotImplementedError, "Your SCM strategy module should provide a #fetch_revision method"
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,36 @@
1
+ require "capistrano/doctor"
2
+ require "capistrano/immutable_task"
3
+ include Capistrano::DSL
4
+
5
+ namespace :load do
6
+ task :defaults do
7
+ load "capistrano/defaults.rb"
8
+ end
9
+ end
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
+
20
+ stages.each do |stage|
21
+ Rake::Task.define_task(stage) do
22
+ set(:stage, stage.to_sym)
23
+
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
31
+ I18n.locale = fetch(:locale, :en)
32
+ configure_backend
33
+ end
34
+ end
35
+
36
+ require "capistrano/dotfile"