capistrano 3.6.1 → 3.7.0.beta1

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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/.github/issue_template.md +19 -0
  3. data/.github/pull_request_template.md +26 -0
  4. data/.gitignore +1 -0
  5. data/.travis.yml +5 -1
  6. data/CHANGELOG.md +27 -1
  7. data/DEVELOPMENT.md +7 -1
  8. data/README.md +3 -4
  9. data/capistrano.gemspec +1 -1
  10. data/features/support/vagrant_helpers.rb +3 -5
  11. data/lib/capistrano/all.rb +1 -0
  12. data/lib/capistrano/configuration.rb +12 -2
  13. data/lib/capistrano/configuration/host_filter.rb +1 -1
  14. data/lib/capistrano/configuration/plugin_installer.rb +20 -2
  15. data/lib/capistrano/configuration/role_filter.rb +1 -1
  16. data/lib/capistrano/configuration/scm_resolver.rb +144 -0
  17. data/lib/capistrano/configuration/validated_variables.rb +3 -4
  18. data/lib/capistrano/defaults.rb +3 -1
  19. data/lib/capistrano/doctor/variables_doctor.rb +1 -1
  20. data/lib/capistrano/dsl/env.rb +2 -9
  21. data/lib/capistrano/dsl/paths.rb +1 -1
  22. data/lib/capistrano/dsl/task_enhancements.rb +0 -8
  23. data/lib/capistrano/scm/git.rb +73 -0
  24. data/lib/capistrano/scm/hg.rb +48 -0
  25. data/lib/capistrano/scm/plugin.rb +13 -0
  26. data/lib/capistrano/scm/svn.rb +47 -0
  27. data/lib/capistrano/{tasks → scm/tasks}/git.rake +9 -24
  28. data/lib/capistrano/{tasks → scm/tasks}/hg.rake +11 -10
  29. data/lib/capistrano/{tasks → scm/tasks}/svn.rake +11 -10
  30. data/lib/capistrano/setup.rb +1 -1
  31. data/lib/capistrano/tasks/deploy.rake +0 -3
  32. data/lib/capistrano/templates/Capfile +18 -7
  33. data/lib/capistrano/templates/deploy.rb.erb +7 -10
  34. data/lib/capistrano/templates/stage.rb.erb +7 -7
  35. data/lib/capistrano/version.rb +1 -1
  36. data/lib/capistrano/version_validator.rb +2 -5
  37. data/spec/lib/capistrano/configuration/host_filter_spec.rb +5 -0
  38. data/spec/lib/capistrano/configuration/plugin_installer_spec.rb +98 -0
  39. data/spec/lib/capistrano/configuration/role_filter_spec.rb +17 -1
  40. data/spec/lib/capistrano/doctor/variables_doctor_spec.rb +0 -7
  41. data/spec/lib/capistrano/dsl/task_enhancements_spec.rb +0 -15
  42. data/spec/lib/capistrano/scm/git_spec.rb +131 -0
  43. data/spec/lib/capistrano/scm/hg_spec.rb +104 -0
  44. data/spec/lib/capistrano/scm/svn_spec.rb +116 -0
  45. data/spec/lib/capistrano/scm_spec.rb +1 -1
  46. metadata +23 -20
  47. data/features/remote_file_task.feature +0 -14
  48. data/issue_template.md +0 -21
  49. data/lib/capistrano/git.rb +0 -54
  50. data/lib/capistrano/hg.rb +0 -43
  51. data/lib/capistrano/svn.rb +0 -42
  52. data/spec/lib/capistrano/git_spec.rb +0 -109
  53. data/spec/lib/capistrano/hg_spec.rb +0 -90
  54. data/spec/lib/capistrano/svn_spec.rb +0 -105
@@ -27,7 +27,7 @@ stages.each do |stage|
27
27
  load deploy_config_path
28
28
  load stage_config_path.join("#{stage}.rb")
29
29
  end
30
- load "capistrano/#{fetch(:scm)}.rb"
30
+ configure_scm
31
31
  I18n.locale = fetch(:locale, :en)
32
32
  configure_backend
33
33
  end
@@ -26,7 +26,6 @@ namespace :deploy do
26
26
  end
27
27
 
28
28
  task updating: :new_release_path do
