engineyard-serverside 1.6.5 → 1.7.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. data/lib/engineyard-serverside.rb +2 -0
  2. data/lib/engineyard-serverside/cli.rb +83 -48
  3. data/lib/engineyard-serverside/configuration.rb +85 -18
  4. data/lib/engineyard-serverside/deploy.rb +105 -91
  5. data/lib/engineyard-serverside/deploy_hook.rb +22 -20
  6. data/lib/engineyard-serverside/deprecation.rb +9 -17
  7. data/lib/engineyard-serverside/future.rb +10 -4
  8. data/lib/engineyard-serverside/futures/celluloid.rb +3 -13
  9. data/lib/engineyard-serverside/futures/dataflow.rb +8 -13
  10. data/lib/engineyard-serverside/lockfile_parser.rb +1 -1
  11. data/lib/engineyard-serverside/rails_asset_support.rb +26 -10
  12. data/lib/engineyard-serverside/server.rb +17 -12
  13. data/lib/engineyard-serverside/shell.rb +98 -0
  14. data/lib/engineyard-serverside/shell/formatter.rb +71 -0
  15. data/lib/engineyard-serverside/shell/helpers.rb +29 -0
  16. data/lib/engineyard-serverside/strategies/git.rb +33 -63
  17. data/lib/engineyard-serverside/task.rb +34 -13
  18. data/lib/engineyard-serverside/version.rb +1 -1
  19. data/spec/basic_deploy_spec.rb +15 -50
  20. data/spec/bundler_deploy_spec.rb +3 -44
  21. data/spec/configuration_spec.rb +72 -0
  22. data/spec/custom_deploy_spec.rb +3 -4
  23. data/spec/deploy_hook_spec.rb +210 -162
  24. data/spec/deprecation_spec.rb +4 -26
  25. data/spec/ey_yml_customized_deploy_spec.rb +68 -0
  26. data/spec/fixtures/repos/assets_disabled/Gemfile +6 -0
  27. data/spec/fixtures/repos/assets_disabled/Gemfile.lock +90 -0
  28. data/spec/fixtures/repos/assets_disabled/README +1 -0
  29. data/spec/fixtures/repos/assets_disabled/Rakefile +5 -0
  30. data/spec/fixtures/repos/assets_disabled/config/application.rb +5 -0
  31. data/spec/fixtures/repos/assets_disabled_in_ey_yml/Gemfile +6 -0
  32. data/spec/fixtures/repos/assets_disabled_in_ey_yml/Gemfile.lock +90 -0
  33. data/spec/fixtures/repos/assets_disabled_in_ey_yml/README +1 -0
  34. data/spec/fixtures/repos/assets_disabled_in_ey_yml/Rakefile +5 -0
  35. data/spec/fixtures/repos/assets_disabled_in_ey_yml/config/application.rb +5 -0
  36. data/spec/fixtures/repos/assets_disabled_in_ey_yml/config/ey.yml +4 -0
  37. data/spec/fixtures/repos/assets_enabled/Gemfile +6 -0
  38. data/spec/fixtures/repos/assets_enabled/Gemfile.lock +90 -0
  39. data/spec/fixtures/repos/assets_enabled/README +1 -0
  40. data/spec/fixtures/repos/assets_enabled/Rakefile +5 -0
  41. data/spec/fixtures/repos/assets_enabled/config/application.rb +5 -0
  42. data/spec/fixtures/repos/assets_enabled_in_ey_yml/README +1 -0
  43. data/spec/fixtures/repos/assets_enabled_in_ey_yml/Rakefile +5 -0
  44. data/spec/fixtures/repos/assets_enabled_in_ey_yml/config/ey.yml +4 -0
  45. data/spec/fixtures/repos/assets_in_hook/Gemfile +6 -0
  46. data/spec/fixtures/repos/assets_in_hook/Gemfile.lock +90 -0
  47. data/spec/fixtures/repos/assets_in_hook/README +2 -0
  48. data/spec/fixtures/repos/assets_in_hook/Rakefile +5 -0
  49. data/spec/fixtures/repos/assets_in_hook/config/application.rb +5 -0
  50. data/spec/fixtures/repos/assets_in_hook/deploy/before_migrate.rb +1 -0
  51. data/spec/fixtures/repos/default/Gemfile +5 -0
  52. data/spec/fixtures/repos/default/Gemfile.lock +14 -0
  53. data/spec/fixtures/repos/default/README +5 -0
  54. data/spec/fixtures/repos/ey_yml/Gemfile +4 -0
  55. data/spec/fixtures/repos/ey_yml/Gemfile.lock +12 -0
  56. data/spec/fixtures/repos/ey_yml/README +1 -0
  57. data/spec/fixtures/repos/ey_yml/config/ey.yml +12 -0
  58. data/spec/fixtures/repos/ey_yml/deploy/before_migrate.rb +6 -0
  59. data/spec/fixtures/repos/ey_yml_alt/Gemfile +4 -0
  60. data/spec/fixtures/repos/ey_yml_alt/Gemfile.lock +12 -0
  61. data/spec/fixtures/repos/ey_yml_alt/README +1 -0
  62. data/spec/fixtures/repos/ey_yml_alt/deploy/before_migrate.rb +6 -0
  63. data/spec/fixtures/repos/ey_yml_alt/ey.yml +12 -0
  64. data/spec/fixtures/repos/hook_fails/README +1 -0
  65. data/spec/fixtures/repos/hook_fails/deploy/before_migrate.rb +1 -0
  66. data/spec/fixtures/repos/hooks/README +1 -0
  67. data/spec/fixtures/repos/hooks/deploy/after_bundle.rb +1 -0
  68. data/spec/fixtures/repos/hooks/deploy/after_compile_assets.rb +1 -0
  69. data/spec/fixtures/repos/hooks/deploy/after_migrate.rb +1 -0
  70. data/spec/fixtures/repos/hooks/deploy/after_restart.rb +1 -0
  71. data/spec/fixtures/repos/hooks/deploy/after_symlink.rb +1 -0
  72. data/spec/fixtures/repos/hooks/deploy/before_bundle.rb +1 -0
  73. data/spec/fixtures/repos/hooks/deploy/before_compile_assets.rb +1 -0
  74. data/spec/fixtures/repos/hooks/deploy/before_migrate.rb +1 -0
  75. data/spec/fixtures/repos/hooks/deploy/before_restart.rb +1 -0
  76. data/spec/fixtures/repos/hooks/deploy/before_symlink.rb +1 -0
  77. data/spec/fixtures/repos/no_ey_config/Gemfile +4 -0
  78. data/spec/fixtures/repos/no_ey_config/Gemfile.lock +12 -0
  79. data/spec/fixtures/repos/no_ey_config/README +1 -0
  80. data/spec/fixtures/repos/no_gemfile_lock/Gemfile +5 -0
  81. data/spec/fixtures/repos/no_gemfile_lock/README +1 -0
  82. data/spec/fixtures/repos/nodejs/README +1 -0
  83. data/spec/fixtures/repos/nodejs/package.json +7 -0
  84. data/spec/fixtures/repos/not_bundled/README +1 -0
  85. data/spec/fixtures/{gemfiles/1.0.21-rails-31-with-sqlite → repos/sqlite3/Gemfile} +0 -0
  86. data/spec/fixtures/{lockfiles/1.0.21-rails-31-with-sqlite → repos/sqlite3/Gemfile.lock} +0 -0
  87. data/spec/fixtures/repos/sqlite3/README +1 -0
  88. data/spec/git_strategy_spec.rb +11 -2
  89. data/spec/lockfile_parser_spec.rb +8 -3
  90. data/spec/nodejs_deploy_spec.rb +1 -26
  91. data/spec/rails31_deploy_spec.rb +23 -31
  92. data/spec/services_deploy_spec.rb +41 -100
  93. data/spec/shell_spec.rb +50 -0
  94. data/spec/spec_helper.rb +80 -66
  95. data/spec/sqlite3_deploy_spec.rb +10 -16
  96. data/spec/support/integration.rb +45 -139
  97. metadata +233 -78
  98. data/lib/engineyard-serverside/logged_output.rb +0 -91
  99. data/spec/logged_output_spec.rb +0 -55
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ describe EY::Serverside::Deploy::Configuration do
4
+ describe "ey.yml loading" do
5
+ before(:each) do
6
+ @tempdir = `mktemp -d -t ey_yml_spec.XXXXX`.strip
7
+ @config = EY::Serverside::Deploy::Configuration.new({
8
+ 'repository_cache' => @tempdir,
9
+ 'environment_name' => 'env_name',
10
+ 'account_name' => 'acc',
11
+ 'migrate' => nil,
12
+ 'branch' => 'branch_from_command_line',
13
+ 'config' => {'custom' => 'custom_from_extra_config'}.to_json
14
+ })
15
+
16
+ @deploy = FullTestDeploy.new(@config, test_shell)
17
+
18
+ @yaml_data = {
19
+ 'environments' => {
20
+ 'env_name' => {
21
+ 'copy_exclude' => ['.git'],
22
+ 'migrate' => true,
23
+ 'migration_command' => 'uh oh',
24
+ 'branch' => 'branch_from_ey_yml',
25
+ 'custom' => 'custom_from_ey_yml',
26
+ 'bundle_without' => 'only test',
27
+ }
28
+ }
29
+ }
30
+ end
31
+
32
+ def write_ey_yml(relative_path, data)
33
+ FileUtils.mkdir_p(File.join(
34
+ @tempdir,
35
+ File.dirname(relative_path)))
36
+
37
+ File.open(File.join(@tempdir, relative_path), 'w') do |f|
38
+ f.write data.to_yaml
39
+ end
40
+ end
41
+
42
+ it "requires 'ey.yml' and adds any defined methods to the deploy" do
43
+ write_ey_yml 'ey.yml', @yaml_data
44
+ @deploy.load_ey_yml
45
+ @deploy.config.copy_exclude.should == ['.git']
46
+ end
47
+
48
+ it "falls back to 'config/ey.yml'" do
49
+ write_ey_yml 'config/ey.yml', @yaml_data
50
+ @deploy.load_ey_yml
51
+ @deploy.config.copy_exclude.should == ['.git']
52
+ end
53
+
54
+ it "loads at lower priority than command line options" do
55
+ write_ey_yml 'ey.yml', @yaml_data
56
+ @deploy.load_ey_yml
57
+ @deploy.config.migrate?.should == false
58
+ end
59
+
60
+ it "loads at lower priority than json config option" do
61
+ write_ey_yml 'ey.yml', @yaml_data
62
+ @deploy.load_ey_yml
63
+ @deploy.config.branch.should == 'branch_from_command_line'
64
+ end
65
+
66
+ it "loads bundle_without from the config, which overrides the default" do
67
+ write_ey_yml 'ey.yml', @yaml_data
68
+ @deploy.load_ey_yml
69
+ @deploy.config.bundle_without.should == 'only test'
70
+ end
71
+ end
72
+ end
@@ -11,7 +11,6 @@ describe "the EY::Serverside::Deploy API" do
11
11
  # cheat a bit; we don't actually want to do these things
