capistrano 3.0.0.pre14 → 3.0.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -0
  3. data/README.md +1 -1
  4. data/bin/cap +1 -1
  5. data/capistrano.gemspec +3 -0
  6. data/features/deploy.feature +52 -0
  7. data/features/installation.feature +16 -0
  8. data/features/remote_file_task.feature +14 -0
  9. data/features/step_definitions/assertions.rb +90 -0
  10. data/features/step_definitions/cap_commands.rb +8 -0
  11. data/features/step_definitions/setup.rb +25 -0
  12. data/features/support/env.rb +12 -0
  13. data/features/support/remote_command_helpers.rb +20 -0
  14. data/lib/Capfile +1 -0
  15. data/lib/capistrano.rb +0 -14
  16. data/lib/capistrano/all.rb +16 -0
  17. data/lib/capistrano/application.rb +1 -10
  18. data/lib/capistrano/configuration.rb +4 -0
  19. data/lib/capistrano/configuration/server.rb +44 -6
  20. data/lib/capistrano/configuration/servers.rb +14 -51
  21. data/lib/capistrano/configuration/servers/role_filter.rb +86 -0
  22. data/lib/capistrano/defaults.rb +0 -8
  23. data/lib/capistrano/dsl.rb +1 -1
  24. data/lib/capistrano/dsl/env.rb +6 -2
  25. data/lib/capistrano/dsl/paths.rb +7 -4
  26. data/lib/capistrano/dsl/task_enhancements.rb +38 -0
  27. data/lib/capistrano/hg.rb +1 -0
  28. data/lib/capistrano/i18n.rb +1 -1
  29. data/lib/capistrano/setup.rb +7 -3
  30. data/lib/capistrano/tasks/deploy.rake +39 -9
  31. data/lib/capistrano/tasks/framework.rake +0 -2
  32. data/lib/capistrano/tasks/git.rake +3 -6
  33. data/lib/capistrano/tasks/hg.rake +39 -0
  34. data/lib/capistrano/templates/Capfile +2 -23
  35. data/lib/capistrano/templates/deploy.rb.erb +23 -0
  36. data/lib/capistrano/templates/stage.rb.erb +1 -1
  37. data/lib/capistrano/version.rb +1 -1
  38. data/spec/integration/dsl_spec.rb +71 -0
  39. data/spec/lib/capistrano/configuration/server_spec.rb +69 -0
  40. data/spec/lib/capistrano/configuration/servers/role_filter_spec.rb +140 -0
  41. data/spec/lib/capistrano/configuration/servers_spec.rb +46 -9
  42. data/spec/lib/capistrano/configuration_spec.rb +11 -0
  43. data/spec/spec_helper.rb +1 -2
  44. data/spec/support/.gitignore +1 -0
  45. data/spec/support/Vagrantfile +13 -0
  46. data/spec/support/tasks/database.cap +11 -0
  47. data/spec/support/test_app.rb +55 -6
  48. metadata +74 -16
  49. data/lib/capistrano/bundler.rb +0 -1
  50. data/lib/capistrano/tasks/bundler.rake +0 -13
  51. data/spec/integration/deploy_finalize_spec.rb +0 -34
  52. data/spec/integration/deploy_finished_spec.rb +0 -36
  53. data/spec/integration/deploy_started_spec.rb +0 -74
  54. data/spec/integration/deploy_update_spec.rb +0 -45
  55. data/spec/integration/installation_spec.rb +0 -76
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8d396873548e6dd9e20c1853f741bc8808e7a529
4
- data.tar.gz: 24aa535d127498013298938e5effb7e38bd26fbb
3
+ metadata.gz: 6e84be755bb1beb1fa002d555a2a237a569fe0b0
4
+ data.tar.gz: 2fdcff3917f21ed061bc94fa74d09fb06e4b8bd0
5
5
  SHA512:
6
- metadata.gz: 828006f69722330dcfbf09833922f0547a00fde78bd2d59948b4ebd59b139afa779f69c87e7d69e22e1fff7e9377d84484594dc5edaa544919a644c39d9d9338
7
- data.tar.gz: 8cfb03d51c92cac8ab9c6bd8cd7ba4d3416731de893927db8ab1b0117e5478af71c4e9256aaea8350a7cf23f663432ae1f7b1b19b5cad80e10890a607bb4c245
6
+ metadata.gz: 9d330918070791f930fc5254574f633ec354b87ebd2b194b16392771f1d135c1d1352f412ca915e8c194b8776fa0b820e023f88829782807bb2c4d41cf37981d
7
+ data.tar.gz: bd9b0c4d70a9b420decc32592d7fd5d59e93d40e01558318e5f969dfb5add69ccb813a10a3518224940d8da6f40f1d6e30699e072ada18b97925a08aaa6426a5
data/CHANGELOG.md CHANGED
@@ -2,6 +2,48 @@
2
2
 