29
- invoke "#{scm}:create_release"
30
29
  invoke "deploy:set_current_revision"
31
30
  invoke "deploy:symlink:shared"
32
31
  end
@@ -53,7 +52,6 @@ namespace :deploy do
53
52
 
54
53
  desc "Check required files and directories exist"
55
54
  task :check do
56
- invoke "#{scm}:check"
57
55
  invoke "deploy:check:directories"
58
56
  invoke "deploy:check:linked_dirs"
59
57
  invoke "deploy:check:make_linked_dirs"
@@ -225,7 +223,6 @@ namespace :deploy do
225
223
 
226
224
  desc "Place a REVISION file with the current revision SHA in the current release path"
227
225
  task :set_current_revision do
228
- invoke "#{scm}:set_current_revision"
229
226
  on release_roles(:all) do
230
227
  within release_path do
231
228
  execute :echo, "\"#{fetch(:current_revision)}\" >> REVISION"
@@ -4,6 +4,17 @@ require "capistrano/setup"
4
4
  # Include default deployment tasks
5
5
  require "capistrano/deploy"
6
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
17
+
7
18
  # Include tasks from other gems included in your Gemfile
8
19
  #
9
20
  # For documentation on these, see for example:
@@ -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
38
  Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
@@ -1,33 +1,30 @@
1
1
  # config valid only for current version of Capistrano
2
- lock '<%= Capistrano::VERSION %>'
2
+ lock "<%= Capistrano::VERSION %>"
3
3
 
4
- set :application, 'my_app_name'
5
- set :repo_url, 'git@example.com:me/my_repo.git'
4
+ set :application, "my_app_name"
5
+ set :repo_url, "git@example.com:me/my_repo.git"
6
6
 
7
7
  # Default branch is :master
8
8
  # ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp
9
9
 
10
10
  # Default deploy_to directory is /var/www/my_app_name
11
- # set :deploy_to, '/var/www/my_app_name'
12
-
13
- # Default value for :scm is :git
14
- # set :scm, :git
11
+ # set :deploy_to, "/var/www/my_app_name"
15
12
 
16
13
  # Default value for :format is :airbrussh.
17
14
  # set :format, :airbrussh
18
15
 
19
16
  # You can configure the Airbrussh format using :format_options.
20
17
  # These are the defaults.
21
- # set :format_options, command_output: true, log_file: 'log/capistrano.log', color: :auto, truncate: :auto
18
+ # set :format_options, command_output: true, log_file: "log/capistrano.log", color: :auto, truncate: :auto
22
19
 
23
20
  # Default value for :pty is false
24
21
  # set :pty, true
25
22
 
26
23
  # Default value for :linked_files is []
27
- # append :linked_files, 'config/database.yml', 'config/secrets.yml'
24
+ # append :linked_files, "config/database.yml", "config/secrets.yml"
28
25
 
29
26
  # Default value for linked_dirs is []
30
- # append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'public/system'
27
+ # append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system"
31
28
 
32
29
  # Default value for default_env is {}
33
30
  # set :default_env, { path: "/opt/ruby/bin:$PATH" }
@@ -3,9 +3,9 @@
3
3
  # Defines a single server with a list of roles and multiple properties.
4
4
  # You can define all roles on a single server, or split them:
5
5
 
6
- # server 'example.com', user: 'deploy', roles: %w{app db web}, my_property: :my_value
7
- # server 'example.com', user: 'deploy', roles: %w{app web}, other_property: :other_value
8
- # server 'db.example.com', user: 'deploy', roles: %w{db}
6
+ # server "example.com", user: "deploy", roles: %w{app db web}, my_property: :my_value
7
+ # server "example.com", user: "deploy", roles: %w{app web}, other_property: :other_value
8
+ # server "db.example.com", user: "deploy", roles: %w{db}
9
9
 
10
10
 
11
11
 
@@ -49,13 +49,13 @@
49
49
  #
50
50
  # The server-based syntax can be used to override options:
51
51
  # ------------------------------------
52
- # server 'example.com',
53
- # user: 'user_name',
52
+ # server "example.com",
53
+ # user: "user_name",
54
54
  # roles: %w{web app},
55
55
  # ssh_options: {
