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.
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