3
3
  Reverse Chronological Order:
4
4
 
5
+ ## `3.0.0`
6
+
7
+ If you are coming here to wonder why your Capfile doesn't work anymore, please
8
+ vendor lock your Capistrano at 2.5.x, whichever version was working for you
9
+ until today.
10
+
11
+ Capistrano 3 is a ground-up rewrite with modularity, stability, speed and
12
+ future proofing in mind. It's a big change, but now the code is 10x smaller,
13
+ runs faster, is easier to read, and quicker to extend. In the reduction we've
14
+ come up with a great gem based modular system for plugins and we're really
15
+ proud of this release.
16
+
17
+ The 3.0.0 release contains 38 patches from the following amazing people:
18
+
19
+ * Tom `seenmyfate` Clements: more than 28 patches including cucumber integration tests! Not to
20
+ mention Rails asset pipeline code, and bundler integrations.
21
+ * Lee Hambley: Small changes around compatibility and log formatting
22
+ * Kir Shatrov: for improvements in the core to make it easier to write extensions, for
23
+ improving documentation, and for effectively building the chruby, rvm and rbenv integrations.
24
+ * Michael Nikitochkin: Fixing a bug around linked files and directories.
25
+ * Jack Thorne: for improvements to the default `Capfile` to fix some bad example syntax.
26
+ * Erik Hetzner: for (what looks like great) work on the Mercurial (Hg) support. The Hg and Git
27
+ source control mechanisms do not work the same way, but rather lean on the strengths of the
28
+ underlying tools.
29
+
30
+ (If I missed anyone, I'm sorry, your contributions have been awesome)
31
+
32
+ The 2.x branch of code is now no longer maintained. Towards the end of it's
33
+ useful life there were an increasing number of features and pieces of code
34
+ which didn't make sense for certain groups of people, in certain situations,
35
+ leading a to a ping-pong tennis effect with pull requests every few weeks
36
+ "fixing" a use-case which had already been "fixed" shortly before. As many of
37
+ the use-cases are outside the scope of the testing environments I (and by
38
+ extension the trusted contributors and IRC regulars) were able to test for.
39
+
40
+ There's a more extensive post about my failure to be able to keep up with the
41
+ demands of maintaining v2 whilst trying to build something which is appropriate
42
+ for the current landscape. If you are affected by the unsupported 2 branch,
43
+ please contact me (Lee Hambley) to dicsuss how my company can help support you.
44
+ Otherwise, please try v3, we're sure you'll like it, and the code is designed
45
+ to be so simple that anyone can work on it.
46
+
5
47
  ## `3.0.0.pre14`
6
48
 
7
49
  * Thanks to numerous contributors, in particular (@teohm) for a series of improvements.
data/README.md CHANGED
@@ -19,7 +19,7 @@ $ bundle --binstubs
19
19
  ```
20
20
 
21
21
  Capify:
22
- *make sure there's no "Capfile" or "capfile" present*
22
+ *make sure there's no "Capfile" or "capfile" present*
23
23
  ``` shell
24
24
  $ cap install
25
25
  ```
data/bin/cap CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env ruby
2
- require 'capistrano'
2
+ require 'capistrano/all'
3
3
  Capistrano::Application.new.run
data/capistrano.gemspec CHANGED
@@ -28,5 +28,8 @@ Gem::Specification.new do |gem|
28
28
 
29
29
  gem.add_development_dependency 'rspec'
30
30
  gem.add_development_dependency 'mocha'
31
+ gem.add_development_dependency 'vagrant', '~> 1.0.7'
32
+ gem.add_development_dependency 'kuroko'
33
+ gem.add_development_dependency 'cucumber'
31
34
 
32
35
  end
@@ -0,0 +1,52 @@
1
+ Feature: Deploy
2
+
3
+ Background:
4
+ Given a test app with the default configuration
5
+ And servers with the roles app and web
6
+
7
+ Scenario: Creating the repo
8
+ When I run cap "git:check"
9
+ Then references in the remote repo are listed
10
+
11
+ Scenario: Creating the directory structure
12
+ When I run cap "deploy:check:directories"
13
+ Then the shared path is created
14
+ And the releases path is created
15
+
16
+ Scenario: Creating linked directories
17
+ When I run cap "deploy:check:linked_dirs"
18
+ Then directories in :linked_dirs are created in shared
19
+
20
+ Scenario: Creating linked directories for linked files
21
+ When I run cap "deploy:check:make_linked_dirs"
22
+ Then directories referenced in :linked_files are created in shared
23
+
24
+ Scenario: Checking linked files - missing file
25
+ Given a required file
26
+ But the file does not exist
27
+ When I run cap "deploy:check:linked_files"
28
+ Then the task will exit
29
+
30
+ Scenario: Checking linked files - file exists
31
+ Given a required file
32
+ And that file exists
33
+ When I run cap "deploy:check:linked_files"
34
+ Then the task will be successful
35
+
36
+ Scenario: Creating a release
37
+ When I run cap "git:create_release" as part of a release
38
+ Then the repo is cloned
39
+ And the release is created
40
+
41
+ Scenario: Symlink linked files
42
+ When I run cap "deploy:symlink:linked_files" as part of a release
43
+ Then file symlinks are created in the new release
44
+
45
+ Scenario: Symlink linked dirs
46
+ When I run cap "deploy:symlink:linked_dirs" as part of a release
47
+ Then directory symlinks are created in the new release
48
+
49
+ Scenario: Publishing
50
+ When I run cap "deploy:symlink:release"
51
+ Then the current directory will be a symlink to the release
52
+
@@ -0,0 +1,16 @@
1
+ Feature: Installation
2
+
3
+ Background:
4
+ Given a test app with the default configuration
5
+
6
+ Scenario: With default stages
7
+ When I run cap "install"
8
+ Then the deploy.rb file is created
9
+ And the default stage files are created
10
+ And the tasks folder is created
11
+
12
+ Scenario: With specified stages
13
+ When I run cap "install STAGES=qa,production"
14
+ Then the deploy.rb file is created
15
+ And the specified stage files are created
16
+ And the tasks folder is created
@@ -0,0 +1,14 @@
1
+ Feature: Remote file task
2
+
3
+ Background:
4
+ Given a test app with the default configuration
5
+ And a custom task to generate a file
6
+ And servers with the roles app and web
7
+
8
+ Scenario: Where the file does not exist
9
+ When I run cap "deploy:check:linked_files"
10
+ Then it creates the file with the remote_task prerequisite
11
+
12
+ Scenario: Where the file already exists
13
+ When I run cap "deploy:check:linked_files"
14
+ Then it will not recreate the file
@@ -0,0 +1,90 @@
1
+ Then(/^references in the remote repo are listed$/) do
2
+ end
3
+
4
+ Then(/^the shared path is created$/) do
5
+ run_vagrant_command(test_dir_exists(TestApp.shared_path))
6
+ end
7
+
8
+ Then(/^the releases path is created$/) do
9
+ run_vagrant_command(test_dir_exists(TestApp.releases_path))
10
+ end
11
+
12
+ Then(/^directories in :linked_dirs are created in shared$/) do
13
+ TestApp.linked_dirs.each do |dir|
14
+ run_vagrant_command(test_dir_exists(TestApp.shared_path.join(dir)))
15
+ end
16
+ end
17
+
18
+ Then(/^directories referenced in :linked_files are created in shared$/) do
19
+ dirs = TestApp.linked_files.map { |path| TestApp.shared_path.join(path).dirname }
20
+ dirs.each do | dir|
21
+ run_vagrant_command(test_dir_exists(dir))
22
+ end
23
+ end
24
+
25
+ Then(/^the task will be successful$/) do
26
+ end
27
+
28
+
29
+ Then(/^the task will exit$/) do
30
+ end
31
+
32
+ Then(/^the repo is cloned$/) do
33
+ run_vagrant_command(test_dir_exists(TestApp.repo_path))
34
+ end
35
+
36
+ Then(/^the release is created$/) do
37
+ run_vagrant_command("ls -g #{TestApp.releases_path}")
38
+ end
39
+
40
+ Then(/^file symlinks are created in the new release$/) do
41
+ pending
42
+ TestApp.linked_files.each do |file|
43
+ run_vagrant_command(test_symlink_exists(TestApp.release_path.join(file)))
44
+ end
45
+ end
46
+
47
+ Then(/^directory symlinks are created in the new release$/) do
48
+ pending
49
+ TestApp.linked_dirs.each do |dir|
50
+ run_vagrant_command(test_symlink_exists(TestApp.release_path.join(dir)))
51
+ end
52
+ end
53
+
54
+ Then(/^the current directory will be a symlink to the release$/) do
55
+ run_vagrant_command(test_symlink_exists(TestApp.current_path))
56
+ end
57
+
58
+ Then(/^the deploy\.rb file is created$/) do
59
+ file = TestApp.test_app_path.join('config/deploy.rb')
60
+ expect(File.exists?(file)).to be_true
61
+ end
62
+
63
+ Then(/^the default stage files are created$/) do
64
+ staging = TestApp.test_app_path.join('config/deploy/staging.rb')
65
+ production = TestApp.test_app_path.join('config/deploy/production.rb')
66
+ expect(File.exists?(staging)).to be_true
67
+ expect(File.exists?(production)).to be_true
68
+ end
69
+
70
+ Then(/^the tasks folder is created$/) do
71
+ path = TestApp.test_app_path.join('lib/capistrano/tasks')
72
+ expect(Dir.exists?(path)).to be_true
73
+ end
74
+
75
+ Then(/^the specified stage files are created$/) do
76
+ qa = TestApp.test_app_path.join('config/deploy/qa.rb')
77
+ production = TestApp.test_app_path.join('config/deploy/production.rb')
78
+ expect(File.exists?(qa)).to be_true
79
+ expect(File.exists?(production)).to be_true
80
+ end
81
+
82
+ Then(/^it creates the file with the remote_task prerequisite$/) do
83
+ TestApp.linked_files.each do |file|
84
+ run_vagrant_command(test_file_exists(TestApp.shared_path.join(file)))
85
+ end
86
+ end
87
+
88
+ Then(/^it will not recreate the file$/) do
89
+ #
90
+ end
@@ -0,0 +1,8 @@
1
+ When(/^I run cap "(.*?)"$/) do |task|
2
+ TestApp.cap(task)
3
+ end
4
+
5
+ When(/^I run cap "(.*?)" as part of a release$/) do |task|
6
+ TestApp.cap("deploy:new_release_path #{task}")
7
+ end
8
+
@@ -0,0 +1,25 @@
1
+ Given(/^a test app with the default configuration$/) do
2
+ TestApp.install
3
+ end
4
+
5
+ Given(/^servers with the roles app and web$/) do
6
+ vagrant_cli_command('up')
7
+ end
8
+
9
+ Given(/^a required file$/) do
10
+ end
11
+
12
+ Given(/^that file exists$/) do
13
+ run_vagrant_command("touch #{TestApp.linked_file}")
14
+ end
15
+
16
+ Given(/^the file does not exist$/) do
17
+ pending
18
+ file = TestApp.linked_file
19
+ run_vagrant_command("[ -f #{file} ] && rm #{file}")
20
+ end
21
+
22
+ Given(/^a custom task to generate a file$/) do
23
+ TestApp.copy_task_to_test_app('spec/support/tasks/database.cap')
24
+ end
25
+
@@ -0,0 +1,12 @@
1
+ require 'kuroko'
2
+
3
+ project_root = File.expand_path('../../../', __FILE__)
4
+ vagrant_root = File.join(project_root, 'spec/support')
5
+
6
+ Kuroko.configure do |config|
7
+ config.vagrant_root = 'spec/support'
8
+ end
9
+
10
+ puts vagrant_root.inspect
11
+
12
+ require_relative '../../spec/support/test_app'
@@ -0,0 +1,20 @@
1
+ module RemoteCommandHelpers
2
+
3
+ def test_dir_exists(path)
4
+ exists?('d', path)
5
+ end
6
+
7
+ def test_symlink_exists(path)
8
+ exists?('L', path)
9
+ end
10
+
11
+ def test_file_exists(path)
12
+ exists?('f', path)
13
+ end
14
+
15
+ def exists?(type, path)
16
+ %{[ -#{type} "#{path}" ] && echo "#{path} exists." || echo "Error: #{path} does not exist."}
17
+ end
18
+ end
19
+
20
+ World(RemoteCommandHelpers)
data/lib/Capfile CHANGED
@@ -1,2 +1,3 @@
1
1
  #!/usr/bin/env cap
2
+ include Capistrano::DSL
2
3
  require 'capistrano/install'
data/lib/capistrano.rb CHANGED
@@ -1,14 +0,0 @@
1
- require 'rake'
2
- require 'sshkit'
3
-
4
- Rake.application.options.trace = true
5
-
6
- require 'capistrano/version'
7
- require 'capistrano/version_validator'
8
- require 'capistrano/i18n'
9
- require 'capistrano/dsl'
10
- require 'capistrano/application'
11
- require 'capistrano/configuration'
12
-
13
- module Capistrano
14
- end
@@ -0,0 +1,16 @@
1
+ require 'rake'
2
+ require 'sshkit'
3
+ require 'sshkit/dsl'
4
+
5
+ Rake.application.options.trace = true
6
+
7
+ require 'capistrano/version'
8
+ require 'capistrano/version_validator'
9
+ require 'capistrano/i18n'
10
+ require 'capistrano/dsl'
11
+ require 'capistrano/application'
12
+ require 'capistrano/configuration'
13
+
14
+ module Capistrano
15
+
16
+ end
@@ -26,7 +26,7 @@ module Capistrano
26
26
  if tasks_without_stage_dependency.include?(@top_level_tasks.first)
27
27
  @top_level_tasks
28
28
  else
29
- @top_level_tasks.unshift('deploy:ensure_stage')
29
+ @top_level_tasks.unshift(ensure_stage)
30
30
  end
31
31
  end
32
32
 
@@ -37,15 +37,6 @@ module Capistrano
37
37
  File.expand_path(File.join(File.dirname(__FILE__),'..','Capfile'))
38
38
  end
39
39
 
40
- def tasks_without_stage_dependency
41
- defined_stages = Dir['config/deploy/*.rb'].map { |f| File.basename(f, '.rb') }
42
- defined_stages + default_tasks
43
- end
44
-
45
- def default_tasks
46
- %w{install}
47
- end
48
-
49
40
  def version
50
41
  ['--version', '-V',
51
42
  "Display the program version.",
@@ -20,6 +20,10 @@ module Capistrano
20
20
  config[key] = value
21
21
  end
22
22
 
23
+ def delete(key)
24
+ config.delete(key)
25
+ end
26
+
23
27
  def fetch(key, default=nil, &block)
24
28
  value = fetch_for(key, default, &block)
25
29
  if value.respond_to?(:call)
@@ -22,6 +22,11 @@ module Capistrano
22
22
  hostname == Server.new(host).hostname
23
23
  end
24
24
 
25
+ def select?(options)
26
+ selector = Selector.new(options)
27
+ selector.call(self)
28
+ end
29
+
25
30
  def primary
26
31
  self if fetch(:primary)
27
32
  end
@@ -41,6 +46,20 @@ module Capistrano
41
46
  alias_method :netssh_options_without_options, :netssh_options
42
47
  alias_method :netssh_options, :netssh_options_with_options
43
48
 
49
+ def roles_array
50
+ roles.to_a
51
+ end
52
+
53
+ private
54
+
55
+ def add_property(key, value)
56
+ if respond_to?("#{key}=")
57
+ send("#{key}=", value)
58
+ else
59
+ set(key, value)
60
+ end
61
+ end
62
+
44
63
  class Properties
45
64
 
46
65
  def initialize
@@ -79,15 +98,34 @@ module Capistrano
79
98
 
80
99
  end
81
100
 
101
+ class Selector
102
+ def initialize(options)
103
+ @options = options
104
+ end
82
105
 
83
- private
106
+ def callable
107
+ if key.respond_to?(:call)
108
+ key
109
+ else
110
+ ->(server) { server.fetch(key) }
111
+ end
112
+ end
84
113
 
85
- def add_property(key, value)
86
- if respond_to?("#{key}=")
87
- send("#{key}=", value)
88
- else
89
- set(key, value)
114
+ def call(server)
115
+ callable.call(server)
90
116
  end
117
+
118
+ private
119
+ attr_reader :options
120
+
121
+ def key
122
+ options[:filter] || options[:select] || all
123
+ end
124
+
125
+ def all
126
+ ->(server) { :all }
127
+ end
128
+
91
129
  end
92
130
 
93
131
  end