56
- # user: 'user_name', # overrides user setting above
56
+ # user: "user_name", # overrides user setting above
57
57
  # keys: %w(/home/user_name/.ssh/id_rsa),
58
58
  # forward_agent: false,
59
59
  # auth_methods: %w(publickey password)
60
- # # password: 'please use keys'
60
+ # # password: "please use keys"
61
61
  # }
@@ -1,3 +1,3 @@
1
1
  module Capistrano
2
- VERSION = "3.6.1".freeze
2
+ VERSION = "3.7.0.beta1".freeze
3
3
  end
@@ -5,11 +5,8 @@ module Capistrano
5
5
  end
6
6
 
7
7
  def verify
8
- if match?
9
- self
10
- else
11
- raise "Capfile locked at #{version}, but #{current_version} is loaded"
12
- end
8
+ return self if match?
9
+ raise "Capfile locked at #{version}, but #{current_version} is loaded"
13
10
  end
14
11
 
15
12
  private
@@ -55,6 +55,11 @@ module Capistrano
55
55
  let(:values) { 'server\d{1,3}$' }
56
56
  it_behaves_like "it filters hosts correctly", %w{server1 server2 server3 server4 server5}
57
57
  end
58
+
59
+ context "without number" do
60
+ let(:values) { "server" }
61
+ it_behaves_like "it filters hosts correctly", %w{}
62
+ end
58
63
  end
59
64
  end
60
65
  end
@@ -0,0 +1,98 @@
1
+ require "spec_helper"
2
+ require "capistrano/plugin"
3
+ require "capistrano/scm/plugin"
4
+
5
+ module Capistrano
6
+ class Configuration
7
+ class ExamplePlugin < Capistrano::Plugin
8
+ def set_defaults
9
+ set_if_empty :example_variable, "foo"
10
+ end
11
+
12
+ def define_tasks
13
+ task :example
14
+ task :example_prerequisite
15
+ end
16
+
17
+ def register_hooks
18
+ before :example, :example_prerequisite
19
+ end
20
+ end
21
+
22
+ class ExampleSCMPlugin < Capistrano::SCM::Plugin
23
+ end
24
+
25
+ describe PluginInstaller do
26
+ include Capistrano::DSL
27
+
28
+ let(:installer) { PluginInstaller.new }
29
+ let(:options) { {} }
30
+ let(:plugin) { ExamplePlugin.new }
31
+
32
+ before do
33
+ installer.install(plugin, **options)
34
+ end
35
+
36
+ after do
37
+ Rake::Task.clear
38
+ Capistrano::Configuration.reset!
39
+ end
40
+
41
+ context "installing plugin" do
42
+ it "defines tasks" do
43
+ expect(Rake::Task[:example]).to_not be_nil
44
+ expect(Rake::Task[:example_prerequisite]).to_not be_nil
45
+ end
46
+
47
+ it "registers hooks" do
48
+ task = Rake::Task[:example]
49
+ expect(task.prerequisites).to eq([:example_prerequisite])
50
+ end
51
+
52
+ it "sets defaults when load:defaults is invoked" do
53
+ expect(fetch(:example_variable)).to be_nil
54
+ invoke "load:defaults"
55
+ expect(fetch(:example_variable)).to eq("foo")
56
+ end
57
+
58
+ it "doesn't say an SCM is installed" do
59
+ expect(installer.scm_installed?).to be_falsey
60
+ end
61
+ end
62
+
63
+ context "installing plugin class" do
64
+ let(:plugin) { ExamplePlugin }
65
+
66
+ it "defines tasks" do
67
+ expect(Rake::Task[:example]).to_not be_nil
68
+ expect(Rake::Task[:example_prerequisite]).to_not be_nil
69
+ end
70
+ end
71
+
72
+ context "installing plugin without hooks" do
73
+ let(:options) { { load_hooks: false } }
74
+
75
+ it "doesn't register hooks" do
76
+ task = Rake::Task[:example]
77
+ expect(task.prerequisites).to be_empty
78
+ end
79
+ end
80
+
81
+ context "installing plugin and loading immediately" do
82
+ let(:options) { { load_immediately: true } }
83
+
84
+ it "sets defaults immediately" do
85
+ expect(fetch(:example_variable)).to eq("foo")
86
+ end
87
+ end
88
+
89
+ context "installing an SCM plugin" do
90
+ let(:plugin) { ExampleSCMPlugin }
91
+
92
+ it "says an SCM is installed" do
93
+ expect(installer.scm_installed?).to be_truthy
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -11,7 +11,8 @@ module Capistrano
11
11
  Server.new("server2").add_role(:web),
