engineyard-serverside 1.6.5 → 1.7.0.pre2

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