12
12
  def require_custom_tasks() end
13
13
  def callback(*_) end
14
- def puts(*_) 'stfu' end
15
14
 
16
15
  attr_reader :call_order
17
16
  def initialize(*a)
@@ -34,7 +33,7 @@ describe "the EY::Serverside::Deploy API" do
34
33
  def disable_maintenance_page() @call_order << 'disable_maintenance_page' end
35
34
  end
36
35
 
37
- td = TestDeploy.new(EY::Serverside::Deploy::Configuration.new)
36
+ td = TestDeploy.new(EY::Serverside::Deploy::Configuration.new, test_shell)
38
37
  td.deploy
39
38
  td.call_order.should == %w(
40
39
  push_code
@@ -60,7 +59,7 @@ describe "the EY::Serverside::Deploy API" do
60
59
  before(:each) do
61
60
  @tempdir = `mktemp -d -t custom_deploy_spec.XXXXX`.strip
62
61
  @config = EY::Serverside::Deploy::Configuration.new('repository_cache' => @tempdir)
63
- @deploy = TestQuietDeploy.new(@config)
62
+ @deploy = TestQuietDeploy.new(@config, test_shell)
64
63
  end
65
64
 
66
65
  def write_eydeploy(relative_path, contents = "def got_new_methods() 'from the file on disk' end")
@@ -92,7 +91,7 @@ describe "the EY::Serverside::Deploy API" do
92
91
  def value() 'base' end
93
92
  end
94
93
 
95
- deploy = TestDeploySuper.new(@config)
94
+ deploy = TestDeploySuper.new(@config, test_shell)
96
95
  deploy.require_custom_tasks.should be_true
97
96
  deploy.value.should == "base + derived"
98
97
  end
@@ -1,213 +1,261 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "the deploy-hook API" do
4
- def deploy_hook(options={})
5
- EY::Serverside::DeployHook.new(options)
6
- end
3
+ describe "deploy hooks" do
4
+ context "successful deploy with all hooks" do
5
+ before(:all) do
6
+ deploy_test_application('hooks')
7
+ end
7
8
 
8
- def run_hook(options={}, &blk)
9
- raise ArgumentError unless block_given?
10
- # The hooks on the filesystem are run by passing a string to
11
- # context.instance_eval, not a block. However, using a block
12
- # should allow us to get the same degree of test coverage and
13
- # still let us have things like syntax checking work on this spec
14
- # file.
15
- deploy_hook(options).callback_context.instance_eval(&blk)
9
+ it "runs all the hooks" do
10
+ @deploy_dir.join('current', 'before_bundle.ran' ).should exist
11
+ @deploy_dir.join('current', 'after_bundle.ran' ).should exist
12
+ @deploy_dir.join('current', 'before_migrate.ran').should exist
13
+ @deploy_dir.join('current', 'after_migrate.ran' ).should exist
14
+ @deploy_dir.join('current', 'before_compile_assets.ran').should exist
15
+ @deploy_dir.join('current', 'after_compile_assets.ran' ).should exist
16
+ @deploy_dir.join('current', 'before_symlink.ran').should exist
17
+ @deploy_dir.join('current', 'after_symlink.ran' ).should exist
18
+ @deploy_dir.join('current', 'before_restart.ran').should exist
19
+ @deploy_dir.join('current', 'after_restart.ran' ).should exist
20
+ end
16
21
  end
17
22
 
18
- context "#run" do
19
- it "is available" do
20
- run_hook { respond_to?(:run) }.should be_true
23
+ context "with failing deploy hook" do
24
+ before(:all) do
25
+ begin
26
+ deploy_test_application('hook_fails')
27
+ rescue EY::Serverside::RemoteFailure
28
+ end
21
29
  end
22
30
 
23
- it "runs commands like the shell does" do
24
- ENV['COUNT'] = 'Chocula'
25
- File.unlink("/tmp/deploy_hook_spec.the_count") rescue nil
31
+ it "retains the failed release" do
32
+ release_name = File.basename(@config.release_path)
33
+ @deploy_dir.join('releases_failed', release_name).should be_directory
34
+ end
35
+ end
26
36
 
27
- run_hook { run("echo $COUNT > /tmp/deploy_hook_spec.the_count") }
37
+ context "deploy hook API" do
28
38
 
29
- IO.read("/tmp/deploy_hook_spec.the_count").strip.should == "Chocula"
39
+ def deploy_hook(options={})
40
+ config = EY::Serverside::Deploy::Configuration.new(options)
41
+ EY::Serverside::DeployHook.new(config, test_shell)
30
42
  end
31
43
 
32
- it "returns true/false to indicate the command's success" do
33
- run_hook { run("true") }.should be_true
34
- run_hook { run("false") }.should be_false
35
- end
36
- end
44
+ context "#run" do
45
+ it "is available" do
46
+ deploy_hook.eval_hook('respond_to?(:run)').should be_true
47
+ end
37
48
 
38
- context "#sudo" do
39
- it "is available" do
40
- run_hook { respond_to?(:sudo) }.should be_true
41
- end
49
+ it "runs commands like the shell does" do
50
+ ENV['COUNT'] = 'Chocula'
51
+ File.unlink("/tmp/deploy_hook_spec.the_count") rescue nil
42
52
 
43
- it "runs things with sudo" do
44
- callback = deploy_hook.callback_context
45
- callback.should_receive(:system).with("sudo sh -l -c 'do it as root'").and_return(true)
46
- callback.instance_eval { sudo("do it as root") }
47
- end
48
- end
53
+ deploy_hook.eval_hook('run("echo $COUNT > /tmp/deploy_hook_spec.the_count")')
49
54
 
50
- context "capistrano-ish methods" do
51
- it "has them" do
52
- run_hook { respond_to?(:latest_release) }.should be_true
53
- run_hook { respond_to?(:previous_release) }.should be_true
54
- run_hook { respond_to?(:all_releases) }.should be_true
55
- run_hook { respond_to?(:current_path) }.should be_true
56
- run_hook { respond_to?(:shared_path) }.should be_true
57
- run_hook { respond_to?(:release_dir) }.should be_true
58
- run_hook { respond_to?(:failed_release_dir)}.should be_true
59
- run_hook { respond_to?(:release_path) }.should be_true
60
- end
61
- end
55
+ IO.read("/tmp/deploy_hook_spec.the_count").strip.should == "Chocula"
56
+ end
62
57
 
63
- context "the @node ivar" do
64
- before(:each) do
65
- EY::Serverside.dna_json = {
66
- 'instance_role' => 'solo',
67
- 'applications' => {
68
- 'myapp' => {
69
- 'type' => 'rails',
70
- 'branch' => 'master',
71
- }
72
- }
73
- }.to_json
58
+ it "returns true/false to indicate the command's success" do
59
+ deploy_hook.eval_hook('run("true")').should be_true
60
+ deploy_hook.eval_hook('run("false")').should be_false
61
+ end
74
62
  end
75
63
 
76
- it "is available" do
77
- run_hook { @node.nil? }.should be_false
78
- end
64
+ context "#sudo" do
65
+ it "is available" do
66
+ deploy_hook.eval_hook('respond_to?(:sudo)').should be_true
67
+ end
79
68
 
80
- it "has indifferent access" do
81
- run_hook { @node[:instance_role] }.should == 'solo'
82
- run_hook { @node['instance_role'] }.should == 'solo'
69
+ it "runs things with sudo" do
70
+ hook = deploy_hook
71
+ cmd = "sudo sh -l -c 'do it as root'"
72
+ result = EY::Serverside::Shell::CommandResult.new(cmd, 0, "out\nerr")
73
+ hook.callback_context.shell.should_receive(:logged_system).with(cmd).and_return(result)
74
+ hook.eval_hook('sudo("do it as root") || raise("failed")')
75
+ end
83
76
  end
84
77
 
85
- it "has deep indifferent access" do
86
- run_hook { @node['applications']['myapp']['type'] }.should == 'rails'
87
- run_hook { @node[:applications]['myapp'][:type] }.should == 'rails'
88
- run_hook { @node[:applications][:myapp][:type] }.should == 'rails'
78
+ context "capistrano-ish methods" do
79
+ it "has them" do
80
+ deploy_hook.eval_hook('respond_to?(:latest_release) ').should be_true
81
+ deploy_hook.eval_hook('respond_to?(:previous_release) ').should be_true
82
+ deploy_hook.eval_hook('respond_to?(:all_releases) ').should be_true
83
+ deploy_hook.eval_hook('respond_to?(:current_path) ').should be_true
84
+ deploy_hook.eval_hook('respond_to?(:shared_path) ').should be_true
85
+ deploy_hook.eval_hook('respond_to?(:release_dir) ').should be_true
86
+ deploy_hook.eval_hook('respond_to?(:failed_release_dir)').should be_true
87
+ deploy_hook.eval_hook('respond_to?(:release_path) ').should be_true
88
+ end
89
89
  end
90
- end
91
90
 
92
- context "the @configuration ivar" do
93
- it "is available" do
94
- run_hook { @configuration.nil? }.should be_false
95
- end
91
+ context "access to command line options that should be handed through to the config" do
92
+ before do
93
+ @hook = deploy_hook({'app' => 'app', 'environment_name' => 'env', 'account_name' => 'acc'})
94
+ end
96
95
 
97
- it "has the configuration in it" do
98
- run_hook('bert' => 'ernie') { @configuration.bert }.should == 'ernie'
99
- end
96
+ it "has account_name" do
97
+ @hook.eval_hook('account_name').should == 'acc'
98
+ end
100
99
 
101
- it "can be accessed with method calls, with [:symbols], or ['strings']" do
102
- run_hook('bert' => 'ernie') { @configuration.bert }.should == 'ernie'
103
- run_hook('bert' => 'ernie') { @configuration[:bert] }.should == 'ernie'
104
- run_hook('bert' => 'ernie') { @configuration['bert'] }.should == 'ernie'
105
- end
100
+ it "has environment_name" do
101
+ @hook.eval_hook('environment_name').should == 'env'
102
+ end
106
103
 
107
- [:repository_cache,
108
- :release_path,
109
- :branch,
110
- :shared_path,
111
- :deploy_to,
112
- :user,
113
- :revision,
114
- :environment].each do |attribute|
115
- it "has the #{attribute.inspect} attribute for compatibility with chef-deploy" do
116
- run_hook { @configuration.has_key?(attribute) }.should be_true
104
+ it "has app_name" do
105
+ @hook.eval_hook('app_name').should == 'app'
117
106
  end
118
107
  end
119
- end
120
108
 
121
- context "environment variables" do
122
- it "sets the framework env variables" do
123
- run_hook('framework_env' => 'production') { ENV['RAILS_ENV'] }.should == 'production'
124
- run_hook('framework_env' => 'production') { ENV['RACK_ENV'] }.should == 'production'
125
- run_hook('framework_env' => 'production') { ENV['MERB_ENV'] }.should == 'production'
126
- run_hook('framework_env' => 'production') { ENV['NODE_ENV'] }.should == 'production'
127
- end
128
- end
109
+ context "the @node ivar" do
110
+ before(:each) do
111
+ EY::Serverside.dna_json = {
112
+ 'instance_role' => 'solo',
113
+ 'applications' => {
114
+ 'myapp' => {
115
+ 'type' => 'rails',
116
+ 'branch' => 'master',
117
+ }
118
+ }
119
+ }.to_json
120
+ end
121
+
122
+ it "is available" do
123
+ deploy_hook.eval_hook('@node.nil?').should be_false
124
+ end
129
125
 
130
- context "has methods to run code only on certain instances" do
131
- def scenarios
132
- [
133
- {:instance_role => 'solo'},
134
- {:instance_role => 'app_master'},
135
- {:instance_role => 'app'},
136
- {:instance_role => 'db_master'},
137
- {:instance_role => 'db_slave'},
138
- {:instance_role => 'multi_role,app'},
139
- {:instance_role => 'multi,util'},
140
- {:instance_role => 'util', :name => "alpha"},
141
- {:instance_role => 'util', :name => "beta"},
142
- {:instance_role => 'util', :name => "gamma"},
143
- ]
126
+ it "has indifferent access" do
127
+ deploy_hook.eval_hook('@node[:instance_role] ').should == 'solo'
128
+ deploy_hook.eval_hook('@node["instance_role"]').should == 'solo'
129
+ end
130
+
131
+ it "has deep indifferent access" do
132
+ deploy_hook.eval_hook('@node["applications"]["myapp"]["type"]').should == 'rails'
133
+ deploy_hook.eval_hook('@node[:applications]["myapp"][:type] ').should == 'rails'
134
+ deploy_hook.eval_hook('@node[:applications][:myapp][:type] ').should == 'rails'
135
+ end
144
136
  end
145
137
 
146
- def where_code_runs_with(method, *args)
147
- scenarios.map do |s|
148
- hook_result = run_hook('current_roles' => s[:instance_role].split(','), 'current_name' => s[:name]) do
149
- send(method, *args) { 'ran!' }
150
- end
138
+ context "the @configuration ivar" do
139
+ it "is available" do
140
+ deploy_hook.eval_hook('@configuration.nil?').should be_false
141
+ end
142
+
143
+ it "has the configuration in it" do
144
+ deploy_hook('bert' => 'ernie').eval_hook('@configuration.bert').should == 'ernie'
145
+ end
146
+
147
+ it "can be accessed with method calls, with [:symbols], or ['strings']" do
148
+ deploy_hook('bert' => 'ernie').eval_hook('@configuration.bert ').should == 'ernie'
149
+ deploy_hook('bert' => 'ernie').eval_hook('@configuration[:bert] ').should == 'ernie'
150
+ deploy_hook('bert' => 'ernie').eval_hook('@configuration["bert"]').should == 'ernie'
151
+ end
151
152
 
152
- if hook_result == 'ran!'
153
- result = s[:instance_role]
154
- result << "_#{s[:name]}" if s[:name]
155
- result
153
+ [:repository_cache,
154
+ :release_path,
155
+ :branch,
156
+ :shared_path,
157
+ :deploy_to,
158
+ :user,
159
+ :revision,
160
+ :environment].each do |attribute|
161
+ it "has the #{attribute.inspect} attribute for compatibility with chef-deploy" do
162
+ deploy_hook.eval_hook("@configuration.has_key?(#{attribute.inspect})").should be_true
156
163
  end
157
- end.compact
164
+ end
158
165
  end
159
166
 
160
- it "#on_app_master runs on app masters and solos" do
161
- where_code_runs_with(:on_app_master).should == %w(solo app_master)
167
+ context "environment variables" do
168
+ it "sets the framework env variables" do
169
+ run_hook('framework_env' => 'production') { ENV['RAILS_ENV'] }.should == 'production'
170
+ run_hook('framework_env' => 'production') { ENV['RACK_ENV'] }.should == 'production'
171
+ run_hook('framework_env' => 'production') { ENV['MERB_ENV'] }.should == 'production'
172
+ run_hook('framework_env' => 'production') { ENV['NODE_ENV'] }.should == 'production'
173
+ end
162
174
  end
163
175
 
164
- it "#on_app_servers runs on app masters, app slaves, and solos" do
165
- where_code_runs_with(:on_app_servers).should == %w(solo app_master app multi_role,app)
166
- end
176
+ context "has methods to run code only on certain instances" do
177
+ def scenarios
178
+ [
179
+ ['solo' ],
180
+ ['app_master' ],
181
+ ['app' ],
182
+ ['db_master' ],
183
+ ['db_slave' ],
184
+ ['multi_role,app'],
185
+ ['multi,util' ],
186
+ ['util', 'alpha' ],
187
+ ['util', 'beta' ],
188
+ ['util', 'gamma' ],
189
+ ]
190
+ end
167
191
 
168
- it "#on_app_servers_and_utilities does what it says on the tin" do
169
- where_code_runs_with(:on_app_servers_and_utilities).should ==
170
- %w(solo app_master app multi_role,app multi,util util_alpha util_beta util_gamma)
171
- end
192
+ def where_code_runs_with(code)
193
+ scenarios.select do |role, name|
194
+ hook = deploy_hook(:current_roles => role.split(','), :current_name => name)
195
+ hook.eval_hook("#{code} { 'ran' } == 'ran'")
196
+ end.map do |scenario|
197
+ scenario.compact.join("_")
198
+ end.compact
199
+ end
172
200
 
173
- it "#on_utilities() runs on all utility instances" do
174
- where_code_runs_with(:on_utilities).should ==
175
- %w(multi,util util_alpha util_beta util_gamma)
176
- end
201
+ it "#on_app_master runs on app masters and solos" do
202
+ where_code_runs_with("on_app_master").should == %w(solo app_master)
203
+ end
177
204
 
178
- it "#on_utilities('sometype') runs on only utilities of type 'sometype'" do
179
- where_code_runs_with(:on_utilities, 'alpha').should == %w(util_alpha)
180
- end
205
+ it "#on_app_servers runs on app masters, app slaves, and solos" do
206
+ where_code_runs_with("on_app_servers").should == %w(solo app_master app multi_role,app)
207
+ end
181
208
 
182
- it "#on_utilities('type1', 'type2') runs on utilities of both types" do
183
- where_code_runs_with(:on_utilities, 'alpha', 'beta').should ==
184
- %w(util_alpha util_beta)
185
- end
209
+ it "#on_app_servers_and_utilities does what it says on the tin" do
210
+ where_code_runs_with("on_app_servers_and_utilities").should ==
211
+ %w(solo app_master app multi_role,app multi,util util_alpha util_beta util_gamma)
212
+ end
186
213
 
187
- it "#on_utilities can be invoked with (['a', 'b']) or ('a', 'b')" do
188
- where_code_runs_with(:on_utilities, %w[alpha beta]).should ==
189
- where_code_runs_with(:on_utilities, 'alpha', 'beta')
190
- end
214
+ it "#on_utilities() runs on all utility instances" do
215
+ where_code_runs_with("on_utilities").should ==
216
+ %w(multi,util util_alpha util_beta util_gamma)
217
+ end
191
218
 
192
- end
219
+ it "#on_utilities('sometype') runs on only utilities of type 'sometype'" do
220
+ where_code_runs_with("on_utilities('alpha')").should == %w(util_alpha)
221
+ end
222
+
223
+ it "#on_utilities('type1', 'type2') runs on utilities of both types" do
224
+ where_code_runs_with("on_utilities('alpha', 'beta')").should ==
225
+ %w(util_alpha util_beta)
226
+ end
193
227
 
194
- context "#syntax_error" do
195
- it "returns nil for hook files containing valid Ruby syntax" do
196
- hook_path = File.expand_path('../fixtures/valid_hook.rb', __FILE__)
197
- deploy_hook.syntax_error(hook_path).should be_nil
228
+ it "#on_utilities can be invoked with (['a', 'b']) or ('a', 'b')" do
229
+ where_code_runs_with("on_utilities(%w[alpha beta])").should ==
230
+ where_code_runs_with("on_utilities('alpha', 'beta')")
231
+ end
198
232
  end
199
233
 
200
- it "returns a brief problem description for hook files containing valid Ruby syntax" do
201
- hook_path = File.expand_path('../fixtures/invalid_hook.rb', __FILE__)
202
- desc = "spec/fixtures/invalid_hook.rb:1: syntax error, unexpected '^'"
203
- match = /#{Regexp.escape desc}/
204
- deploy_hook.syntax_error(hook_path).should =~ match
234
+ context "#syntax_error" do
235
+ it "returns nil for hook files containing valid Ruby syntax" do
236
+ hook_path = File.expand_path('../fixtures/valid_hook.rb', __FILE__)
237
+ deploy_hook.syntax_error(hook_path).should be_nil
238
+ end
239
+
240
+ it "returns a brief problem description for hook files containing valid Ruby syntax" do
241
+ hook_path = File.expand_path('../fixtures/invalid_hook.rb', __FILE__)
242
+ error = Regexp.escape("spec/fixtures/invalid_hook.rb:1: syntax error, unexpected '^'")
243
+ deploy_hook.syntax_error(hook_path).should =~ /#{error}/
244
+ end
205
245
  end
206
- end
207
246
 
208
- context "is compatible with older deploy hook scripts" do
209
- it "#current_role returns the first role" do
210
- run_hook(:current_roles => %w(a b)) { current_role.should == 'a' }
247
+ context "is compatible with older deploy hook scripts" do
248
+ it "#current_role returns the first role" do
249
+ deploy_hook(:current_roles => %w(a b)).eval_hook('current_role').should == 'a'
250
+ end
251
+
252
+ it "has info, warning, debug, logged_system, and access to shell" do
253
+ deploy_hook.eval_hook('respond_to?(:info) ').should be_true
254
+ deploy_hook.eval_hook('respond_to?(:warning) ').should be_true
255
+ deploy_hook.eval_hook('respond_to?(:debug) ').should be_true
256
+ deploy_hook.eval_hook('respond_to?(:logged_system)').should be_true
257
+ deploy_hook.eval_hook('respond_to?(:shell) ').should be_true
258
+ end
211
259
  end
212
260
  end
213
261
  end