12
12
  Server.new("server3").add_role(:redis),
13
13
  Server.new("server4").add_role(:db),
14
- Server.new("server5").add_role(:stageweb)
14
+ Server.new("server5").add_role(:stageweb),
15
+ Server.new("server6").add_role(:"db.new")
15
16
  ]
16
17
  end
17
18
 
@@ -58,6 +59,21 @@ module Capistrano
58
59
  let(:values) { "db,/red/" }
59
60
  it_behaves_like "it filters roles correctly", 3, %w{server1 server3 server4}
60
61
  end
62
+
63
+ context "with a dot wildcard" do
64
+ let(:values) { "db.*" }
65
+ it_behaves_like "it filters roles correctly", 0, %w{}
66
+ end
67
+
68
+ context "with a dot" do
69
+ let(:values) { "db.new" }
70
+ it_behaves_like "it filters roles correctly", 1, %w{server6}
71
+ end
72
+
73
+ context "with a dot wildcard regex" do
74
+ let(:values) { "/db.*/" }
75
+ it_behaves_like "it filters roles correctly", 3, %w{server1 server4 server6}
76
+ end
61
77
  end
62
78
  end
63
79
  end
@@ -15,7 +15,6 @@ module Capistrano
15
15
  env.variables.untrusted! do
16
16
  set :application, "my_app"
17
17
  set :repo_url, ".git"
18
- set :git_strategy, "Capistrano::Git::DefaultStrategy"
19
18
  set :copy_strategy, :scp
20
19
  set :custom_setting, "hello"
21
20
  set "string_setting", "hello"
@@ -57,12 +56,6 @@ module Capistrano
57
56
  .to_stdout
58
57
  end
59
58
 
60
- it "does not print warning for the whitelisted git_strategy variable" do
61
- expect { doc.call }.not_to \
62
- output(/:git_strategy is not a recognized Capistrano setting/)\
63
- .to_stdout
64
- end
65
-
66
59
  describe "Rake" do
67
60
  before do
