capistrano 3.6.1 → 3.7.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/issue_template.md +19 -0
- data/.github/pull_request_template.md +26 -0
- data/.gitignore +1 -0
- data/.travis.yml +5 -1
- data/CHANGELOG.md +27 -1
- data/DEVELOPMENT.md +7 -1
- data/README.md +3 -4
- data/capistrano.gemspec +1 -1
- data/features/support/vagrant_helpers.rb +3 -5
- data/lib/capistrano/all.rb +1 -0
- data/lib/capistrano/configuration.rb +12 -2
- data/lib/capistrano/configuration/host_filter.rb +1 -1
- data/lib/capistrano/configuration/plugin_installer.rb +20 -2
- data/lib/capistrano/configuration/role_filter.rb +1 -1
- data/lib/capistrano/configuration/scm_resolver.rb +144 -0
- data/lib/capistrano/configuration/validated_variables.rb +3 -4
- data/lib/capistrano/defaults.rb +3 -1
- data/lib/capistrano/doctor/variables_doctor.rb +1 -1
- data/lib/capistrano/dsl/env.rb +2 -9
- data/lib/capistrano/dsl/paths.rb +1 -1
- data/lib/capistrano/dsl/task_enhancements.rb +0 -8
- data/lib/capistrano/scm/git.rb +73 -0
- data/lib/capistrano/scm/hg.rb +48 -0
- data/lib/capistrano/scm/plugin.rb +13 -0
- data/lib/capistrano/scm/svn.rb +47 -0
- data/lib/capistrano/{tasks → scm/tasks}/git.rake +9 -24
- data/lib/capistrano/{tasks → scm/tasks}/hg.rake +11 -10
- data/lib/capistrano/{tasks → scm/tasks}/svn.rake +11 -10
- data/lib/capistrano/setup.rb +1 -1
- data/lib/capistrano/tasks/deploy.rake +0 -3
- data/lib/capistrano/templates/Capfile +18 -7
- data/lib/capistrano/templates/deploy.rb.erb +7 -10
- data/lib/capistrano/templates/stage.rb.erb +7 -7
- data/lib/capistrano/version.rb +1 -1
- data/lib/capistrano/version_validator.rb +2 -5
- data/spec/lib/capistrano/configuration/host_filter_spec.rb +5 -0
- data/spec/lib/capistrano/configuration/plugin_installer_spec.rb +98 -0
- data/spec/lib/capistrano/configuration/role_filter_spec.rb +17 -1
- data/spec/lib/capistrano/doctor/variables_doctor_spec.rb +0 -7
- data/spec/lib/capistrano/dsl/task_enhancements_spec.rb +0 -15
- data/spec/lib/capistrano/scm/git_spec.rb +131 -0
- data/spec/lib/capistrano/scm/hg_spec.rb +104 -0
- data/spec/lib/capistrano/scm/svn_spec.rb +116 -0
- data/spec/lib/capistrano/scm_spec.rb +1 -1
- metadata +23 -20
- data/features/remote_file_task.feature +0 -14
- data/issue_template.md +0 -21
- data/lib/capistrano/git.rb +0 -54
- data/lib/capistrano/hg.rb +0 -43
- data/lib/capistrano/svn.rb +0 -42
- data/spec/lib/capistrano/git_spec.rb +0 -109
- data/spec/lib/capistrano/hg_spec.rb +0 -90
- data/spec/lib/capistrano/svn_spec.rb +0 -105
@@ -91,10 +91,9 @@ module Capistrano
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def assert_value_or_block_not_both(value, block)
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
end
|
94
|
+
return if value.nil? || block.nil?
|
95
|
+
raise Capistrano::ValidationError,
|
96
|
+
"Value and block both passed to Configuration#set"
|
98
97
|
end
|
99
98
|
|
100
99
|
class ValidatedQuestion < Question
|
data/lib/capistrano/defaults.rb
CHANGED
@@ -18,7 +18,9 @@ end
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
|
21
|
+
# We use a special :_default_git value so that SCMResolver can tell whether the
|
22
|
+
# default has been replaced by the user via `set`.
|
23
|
+
set_if_empty :scm, Capistrano::Configuration::SCMResolver::DEFAULT_GIT
|
22
24
|
set_if_empty :branch, "master"
|
23
25
|
set_if_empty :deploy_to, -> { "/var/www/#{fetch(:application)}" }
|
24
26
|
set_if_empty :tmp_dir, "/tmp"
|
@@ -7,7 +7,7 @@ module Capistrano
|
|
7
7
|
class VariablesDoctor
|
8
8
|
# These are keys that have no default values in Capistrano, but are
|
9
9
|
# nonetheless expected to be set.
|
10
|
-
WHITELIST = [:application, :repo_url
|
10
|
+
WHITELIST = [:application, :repo_url].freeze
|
11
11
|
private_constant :WHITELIST
|
12
12
|
|
13
13
|
include Capistrano::Doctor::OutputHelpers
|
data/lib/capistrano/dsl/env.rb
CHANGED
@@ -7,15 +7,8 @@ module Capistrano
|
|
7
7
|
def_delegators :env,
|
8
8
|
:configure_backend, :fetch, :set, :set_if_empty, :delete,
|
9
9
|
:ask, :role, :server, :primary, :validate, :append,
|
10
|
-
:remove, :dry_run?, :install_plugin
|
11
|
-
|
12
|
-
def is_question?(key)
|
13
|
-
env.is_question?(key)
|
14
|
-
end
|
15
|
-
|
16
|
-
def any?(key)
|
17
|
-
env.any?(key)
|
18
|
-
end
|
10
|
+
:remove, :dry_run?, :install_plugin, :any?, :is_question?,
|
11
|
+
:configure_scm, :scm_plugin_installed?
|
19
12
|
|
20
13
|
def roles(*names)
|
21
14
|
env.roles_for(names.flatten)
|
data/lib/capistrano/dsl/paths.rb
CHANGED
@@ -17,14 +17,6 @@ module Capistrano
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
def remote_file(task)
|
21
|
-
warn("[Deprecation Warning] `remote_file` is deprecated and will be "\
|
22
|
-
"removed in Capistrano 3.7.0")
|
23
|
-
|
24
|
-
target_roles = task.delete(:roles) { :all }
|
25
|
-
define_remote_file_task(task, target_roles)
|
26
|
-
end
|
27
|
-
|
28
20
|
def define_remote_file_task(task, target_roles)
|
29
21
|
Capistrano::UploadTask.define_task(task) do |t|
|
30
22
|
prerequisite_file = t.prerequisites.first
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require "capistrano/scm/plugin"
|
2
|
+
|
3
|
+
class Capistrano::SCM::Git < Capistrano::SCM::Plugin
|
4
|
+
def set_defaults
|
5
|
+
set_if_empty :git_shallow_clone, false
|
6
|
+
set_if_empty :git_wrapper_path, lambda {
|
7
|
+
# Try to avoid permissions issues when multiple users deploy the same app
|
8
|
+
# by using different file names in the same dir for each deployer and stage.
|
9
|
+
suffix = [:application, :stage, :local_user].map { |key| fetch(key).to_s }.join("-").gsub(/\s+/, "-")
|
10
|
+
"#{fetch(:tmp_dir)}/git-ssh-#{suffix}.sh"
|
11
|
+
}
|
12
|
+
set_if_empty :git_environmental_variables, lambda {
|
13
|
+
{
|
14
|
+
git_askpass: "/bin/echo",
|
15
|
+
git_ssh: fetch(:git_wrapper_path)
|
16
|
+
}
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def register_hooks
|
21
|
+
after "deploy:new_release_path", "git:create_release"
|
22
|
+
before "deploy:check", "git:check"
|
23
|
+
before "deploy:set_current_revision", "git:set_current_revision"
|
24
|
+
end
|
25
|
+
|
26
|
+
def define_tasks
|
27
|
+
eval_rakefile File.expand_path("../tasks/git.rake", __FILE__)
|
28
|
+
end
|
29
|
+
|
30
|
+
def repo_mirror_exists?
|
31
|
+
backend.test " [ -f #{repo_path}/HEAD ] "
|
32
|
+
end
|
33
|
+
|
34
|
+
def check_repo_is_reachable
|
35
|
+
git :'ls-remote --heads', repo_url
|
36
|
+
end
|
37
|
+
|
38
|
+
def clone_repo
|
39
|
+
if (depth = fetch(:git_shallow_clone))
|
40
|
+
git :clone, "--mirror", "--depth", depth, "--no-single-branch", repo_url, repo_path.to_s
|
41
|
+
else
|
42
|
+
git :clone, "--mirror", repo_url, repo_path.to_s
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def update_mirror
|
47
|
+
# Note: Requires git version 1.9 or greater
|
48
|
+
if (depth = fetch(:git_shallow_clone))
|
49
|
+
git :fetch, "--depth", depth, "origin", fetch(:branch)
|
50
|
+
else
|
51
|
+
git :remote, :update, "--prune"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def archive_to_release_path
|
56
|
+
if (tree = fetch(:repo_tree))
|
57
|
+
tree = tree.slice %r#^/?(.*?)/?$#, 1
|
58
|
+
components = tree.split("/").size
|
59
|
+
git :archive, fetch(:branch), tree, "| #{SSHKit.config.command_map[:tar]} -x --strip-components #{components} -f - -C", release_path
|
60
|
+
else
|
61
|
+
git :archive, fetch(:branch), "| #{SSHKit.config.command_map[:tar]} -x -f - -C", release_path
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def fetch_revision
|
66
|
+
backend.capture(:git, "rev-list --max-count=1 #{fetch(:branch)}")
|
67
|
+
end
|
68
|
+
|
69
|
+
def git(*args)
|
70
|
+
args.unshift :git
|
71
|
+
backend.execute(*args)
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "capistrano/scm/plugin"
|
2
|
+
|
3
|
+
class Capistrano::SCM::Hg < Capistrano::SCM::Plugin
|
4
|
+
def register_hooks
|
5
|
+
after "deploy:new_release_path", "hg:create_release"
|
6
|
+
before "deploy:check", "hg:check"
|
7
|
+
before "deploy:set_current_revision", "hg:set_current_revision"
|
8
|
+
end
|
9
|
+
|
10
|
+
def define_tasks
|
11
|
+
eval_rakefile File.expand_path("../tasks/hg.rake", __FILE__)
|
12
|
+
end
|
13
|
+
|
14
|
+
def hg(*args)
|
15
|
+
args.unshift(:hg)
|
16
|
+
backend.execute(*args)
|
17
|
+
end
|
18
|
+
|
19
|
+
def repo_mirror_exists?
|
20
|
+
backend.test " [ -d #{repo_path}/.hg ] "
|
21
|
+
end
|
22
|
+
|
23
|
+
def check_repo_is_reachable
|
24
|
+
hg "id", repo_url
|
25
|
+
end
|
26
|
+
|
27
|
+
def clone_repo
|
28
|
+
hg "clone", "--noupdate", repo_url, repo_path.to_s
|
29
|
+
end
|
30
|
+
|
31
|
+
def update_mirror
|
32
|
+
hg "pull"
|
33
|
+
end
|
34
|
+
|
35
|
+
def archive_to_release_path
|
36
|
+
if (tree = fetch(:repo_tree))
|
37
|
+
tree = tree.slice %r#^/?(.*?)/?$#, 1
|
38
|
+
components = tree.split("/").size
|
39
|
+
hg "archive --type tgz -p . -I", tree, "--rev", fetch(:branch), "| tar -x --strip-components #{components} -f - -C", release_path
|
40
|
+
else
|
41
|
+
hg "archive", release_path, "--rev", fetch(:branch)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def fetch_revision
|
46
|
+
backend.capture(:hg, "log --rev #{fetch(:branch)} --template \"{node}\n\"")
|
47
|
+
end
|
48
|
+
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,47 @@
|
|
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
|
+
svn :update
|
38
|
+
end
|
39
|
+
|
40
|
+
def archive_to_release_path
|
41
|
+
svn :export, "--force", ".", release_path
|
42
|
+
end
|
43
|
+
|
44
|
+
def fetch_revision
|
45
|
+
backend.capture(:svnversion, repo_path.to_s)
|
46
|
+
end
|
47
|
+
end
|
@@ -1,22 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
@strategy ||= Capistrano::Git.new(self, fetch(:git_strategy, Capistrano::Git::DefaultStrategy))
|
4
|
-
end
|
5
|
-
|
6
|
-
set :git_wrapper_path, lambda {
|
7
|
-
# Try to avoid permissions issues when multiple users deploy the same app
|
8
|
-
# by using different file names in the same dir for each deployer and stage.
|
9
|
-
suffix = [:application, :stage, :local_user].map { |key| fetch(key).to_s }.join("-").gsub(/\s+/, "-")
|
10
|
-
"#{fetch(:tmp_dir)}/git-ssh-#{suffix}.sh"
|
11
|
-
}
|
12
|
-
|
13
|
-
set :git_environmental_variables, lambda {
|
14
|
-
{
|
15
|
-
git_askpass: "/bin/echo",
|
16
|
-
git_ssh: fetch(:git_wrapper_path)
|
17
|
-
}
|
18
|
-
}
|
1
|
+
# This trick lets us access the Git plugin within `on` blocks.
|
2
|
+
git_plugin = self
|
19
3
|
|
4
|
+
namespace :git do
|
20
5
|
desc "Upload the git wrapper script, this script guarantees that we can script git without getting an interactive prompt"
|
21
6
|
task :wrapper do
|
22
7
|
on release_roles :all do
|
@@ -31,7 +16,7 @@ namespace :git do
|
|
31
16
|
fetch(:branch)
|
32
17
|
on release_roles :all do
|
33
18
|
with fetch(:git_environmental_variables) do
|
34
|
-
|
19
|
+
git_plugin.check_repo_is_reachable
|
35
20
|
end
|
36
21
|
end
|
37
22
|
end
|
@@ -39,12 +24,12 @@ namespace :git do
|
|
39
24
|
desc "Clone the repo to the cache"
|
40
25
|
task clone: :'git:wrapper' do
|
41
26
|
on release_roles :all do
|
42
|
-
if
|
27
|
+
if git_plugin.repo_mirror_exists?
|
43
28
|
info t(:mirror_exists, at: repo_path)
|
44
29
|
else
|
45
30
|
within deploy_path do
|
46
31
|
with fetch(:git_environmental_variables) do
|
47
|
-
|
32
|
+
git_plugin.clone_repo
|
48
33
|
end
|
49
34
|
end
|
50
35
|
end
|
@@ -56,7 +41,7 @@ namespace :git do
|
|
56
41
|
on release_roles :all do
|
57
42
|
within repo_path do
|
58
43
|
with fetch(:git_environmental_variables) do
|
59
|
-
|
44
|
+
git_plugin.update_mirror
|
60
45
|
end
|
61
46
|
end
|
62
47
|
end
|
@@ -68,7 +53,7 @@ namespace :git do
|
|
68
53
|
with fetch(:git_environmental_variables) do
|
69
54
|
within repo_path do
|
70
55
|
execute :mkdir, "-p", release_path
|
71
|
-
|
56
|
+
git_plugin.archive_to_release_path
|
72
57
|
end
|
73
58
|
end
|
74
59
|
end
|
@@ -79,7 +64,7 @@ namespace :git do
|
|
79
64
|
on release_roles :all do
|
80
65
|
within repo_path do
|
81
66
|
with fetch(:git_environmental_variables) do
|
82
|
-
set :current_revision,
|
67
|
+
set :current_revision, git_plugin.fetch_revision
|
83
68
|
end
|
84
69
|
end
|
85
70
|
end
|
@@ -1,23 +1,24 @@
|
|
1
|
-
|
2
|
-
def strategy
|
3
|
-
@strategy ||= Capistrano::Hg.new(self, fetch(:hg_strategy, Capistrano::Hg::DefaultStrategy))
|
4
|
-
end
|
1
|
+
# TODO: this is nearly identical to git.rake. DRY up?
|
5
2
|
|
3
|
+
# This trick lets us access the Hg plugin within `on` blocks.
|
4
|
+
hg_plugin = self
|
5
|
+
|
6
|
+
namespace :hg do
|
6
7
|
desc "Check that the repo is reachable"
|
7
8
|
task :check do
|
8
9
|
on release_roles :all do
|
9
|
-
|
10
|
+
hg_plugin.check_repo_is_reachable
|
10
11
|
end
|
11
12
|
end
|
12
13
|
|
13
14
|
desc "Clone the repo to the cache"
|
14
15
|
task :clone do
|
15
16
|
on release_roles :all do
|
16
|
-
if
|
17
|
+
if hg_plugin.repo_mirror_exists?
|
17
18
|
info t(:mirror_exists, at: repo_path)
|
18
19
|
else
|
19
20
|
within deploy_path do
|
20
|
-
|
21
|
+
hg_plugin.clone_repo
|
21
22
|
end
|
22
23
|
end
|
23
24
|
end
|
@@ -27,7 +28,7 @@ namespace :hg do
|
|
27
28
|
task update: :'hg:clone' do
|
28
29
|
on release_roles :all do
|
29
30
|
within repo_path do
|
30
|
-
|
31
|
+
hr.update_mirror
|
31
32
|
end
|
32
33
|
end
|
33
34
|
end
|
@@ -36,7 +37,7 @@ namespace :hg do
|
|
36
37
|
task create_release: :'hg:update' do
|
37
38
|
on release_roles :all do
|
38
39
|
within repo_path do
|
39
|
-
|
40
|
+
hg_plugin.archive_to_release_path
|
40
41
|
end
|
41
42
|
end
|
42
43
|
end
|
@@ -45,7 +46,7 @@ namespace :hg do
|
|
45
46
|
task :set_current_revision do
|
46
47
|
on release_roles :all do
|
47
48
|
within repo_path do
|
48
|
-
set :current_revision,
|
49
|
+
set :current_revision, hg_plugin.fetch_revision
|
49
50
|
end
|
50
51
|
end
|
51
52
|
end
|
@@ -1,23 +1,24 @@
|
|
1
|
-
|
2
|
-
def strategy
|
3
|
-
@strategy ||= Capistrano::Svn.new(self, fetch(:svn_strategy, Capistrano::Svn::DefaultStrategy))
|
4
|
-
end
|
1
|
+
# TODO: this is nearly identical to git.rake. DRY up?
|
5
2
|
|
3
|
+
# This trick lets us access the Svn plugin within `on` blocks.
|
4
|
+
svn_plugin = self
|
5
|
+
|
6
|
+
namespace :svn do
|
6
7
|
desc "Check that the repo is reachable"
|
7
8
|
task :check do
|
8
9
|
on release_roles :all do
|
9
|
-
|
10
|
+
svn_plugin.check_repo_is_reachable
|
10
11
|
end
|
11
12
|
end
|
12
13
|
|
13
14
|
desc "Clone the repo to the cache"
|
14
15
|
task :clone do
|
15
16
|
on release_roles :all do
|
16
|
-
if
|
17
|
+
if svn_plugin.repo_mirror_exists?
|
17
18
|
info t(:mirror_exists, at: repo_path)
|
18
19
|
else
|
19
20
|
within deploy_path do
|
20
|
-
|
21
|
+
svn_plugin.clone_repo
|
21
22
|
end
|
22
23
|
end
|
23
24
|
end
|
@@ -27,7 +28,7 @@ namespace :svn do
|
|
27
28
|
task update: :'svn:clone' do
|
28
29
|
on release_roles :all do
|
29
30
|
within repo_path do
|
30
|
-
|
31
|
+
svn_plugin.update_mirror
|
31
32
|
end
|
32
33
|
end
|
33
34
|
end
|
@@ -36,7 +37,7 @@ namespace :svn do
|
|
36
37
|
task create_release: :'svn:update' do
|
37
38
|
on release_roles :all do
|
38
39
|
within repo_path do
|
39
|
-
|
40
|
+
svn_plugin.archive_to_release_path
|
40
41
|
end
|
41
42
|
end
|
42
43
|
end
|
@@ -45,7 +46,7 @@ namespace :svn do
|
|
45
46
|
task :set_current_revision do
|
46
47
|
on release_roles :all do
|
47
48
|
within repo_path do
|
48
|
-
set :current_revision,
|
49
|
+
set :current_revision, svn_plugin.fetch_revision
|
49
50
|
end
|
50
51
|
end
|
51
52
|
end
|