68
61
  load File.expand_path("../../../../../lib/capistrano/doctor.rb",
@@ -104,20 +104,5 @@ module Capistrano
104
104
  expect { Rake::Task["task"].invoke order }.to raise_error(ArgumentError, 'Task "non_existent_task" not found')
105
105
  end
106
106
  end
107
-
108
- describe "remote_file" do
109
- subject(:remote_file) { task_enhancements.remote_file("source" => "destination") }
110
-
111
- it { expect(remote_file.name).to eq("source") }
112
- it { is_expected.to be_a(Capistrano::UploadTask) }
113
-
114
- describe "namespaced" do
115
- let(:app) { Rake.application }
116
- around { |ex| app.in_namespace("namespace", &ex) }
117
-
118
- it { expect(remote_file.name).to eq("source") }
119
- it { is_expected.to be_a(Capistrano::UploadTask) }
120
- end
121
- end
122
107
  end
123
108
  end
@@ -0,0 +1,131 @@
1
+ require "spec_helper"
2
+
3
+ require "capistrano/scm/git"
4
+
5
+ module Capistrano
6
+ describe SCM::Git do
7
+ subject { Capistrano::SCM::Git.new }
8
+
9
+ # This allows us to easily use `set`, `fetch`, etc. in the examples.
10
+ let(:env) { Capistrano::Configuration.env }
11
+
12
+ # Stub the SSHKit backend so we can set up expectations without the plugin
13
+ # actually executing any commands.
14
+ let(:backend) { stub }
15
+ before { SSHKit::Backend.stubs(:current).returns(backend) }
16
+
17
+ # Mimic the deploy flow tasks so that the plugin can register its hooks.
18
+ before do
19
+ Rake::Task.define_task("deploy:new_release_path")
20
+ Rake::Task.define_task("deploy:check")
21
+ Rake::Task.define_task("deploy:set_current_revision")
22
+ end
23
+
24
+ # Clean up any tasks or variables that the plugin defined.
25
+ after do
26
+ Rake::Task.clear
27
+ Capistrano::Configuration.reset!
28
+ end
29
+
30
+ describe "#git" do
31
+ it "should call execute git in the context, with arguments" do
32
+ backend.expects(:execute).with(:git, :init)
33
+ subject.git(:init)
34
+ end
35
+ end
36
+
37
+ describe "#repo_mirror_exists?" do
38
+ it "should call test for repo HEAD" do
39
+ env.set(:repo_path, "/path/to/repo")
40
+ backend.expects(:test).with " [ -f /path/to/repo/HEAD ] "
41
+
42
+ subject.repo_mirror_exists?
43
+ end
44
+ end
45
+
46
+ describe "#check_repo_is_reachable" do
47
+ it "should test the repo url" do
48
+ env.set(:repo_url, "url")
49
+ backend.expects(:execute).with(:git, :'ls-remote --heads', "url").returns(true)
50
+
51
+ subject.check_repo_is_reachable
52
+ end
53
+ end
54
+
55
+ describe "#clone_repo" do
56
+ it "should run git clone" do
57
+ env.set(:repo_url, "url")
58
+ env.set(:repo_path, "path")
59
+ backend.expects(:execute).with(:git, :clone, "--mirror", "url", "path")
60
+
61
+ subject.clone_repo
62
+ end
63
+
64
+ it "should run git clone in shallow mode" do
65
+ env.set(:git_shallow_clone, "1")
66
+ env.set(:repo_url, "url")
67
+ env.set(:repo_path, "path")
68
+
69
+ backend.expects(:execute).with(:git, :clone, "--mirror", "--depth", "1", "--no-single-branch", "url", "path")
70
+
71
+ subject.clone_repo
72
+ end
73
+ end
74
+
75
+ describe "#update_mirror" do
76
+ it "should run git update" do
77
+ backend.expects(:execute).with(:git, :remote, :update, "--prune")
78
+
79
+ subject.update_mirror
80
+ end
81
+
82
+ it "should run git update in shallow mode" do
83
+ env.set(:git_shallow_clone, "1")
84
+ env.set(:branch, "branch")
85
+ backend.expects(:execute).with(:git, :fetch, "--depth", "1", "origin", "branch")
86
+
87
+ subject.update_mirror
88
+ end
89
+ end
90
+
91
+ describe "#archive_to_release_path" do
92
+ it "should run git archive without a subtree" do
93
+ env.set(:branch, "branch")
94
+ env.set(:release_path, "path")
95
+
96
+ backend.expects(:execute).with(:git, :archive, "branch", "| /usr/bin/env tar -x -f - -C", "path")
97
+
98
+ subject.archive_to_release_path
99
+ end
100
+
101
+ it "should run git archive with a subtree" do
102
+ env.set(:repo_tree, "tree")
103
+ env.set(:branch, "branch")
104
+ env.set(:release_path, "path")
105
+
106
+ backend.expects(:execute).with(:git, :archive, "branch", "tree", "| /usr/bin/env tar -x --strip-components 1 -f - -C", "path")
107
+
108
+ subject.archive_to_release_path
109
+ end
110
+
111
+ it "should run tar with an overridden name" do
112
+ env.set(:branch, "branch")
113
+ env.set(:release_path, "path")
114
+ SSHKit.config.command_map.expects(:[]).with(:tar).returns("/usr/bin/env gtar")
115
+
116
+ backend.expects(:execute).with(:git, :archive, "branch", "| /usr/bin/env gtar -x -f - -C", "path")
117
+
118
+ subject.archive_to_release_path
119
+ end
120
+ end
121
+
122
+ describe "#fetch_revision" do
123
+ it "should capture git rev-list" do
124
+ env.set(:branch, "branch")
125
+ backend.expects(:capture).with(:git, "rev-list --max-count=1 branch").returns("81cec13b777ff46348693d327fc8e7832f79bf43")
126
+ revision = subject.fetch_revision
127
+ expect(revision).to eq("81cec13b777ff46348693d327fc8e7832f79bf43")
128
+ end
129
+ end
130
+ end
131
+ end