engineyard-serverside 2.8.0.pre3 → 2.8.0.pre4

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 (206) hide show
  1. checksums.yaml +4 -4
  2. data/lib/engineyard-serverside/callbacks/collection/base.rb +12 -5
  3. data/lib/engineyard-serverside/callbacks/distributor.rb +2 -7
  4. data/lib/engineyard-serverside/callbacks/executor/executable.rb +2 -0
  5. data/lib/engineyard-serverside/cli/workflows/calling_deploy_hooks.rb +1 -2
  6. data/lib/engineyard-serverside/deploy.rb +2 -7
  7. data/lib/engineyard-serverside/version.rb +1 -1
  8. data/spec/archive_deploy_spec.rb +53 -0
  9. data/spec/basic_deploy_spec.rb +26 -0
  10. data/spec/bundler_deploy_spec.rb +160 -0
  11. data/spec/configuration_spec.rb +206 -0
  12. data/spec/custom_deploy_spec.rb +128 -0
  13. data/spec/deploy_hook_spec.rb +378 -0
  14. data/spec/deprecation_spec.rb +23 -0
  15. data/spec/ey_yml_customized_deploy_spec.rb +99 -0
  16. data/spec/fixtures/gitrepo.tar.gz +0 -0
  17. data/spec/fixtures/invalid_hook.rb +1 -0
  18. data/spec/fixtures/lockfiles/0.9-no-bundler +111 -0
  19. data/spec/fixtures/lockfiles/0.9-with-bundler +117 -0
  20. data/spec/fixtures/lockfiles/1.0-no-bundler +54 -0
  21. data/spec/fixtures/lockfiles/1.0.0.rc.1-with-bundler +162 -0
  22. data/spec/fixtures/lockfiles/1.0.18-do_mysql +88 -0
  23. data/spec/fixtures/lockfiles/1.0.18-do_postgres +79 -0
  24. data/spec/fixtures/lockfiles/1.0.18-mysql +43 -0
  25. data/spec/fixtures/lockfiles/1.0.18-mysql2 +43 -0
  26. data/spec/fixtures/lockfiles/1.0.18-pg +43 -0
  27. data/spec/fixtures/lockfiles/1.0.6-no-bundler +51 -0
  28. data/spec/fixtures/lockfiles/1.0.6-with-any-bundler +52 -0
  29. data/spec/fixtures/lockfiles/1.0.6-with-bundler +52 -0
  30. data/spec/fixtures/lockfiles/1.15.1-no-bundler +51 -0
  31. data/spec/fixtures/lockfiles/1.3.1-rails-3.2.13 +112 -0
  32. data/spec/fixtures/lockfiles/not-a-lockfile +1 -0
  33. data/spec/fixtures/repos/assets_detected/Gemfile +5 -0
  34. data/spec/fixtures/repos/assets_detected/Gemfile.lock +88 -0
  35. data/spec/fixtures/repos/assets_detected/README +1 -0
  36. data/spec/fixtures/repos/assets_detected/Rakefile +5 -0
  37. data/spec/fixtures/repos/assets_detected/app/assets/empty +0 -0
  38. data/spec/fixtures/repos/assets_detected/config/application.rb +5 -0
  39. data/spec/fixtures/repos/assets_detected/config/ey.yml +3 -0
  40. data/spec/fixtures/repos/assets_disabled/Gemfile +5 -0
  41. data/spec/fixtures/repos/assets_disabled/Gemfile.lock +88 -0
  42. data/spec/fixtures/repos/assets_disabled/README +1 -0
  43. data/spec/fixtures/repos/assets_disabled/Rakefile +6 -0
  44. data/spec/fixtures/repos/assets_disabled/app/assets/empty +0 -0
  45. data/spec/fixtures/repos/assets_disabled/config/application.rb +5 -0
  46. data/spec/fixtures/repos/assets_disabled/config/ey.yml +3 -0
  47. data/spec/fixtures/repos/assets_disabled_in_ey_yml/Gemfile +5 -0
  48. data/spec/fixtures/repos/assets_disabled_in_ey_yml/Gemfile.lock +88 -0
  49. data/spec/fixtures/repos/assets_disabled_in_ey_yml/README +1 -0
  50. data/spec/fixtures/repos/assets_disabled_in_ey_yml/Rakefile +6 -0
  51. data/spec/fixtures/repos/assets_disabled_in_ey_yml/app/assets/empty +0 -0
  52. data/spec/fixtures/repos/assets_disabled_in_ey_yml/config/application.rb +5 -0
  53. data/spec/fixtures/repos/assets_disabled_in_ey_yml/config/ey.yml +5 -0
  54. data/spec/fixtures/repos/assets_disabled_utf8/Gemfile +5 -0
  55. data/spec/fixtures/repos/assets_disabled_utf8/Gemfile.lock +88 -0
  56. data/spec/fixtures/repos/assets_disabled_utf8/README +3 -0
  57. data/spec/fixtures/repos/assets_disabled_utf8/Rakefile +5 -0
  58. data/spec/fixtures/repos/assets_disabled_utf8/app/assets/empty +0 -0
  59. data/spec/fixtures/repos/assets_disabled_utf8/config/application.rb +7 -0
  60. data/spec/fixtures/repos/assets_disabled_utf8/config/ey.yml +3 -0
  61. data/spec/fixtures/repos/assets_enabled_all/Gemfile +5 -0
  62. data/spec/fixtures/repos/assets_enabled_all/Gemfile.lock +88 -0
  63. data/spec/fixtures/repos/assets_enabled_all/README +1 -0
  64. data/spec/fixtures/repos/assets_enabled_all/app/assets/empty +0 -0
  65. data/spec/fixtures/repos/assets_enabled_all/config/application.rb +5 -0
  66. data/spec/fixtures/repos/assets_enabled_all/config/ey.yml +6 -0
  67. data/spec/fixtures/repos/assets_enabled_all/script/assets +5 -0
  68. data/spec/fixtures/repos/assets_enabled_all/tmp/obstruction +1 -0
  69. data/spec/fixtures/repos/assets_enabled_in_ey_yml/Gemfile +3 -0
  70. data/spec/fixtures/repos/assets_enabled_in_ey_yml/Gemfile.lock +10 -0
  71. data/spec/fixtures/repos/assets_enabled_in_ey_yml/README +1 -0
  72. data/spec/fixtures/repos/assets_enabled_in_ey_yml/Rakefile +8 -0
  73. data/spec/fixtures/repos/assets_enabled_in_ey_yml/config/ey.yml +4 -0
  74. data/spec/fixtures/repos/assets_enabled_util_only/Gemfile +5 -0
  75. data/spec/fixtures/repos/assets_enabled_util_only/Gemfile.lock +88 -0
  76. data/spec/fixtures/repos/assets_enabled_util_only/README +1 -0
  77. data/spec/fixtures/repos/assets_enabled_util_only/Rakefile +6 -0
  78. data/spec/fixtures/repos/assets_enabled_util_only/app/assets/empty +0 -0
  79. data/spec/fixtures/repos/assets_enabled_util_only/config/application.rb +5 -0
  80. data/spec/fixtures/repos/assets_enabled_util_only/config/ey.yml +6 -0
  81. data/spec/fixtures/repos/assets_error/Gemfile +5 -0
  82. data/spec/fixtures/repos/assets_error/Gemfile.lock +88 -0
  83. data/spec/fixtures/repos/assets_error/README +1 -0
  84. data/spec/fixtures/repos/assets_error/Rakefile +4 -0
  85. data/spec/fixtures/repos/assets_error/app/assets/empty +0 -0
  86. data/spec/fixtures/repos/assets_error/config/application.rb +5 -0
  87. data/spec/fixtures/repos/assets_error/config/ey.yml +4 -0
  88. data/spec/fixtures/repos/assets_in_hook/Gemfile +5 -0
  89. data/spec/fixtures/repos/assets_in_hook/Gemfile.lock +88 -0
  90. data/spec/fixtures/repos/assets_in_hook/README +2 -0
  91. data/spec/fixtures/repos/assets_in_hook/Rakefile +5 -0
  92. data/spec/fixtures/repos/assets_in_hook/app/assets/empty +0 -0
  93. data/spec/fixtures/repos/assets_in_hook/config/application.rb +5 -0
  94. data/spec/fixtures/repos/assets_in_hook/config/ey.yml +3 -0
  95. data/spec/fixtures/repos/assets_in_hook/deploy/before_compile_assets.rb +2 -0
  96. data/spec/fixtures/repos/bundle_fails/Gemfile +1 -0
  97. data/spec/fixtures/repos/bundle_fails/README +1 -0
  98. data/spec/fixtures/repos/bundle_fails/deploy/after_bundle.rb +1 -0
  99. data/spec/fixtures/repos/bundler_disabled/Gemfile +4 -0
  100. data/spec/fixtures/repos/bundler_disabled/Gemfile.lock +12 -0
  101. data/spec/fixtures/repos/bundler_disabled/README +1 -0
  102. data/spec/fixtures/repos/bundler_disabled/config/ey.yml +2 -0
  103. data/spec/fixtures/repos/bundler_disabled/deploy/after_bundle.rb +1 -0
  104. data/spec/fixtures/repos/bundler_disabled/deploy/before_bundle.rb +1 -0
  105. data/spec/fixtures/repos/bundler_old/Gemfile +5 -0
  106. data/spec/fixtures/repos/bundler_old/Gemfile.lock +15 -0
  107. data/spec/fixtures/repos/bundler_old/README +1 -0
  108. data/spec/fixtures/repos/default/Gemfile +4 -0
  109. data/spec/fixtures/repos/default/Gemfile.lock +12 -0
  110. data/spec/fixtures/repos/default/README +5 -0
  111. data/spec/fixtures/repos/default/ey.yml +3 -0
  112. data/spec/fixtures/repos/executable_hooks/README +1 -0
  113. data/spec/fixtures/repos/executable_hooks/deploy/before_restart +72 -0
  114. data/spec/fixtures/repos/executable_hooks_not_executable/README +3 -0
  115. data/spec/fixtures/repos/executable_hooks_not_executable/deploy/before_restart +3 -0
  116. data/spec/fixtures/repos/ey_yml/Gemfile +4 -0
  117. data/spec/fixtures/repos/ey_yml/Gemfile.lock +12 -0
  118. data/spec/fixtures/repos/ey_yml/README +1 -0
  119. data/spec/fixtures/repos/ey_yml/config/ey.yml +18 -0
  120. data/spec/fixtures/repos/ey_yml/deploy/before_migrate.rb +6 -0
  121. data/spec/fixtures/repos/ey_yml_alt/Gemfile +4 -0
  122. data/spec/fixtures/repos/ey_yml_alt/Gemfile.lock +12 -0
  123. data/spec/fixtures/repos/ey_yml_alt/README +1 -0
  124. data/spec/fixtures/repos/ey_yml_alt/deploy/before_migrate.rb +6 -0
  125. data/spec/fixtures/repos/ey_yml_alt/ey.yml +12 -0
  126. data/spec/fixtures/repos/hook_fails/README +1 -0
  127. data/spec/fixtures/repos/hook_fails/deploy/before_deploy.rb +1 -0
  128. data/spec/fixtures/repos/hooks/README +1 -0
  129. data/spec/fixtures/repos/hooks/deploy/after_bundle.rb +1 -0
  130. data/spec/fixtures/repos/hooks/deploy/after_compile_assets.rb +1 -0
  131. data/spec/fixtures/repos/hooks/deploy/after_deploy.rb +1 -0
  132. data/spec/fixtures/repos/hooks/deploy/after_migrate.rb +1 -0
  133. data/spec/fixtures/repos/hooks/deploy/after_restart.rb +1 -0
  134. data/spec/fixtures/repos/hooks/deploy/after_symlink.rb +1 -0
  135. data/spec/fixtures/repos/hooks/deploy/before_bundle.rb +1 -0
  136. data/spec/fixtures/repos/hooks/deploy/before_compile_assets.rb +1 -0
  137. data/spec/fixtures/repos/hooks/deploy/before_deploy.rb +1 -0
  138. data/spec/fixtures/repos/hooks/deploy/before_migrate.rb +1 -0
  139. data/spec/fixtures/repos/hooks/deploy/before_restart.rb +1 -0
  140. data/spec/fixtures/repos/hooks/deploy/before_symlink.rb +1 -0
  141. data/spec/fixtures/repos/multi_dep_manager/README +1 -0
  142. data/spec/fixtures/repos/multi_dep_manager/composer.json +5 -0
  143. data/spec/fixtures/repos/multi_dep_manager/composer.lock +462 -0
  144. data/spec/fixtures/repos/multi_dep_manager/package.json +7 -0
  145. data/spec/fixtures/repos/multi_dep_manager/public/index.php +4 -0
  146. data/spec/fixtures/repos/no_ey_config/Gemfile +3 -0
  147. data/spec/fixtures/repos/no_ey_config/Gemfile.lock +10 -0
  148. data/spec/fixtures/repos/no_ey_config/README +1 -0
  149. data/spec/fixtures/repos/no_ey_config/ey.yml +3 -0
  150. data/spec/fixtures/repos/no_ey_config_no_warning/Gemfile +3 -0
  151. data/spec/fixtures/repos/no_ey_config_no_warning/Gemfile.lock +10 -0
  152. data/spec/fixtures/repos/no_ey_config_no_warning/README +1 -0
  153. data/spec/fixtures/repos/no_ey_config_no_warning/ey.yml +5 -0
  154. data/spec/fixtures/repos/no_gemfile_lock/Gemfile +4 -0
  155. data/spec/fixtures/repos/no_gemfile_lock/README +1 -0
  156. data/spec/fixtures/repos/no_gemfile_lock/ey.yml +3 -0
  157. data/spec/fixtures/repos/nodejs/README +1 -0
  158. data/spec/fixtures/repos/nodejs/package.json +7 -0
  159. data/spec/fixtures/repos/not_bundled/README +1 -0
  160. data/spec/fixtures/repos/npm_disabled/README +1 -0
  161. data/spec/fixtures/repos/npm_disabled/config/ey.yml +2 -0
  162. data/spec/fixtures/repos/npm_disabled/package.json +7 -0
  163. data/spec/fixtures/repos/php_composer_disabled/README +1 -0
  164. data/spec/fixtures/repos/php_composer_disabled/composer.json +5 -0
  165. data/spec/fixtures/repos/php_composer_disabled/composer.lock +462 -0
  166. data/spec/fixtures/repos/php_composer_disabled/config/ey.yml +2 -0
  167. data/spec/fixtures/repos/php_composer_disabled/public/index.php +4 -0
  168. data/spec/fixtures/repos/php_composer_lock/README +1 -0
  169. data/spec/fixtures/repos/php_composer_lock/composer.json +5 -0
  170. data/spec/fixtures/repos/php_composer_lock/composer.lock +462 -0
  171. data/spec/fixtures/repos/php_composer_lock/public/index.php +4 -0
  172. data/spec/fixtures/repos/php_no_composer_lock/README +1 -0
  173. data/spec/fixtures/repos/php_no_composer_lock/composer.json +21 -0
  174. data/spec/fixtures/repos/php_no_composer_lock/public/index.php +4 -0
  175. data/spec/fixtures/repos/public_system/Gemfile +4 -0
  176. data/spec/fixtures/repos/public_system/Gemfile.lock +12 -0
  177. data/spec/fixtures/repos/public_system/README +5 -0
  178. data/spec/fixtures/repos/public_system/ey.yml +3 -0
  179. data/spec/fixtures/repos/public_system/public/system/cant_touch_this.txt +3 -0
  180. data/spec/fixtures/repos/sqlite3/Gemfile +4 -0
  181. data/spec/fixtures/repos/sqlite3/Gemfile.lock +89 -0
  182. data/spec/fixtures/repos/sqlite3/README +1 -0
  183. data/spec/fixtures/retwisj.war +0 -0
  184. data/spec/fixtures/valid_hook.rb +1 -0
  185. data/spec/git_strategy_spec.rb +34 -0
  186. data/spec/lockfile_parser_spec.rb +126 -0
  187. data/spec/maintenance_spec.rb +44 -0
  188. data/spec/multi_dependency_manager_spec.rb +25 -0
  189. data/spec/nodejs_deploy_spec.rb +30 -0
  190. data/spec/php_deploy_spec.rb +81 -0
  191. data/spec/platform_configure_spec.rb +61 -0
  192. data/spec/rails31_deploy_spec.rb +172 -0
  193. data/spec/restart_spec.rb +43 -0
  194. data/spec/rollback_spec.rb +87 -0
  195. data/spec/server_spec.rb +70 -0
  196. data/spec/services_deploy_spec.rb +165 -0
  197. data/spec/shell_spec.rb +57 -0
  198. data/spec/source/archive_spec.rb +33 -0
  199. data/spec/source/git_spec.rb +44 -0
  200. data/spec/spec_helper.rb +361 -0
  201. data/spec/sqlite3_deploy_spec.rb +38 -0
  202. data/spec/support/integration.rb +103 -0
  203. data/spec/support/source_doubles.rb +28 -0
  204. data/spec/support/timecop.rb +5 -0
  205. data/spec/symlink_spec.rb +15 -0
  206. metadata +399 -3
@@ -0,0 +1,128 @@
1
+ require 'spec_helper'
2
+
3
+ describe "the EY::Serverside::Deploy API" do
4
+ it "calls tasks in the right order" do
5
+ class TestDeploy < FullTestDeploy
6
+ attr_reader :call_order
7
+ def initialize(*a)
8
+ super
9
+ @call_order = []
10
+ end
11
+
12
+ def push_code() @call_order << 'push_code' ; super end
13
+ def copy_repository_cache() @call_order << 'copy_repository_cache' ; super end
14
+ def create_revision_file() @call_order << 'create_revision_file' ; super end
15
+ def bundle() @call_order << 'bundle' ; super end
16
+ def setup_services() @call_order << 'setup_services' ; super end
17
+ def symlink_configs() @call_order << 'symlink_configs' ; super end
18
+ def migrate() @call_order << 'migrate' ; super end
19
+ def compile_assets() @call_order << 'compile_assets' ; super end
20
+ def symlink() @call_order << 'symlink' ; super end
21
+ def restart() @call_order << 'restart' ; super end
22
+ def cleanup_old_releases() @call_order << 'cleanup_old_releases' ; super end
23
+ def enable_maintenance_page() @call_order << 'enable_maintenance_page' ; super end
24
+ def disable_maintenance_page() @call_order << 'disable_maintenance_page'; super end
25
+ def gc_repository_cache() @call_order << 'gc_repository_cache' ; super end
26
+ end
27
+
28
+ config = EY::Serverside::Deploy::Configuration.new(default_configuration)
29
+
30
+ td = TestDeploy.realnew(test_servers, config, test_shell)
31
+ mock_bundler
32
+ with_mocked_commands do
33
+ capture do
34
+ td.deploy
35
+ end
36
+ end
37
+
38
+ ############################# IMPORTANT ####################################
39
+ #
40
+ # Call order is referenced in the engineyard gem eydeploy.rb documentation.
41
+ #
42
+ # https://support.cloud.engineyard.com/entries/20996661-customize-your-deployment
43
+ #
44
+ # Changing call order or removing methods may adversely affect customers
45
+ # that are using eydeploy.rb and relying on this documentation.
46
+ #
47
+ ############################################################################
48
+ expect(td.call_order).to eq(%w(
49
+ push_code
50
+ copy_repository_cache
51
+ create_revision_file
52
+ bundle
53
+ setup_services
54
+ symlink_configs
55
+ compile_assets
56
+ enable_maintenance_page
57
+ migrate
58
+ symlink
59
+ restart
60
+ disable_maintenance_page
61
+ cleanup_old_releases
62
+ gc_repository_cache))
63
+ end
64
+
65
+ describe "task overrides" do
66
+ before(:each) do
67
+ @tempdir = Pathname.new(`mktemp -d -t custom_deploy_spec.XXXXX`.strip)
68
+ end
69
+
70
+ def write_eydeploy(relative_path, contents = "def got_new_methods() 'from the file on disk' end")
71
+ path = @tempdir.join(relative_path)
72
+ path.dirname.mkpath
73
+ path.open('w') { |f| f << contents }
74
+ end
75
+
76
+ describe "eydeploy_rb disabled" do
77
+ before do
78
+ @config = EY::Serverside::Deploy::Configuration.new('app' => 'app_name', 'repository_cache' => @tempdir.to_s, 'eydeploy_rb' => 'false')
79
+ @deploy = FullTestDeploy.realnew(test_servers, @config, test_shell)
80
+ end
81
+
82
+ it "doesn't load eydeploy_rb file" do
83
+ write_eydeploy 'eydeploy.rb'
84
+ @deploy.require_custom_tasks
85
+ expect(@deploy).not_to respond_to(:got_new_methods)
86
+ end
87
+ end
88
+
89
+ describe "eydeploy_rb detect or enabled" do
90
+ before do
91
+ @config = EY::Serverside::Deploy::Configuration.new('app' => 'app_name', 'repository_cache' => @tempdir.to_s, 'eydeploy_rb' => 'true')
92
+ @deploy = FullTestDeploy.realnew(test_servers, @config, test_shell)
93
+ end
94
+
95
+ it "requires 'eydeploy.rb' and adds any defined methods to the deploy" do
96
+ write_eydeploy 'eydeploy.rb'
97
+ @deploy.require_custom_tasks
98
+ expect(@deploy.got_new_methods).to eq('from the file on disk')
99
+ end
100
+
101
+ it "falls back to 'config/eydeploy.rb'" do
102
+ write_eydeploy 'config/eydeploy.rb'
103
+ @deploy.require_custom_tasks
104
+ expect(@deploy.got_new_methods).to eq('from the file on disk')
105
+ end
106
+
107
+ it "lets you super up from any defined methods" do
108
+ write_eydeploy 'eydeploy.rb', "def value() super << ' + derived' end"
109
+
110
+ class TestDeploySuper < FullTestDeploy
111
+ def value() 'base' end
112
+ end
113
+
114
+ deploy = TestDeploySuper.realnew(test_servers, @config, test_shell)
115
+ deploy.require_custom_tasks
116
+ expect(deploy.value).to eq("base + derived")
117
+ end
118
+
119
+ it "records exceptions raised from the instance eval in the log" do
120
+ write_eydeploy 'eydeploy.rb', "raise 'Imma blow up'"
121
+ expect { @deploy.require_custom_tasks }.to raise_error
122
+ log = @log_path.read
123
+ expect(log).to match(/Exception while loading .*eydeploy\.rb/)
124
+ expect(log).to include('Imma blow up')
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,378 @@
1
+ require 'spec_helper'
2
+
3
+ describe "deploy hooks" do
4
+ context "successful deploy with all hooks" do
5
+ before(:all) do
6
+ deploy_test_application('hooks')
7
+ end
8
+
9
+ it "runs all the hooks" do
10
+ expect(deploy_dir.join('current', 'before_deploy.ran' )).to exist
11
+ expect(deploy_dir.join('current', 'before_bundle.ran' )).to exist
12
+ expect(deploy_dir.join('current', 'after_bundle.ran' )).to exist
13
+ expect(deploy_dir.join('current', 'before_migrate.ran')).to exist
14
+ expect(deploy_dir.join('current', 'after_migrate.ran' )).to exist
15
+ expect(deploy_dir.join('current', 'before_compile_assets.ran')).to exist
16
+ expect(deploy_dir.join('current', 'after_compile_assets.ran' )).to exist
17
+ expect(deploy_dir.join('current', 'before_symlink.ran')).to exist
18
+ expect(deploy_dir.join('current', 'after_symlink.ran' )).to exist
19
+ expect(deploy_dir.join('current', 'before_restart.ran')).to exist
20
+ expect(deploy_dir.join('current', 'after_restart.ran' )).to exist
21
+ expect(deploy_dir.join('current', 'after_deploy.ran' )).to exist
22
+ end
23
+ end
24
+
25
+ context "with failing deploy hook" do
26
+ before(:all) do
27
+ begin
28
+ deploy_test_application('hook_fails', :verbose => false)
29
+ rescue EY::Serverside::RemoteFailure
30
+ end
31
+ end
32
+
33
+ it "prints the failure to the log even when non-verbose" do
34
+ out = read_output
35
+ expect(out).to match(%r|FATAL:\s+Exception raised in hook .*/deploy/before_deploy.rb.|)
36
+ expect(out).to match(%r|RuntimeError:.*Hook failing in \(eval\)|)
37
+ expect(out).to match(%r|Please fix this error before retrying.|)
38
+ end
39
+
40
+ it "retains the failed release" do
41
+ release_name = @config.paths.active_release.basename
42
+ expect(deploy_dir.join('releases_failed', release_name)).to be_directory
43
+ end
44
+ end
45
+
46
+ context "with an executable for a deploy hook" do
47
+ before(:all) do
48
+ deploy_test_application('executable_hooks')
49
+ end
50
+
51
+ it 'runs the hook' do
52
+ expect(deploy_dir.join('current', 'before_restart.ran')).to exist
53
+ end
54
+ end
55
+
56
+ context "with a non-executable, but correctly named deploy hook" do
57
+ before(:all) do
58
+ deploy_test_application('executable_hooks_not_executable')
59
+ end
60
+
61
+ it 'does not run the hook' do
62
+ expect(deploy_dir.join('current', 'before_restart.ran')).not_to exist
63
+ end
64
+
65
+ it 'outputs a message about the hook not being executable' do
66
+ expect(read_output).to match(%r|Skipping.*deploy hook.*not executable|)
67
+ end
68
+ end
69
+
70
+ context "deploy hook API" do
71
+ def deploy_hook(options={})
72
+ config = EY::Serverside::Deploy::Configuration.new({
73
+ 'app' => 'app_name',
74
+ 'framework_env' => 'staging',
75
+ 'current_roles' => ['solo'],
76
+ 'deploy_to' => deploy_dir.to_s,
77
+ }.merge(options))
78
+ # setup to run hooks since a deploy hasn't happened
79
+ config.paths.new_release!
80
+ config.paths.active_release.mkpath
81
+ hook = EY::Serverside::Callbacks::Hooks::App.new(
82
+ File.join(config.paths.active_release, 'deploy', 'fake_test_hook.rb')
83
+ )
84
+ #EY::Serverside::DeployHook.new(config, test_shell, 'fake_test_hook')
85
+ EY::Serverside::Callbacks::Executor::Ruby::Context.new(
86
+ config,
87
+ test_shell,
88
+ hook
89
+ )
90
+ end
91
+
92
+ # Deprecated by inside tests - dwalters
93
+ #context "#run" do
94
+ #it "is available" do
95
+ #expect(deploy_hook.instance_eval('respond_to?(:run)')).to be_truthy
96
+ #end
97
+
98
+ #it "runs commands like the shell does" do
99
+ #ENV['COUNT'] = 'Chocula'
100
+ #File.unlink("/tmp/deploy_hook_spec.the_count") rescue nil
101
+
102
+ #deploy_hook.instance_eval('run("echo $COUNT > /tmp/deploy_hook_spec.the_count")')
103
+
104
+ #expect(IO.read("/tmp/deploy_hook_spec.the_count").strip).to eq("Chocula")
105
+ #end
106
+
107
+ #it "returns true/false to indicate the command's success" do
108
+ #expect(deploy_hook.instance_eval('run("true")')).to be_truthy
109
+ #expect(deploy_hook.instance_eval('run("false")')).to be_falsey
110
+ #end
111
+
112
+ #it "raises when the bang method alternative is used" do
113
+ ##expect {
114
+ #deploy_hook.instance_eval('run!("false")')
115
+ ##}.to raise_error(RuntimeError)
116
+ #out = read_output
117
+ #puts "out == '#{out}'"
118
+ #fail
119
+ #expect(out).to match(%r|FATAL:\s+Exception raised in hook .*/deploy/fake_test_hook.rb.|)
120
+ #expect(out).to match(%r|RuntimeError: .*run!.*Command failed. false|)
121
+ #expect(out).to match(%r|Please fix this error before retrying.|)
122
+ #end
123
+ #end
124
+
125
+ # Deprecated by inside tests - dwalters
126
+ #context "#sudo" do
127
+ #it "is available" do
128
+ #expect(deploy_hook.instance_eval('respond_to?(:sudo)')).to be_truthy
129
+ #end
130
+
131
+ #it "runs things with sudo" do
132
+ #hook = deploy_hook
133
+ #mock_sudo do
134
+ #hook.instance_eval('sudo("true") || raise("failed")')
135
+ #end
136
+ #end
137
+
138
+ #it "raises when the bang method alternative is used" do
139
+ #hook = deploy_hook
140
+ #mock_sudo do
141
+ #expect {
142
+ #hook.instance_eval('sudo!("false")')
143
+ #}.to raise_error(RuntimeError)
144
+ #end
145
+ #out = read_output
146
+ #expect(out).to match(%r|FATAL:\s+Exception raised in hook .*/deploy/fake_test_hook.rb.|)
147
+ #expect(out).to match(%r|RuntimeError: .*sudo!.*Command failed. false|)
148
+ #expect(out).to match(%r|Please fix this error before retrying.|)
149
+ #end
150
+ #end
151
+
152
+ context "capistrano-ish methods" do
153
+ it "has them" do
154
+ expect(deploy_hook.instance_eval('respond_to?(:latest_release) ')).to be_truthy
155
+ expect(deploy_hook.instance_eval('respond_to?(:previous_release) ')).to be_truthy
156
+ expect(deploy_hook.instance_eval('respond_to?(:all_releases) ')).to be_truthy
157
+ expect(deploy_hook.instance_eval('respond_to?(:current_path) ')).to be_truthy
158
+ expect(deploy_hook.instance_eval('respond_to?(:shared_path) ')).to be_truthy
159
+ expect(deploy_hook.instance_eval('respond_to?(:release_dir) ')).to be_truthy
160
+ expect(deploy_hook.instance_eval('respond_to?(:failed_release_dir)')).to be_truthy
161
+ expect(deploy_hook.instance_eval('respond_to?(:release_path) ')).to be_truthy
162
+ end
163
+
164
+ it "shows a deprecation warning that asks you to use config to access these variables" do
165
+ expect(deploy_hook.instance_eval('shared_path.nil?')).to be_falsey
166
+ out = read_output
167
+ expect(out).to include("Use of `shared_path` (via method_missing) is deprecated in favor of `config.shared_path` for improved error messages and compatibility.")
168
+ expect(out).to match(%r|in .*/deploy/fake_test_hook.rb|)
169
+ end
170
+ end
171
+
172
+ context "access to command line options that should be handed through to the config" do
173
+ before do
174
+ @hook = deploy_hook({'app' => 'app', 'environment_name' => 'env', 'account_name' => 'acc'})
175
+ end
176
+
177
+ it "has account_name" do
178
+ expect(@hook.instance_eval('account_name')).to eq('acc')
179
+ end
180
+
181
+ it "has environment_name" do
182
+ expect(@hook.instance_eval('environment_name')).to eq('env')
183
+ end
184
+
185
+ it "has app_name" do
186
+ expect(@hook.instance_eval('app_name')).to eq('app')
187
+ end
188
+ end
189
+
190
+ context "node" do
191
+ before(:each) do
192
+ EY::Serverside.dna_json = MultiJson.dump({
193
+ 'instance_role' => 'solo',
194
+ 'applications' => {
195
+ 'myapp' => {
196
+ 'type' => 'rails',
197
+ 'branch' => 'master',
198
+ }
199
+ }
200
+ })
201
+ end
202
+
203
+ # Test deprecated by inside tests and new implementation - dwalters
204
+ #it "is deprecated through the @node ivar" do
205
+ #expect(deploy_hook.instance_eval('@node.nil?')).to be_falsey
206
+ #out = read_output
207
+ #expect(out).to match(%r|Use of `@node` in deploy hooks is deprecated.|)
208
+ #expect(out).to match(%r|Please use `config.node`, which provides access to the same object.|)
209
+ #expect(out).to match(%r|.*/deploy/fake_test_hook.rb|)
210
+ #end
211
+
212
+ it "is available" do
213
+ expect(deploy_hook.instance_eval('config.node.nil?')).to be_falsey
214
+ end
215
+
216
+ it "has indifferent access" do
217
+ expect(deploy_hook.instance_eval('config.node[:instance_role] ')).to eq('solo')
218
+ expect(deploy_hook.instance_eval('config.node["instance_role"]')).to eq('solo')
219
+ end
220
+
221
+ it "has deep indifferent access" do
222
+ expect(deploy_hook.instance_eval('config.node["applications"]["myapp"]["type"]')).to eq('rails')
223
+ expect(deploy_hook.instance_eval('config.node[:applications]["myapp"][:type] ')).to eq('rails')
224
+ expect(deploy_hook.instance_eval('config.node[:applications][:myapp][:type] ')).to eq('rails')
225
+ end
226
+ end
227
+
228
+ context "config" do
229
+ it "is available" do
230
+ expect(deploy_hook.instance_eval('config.nil?')).to be_falsey
231
+ end
232
+
233
+ # Test deprecated by inside tests and new implementation - dwalters
234
+ #it "is deprecated through the @configuration ivar" do
235
+ #expect(deploy_hook.instance_eval('@configuration.nil?')).to be_falsey
236
+ #out = read_output
237
+ #expect(out).to match(%r|Use of `@configuration` in deploy hooks is deprecated.|)
238
+ #expect(out).to match(%r|Please use `config`, which provides access to the same object.|)
239
+ #expect(out).to match(%r|.*/deploy/fake_test_hook.rb|)
240
+ #end
241
+
242
+ it "has the configuration in it" do
243
+ expect(deploy_hook('bert' => 'ernie').instance_eval('config.bert')).to eq('ernie')
244
+ end
245
+
246
+ it "can be accessed with method calls, with [:symbols], or ['strings']" do
247
+ expect(deploy_hook('bert' => 'ernie').instance_eval('config.bert ')).to eq('ernie')
248
+ expect(deploy_hook('bert' => 'ernie').instance_eval('config[:bert] ')).to eq('ernie')
249
+ expect(deploy_hook('bert' => 'ernie').instance_eval('config["bert"]')).to eq('ernie')
250
+ end
251
+
252
+ [:repository_cache,
253
+ :release_path,
254
+ :branch,
255
+ :shared_path,
256
+ :deploy_to,
257
+ :user,
258
+ :revision,
259
+ :environment].each do |attribute|
260
+ it "has the #{attribute.inspect} attribute for compatibility with chef-deploy" do
261
+ expect(deploy_hook.instance_eval("config.has_key?(#{attribute.inspect})")).to be_truthy
262
+ end
263
+ end
264
+ end
265
+
266
+ context "environment variables" do
267
+ it "sets the framework env variables" do
268
+ expect(deploy_hook('framework_env' => 'production').instance_eval("ENV['RAILS_ENV']")).to eq('production')
269
+ expect(deploy_hook('framework_env' => 'production').instance_eval("ENV['RACK_ENV'] ")).to eq('production')
270
+ expect(deploy_hook('framework_env' => 'production').instance_eval("ENV['MERB_ENV'] ")).to eq('production')
271
+ expect(deploy_hook('framework_env' => 'production').instance_eval("ENV['NODE_ENV'] ")).to eq('production')
272
+ end
273
+ end
274
+
275
+ context "has methods to run code only on certain instances" do
276
+ def scenarios
277
+ [
278
+ ['solo' ],
279
+ ['app_master' ],
280
+ ['app' ],
281
+ ['db_master' ],
282
+ ['db_slave' ],
283
+ ['multi_role,app'],
284
+ ['multi,util' ],
285
+ ['util', 'alpha' ],
286
+ ['util', 'beta' ],
287
+ ['util', 'gamma' ],
288
+ ]
289
+ end
290
+
291
+ def where_code_runs_with(code)
292
+ scenarios.select do |role, name|
293
+ hook = deploy_hook('current_roles' => role.split(','), 'current_name' => name)
294
+ hook.instance_eval("#{code} { 'ran' } == 'ran'")
295
+ end.map do |scenario|
296
+ scenario.compact.join("_")
297
+ end.compact
298
+ end
299
+
300
+ it "#on_app_master runs on app masters and solos" do
301
+ expect(where_code_runs_with("on_app_master")).to eq(%w(solo app_master))
302
+ end
303
+
304
+ it "#on_app_servers runs on app masters, app slaves, and solos" do
305
+ expect(where_code_runs_with("on_app_servers")).to eq(%w(solo app_master app multi_role,app))
306
+ end
307
+
308
+ it "#on_app_servers_and_utilities does what it says on the tin" do
309
+ expect(where_code_runs_with("on_app_servers_and_utilities")).to eq(
310
+ %w(solo app_master app multi_role,app multi,util util_alpha util_beta util_gamma)
311
+ )
312
+ end
313
+
314
+ it "#on_utilities() runs on all utility instances" do
315
+ expect(where_code_runs_with("on_utilities")).to eq(
316
+ %w(multi,util util_alpha util_beta util_gamma)
317
+ )
318
+ end
319
+
320
+ it "#on_utilities('sometype') runs on only utilities of type 'sometype'" do
321
+ expect(where_code_runs_with("on_utilities('alpha')")).to eq(%w(util_alpha))
322
+ end
323
+
324
+ it "#on_utilities('type1', 'type2') runs on utilities of both types" do
325
+ expect(where_code_runs_with("on_utilities('alpha', 'beta')")).to eq(
326
+ %w(util_alpha util_beta)
327
+ )
328
+ end
329
+
330
+ it "#on_utilities can be invoked with (['a', 'b']) or ('a', 'b')" do
331
+ expect(where_code_runs_with("on_utilities(%w[alpha beta])")).to eq(
332
+ where_code_runs_with("on_utilities('alpha', 'beta')")
333
+ )
334
+ end
335
+ end
336
+
337
+ # Deprecated by new implementation and inside tests - dwalters
338
+ #context "#syntax_error" do
339
+ #it "returns nil for hook files containing valid Ruby syntax" do
340
+ #hook_path = File.expand_path('../fixtures/valid_hook.rb', __FILE__)
341
+ #expect(deploy_hook.syntax_error(hook_path)).to be_nil
342
+ #end
343
+
344
+ #it "returns a brief problem description for hook files containing valid Ruby syntax" do
345
+ #hook_path = File.expand_path('../fixtures/invalid_hook.rb', __FILE__)
346
+ #error = Regexp.escape("spec/fixtures/invalid_hook.rb:1: syntax error, unexpected '^'")
347
+ #expect(deploy_hook.syntax_error(hook_path)).to match(/#{error}/)
348
+ #end
349
+ #end
350
+
351
+ # Test deprecated by inside tests and new implementation - dwalters
352
+ #context "errors in hooks" do
353
+ #it "shows the error in a helpful way" do
354
+ #expect {
355
+ #deploy_hook.instance_eval('methedo_no_existo')
356
+ #}.to raise_error(NameError)
357
+ #out = read_output
358
+ #expect(out).to match(%r|FATAL:\s+Exception raised in hook .*/deploy/fake_test_hook.rb.|)
359
+ #expect(out).to match(%r|NameError: undefined local variable or method `methedo_no_existo' for|)
360
+ #expect(out).to match(%r|Please fix this error before retrying.|)
361
+ #end
362
+ #end
363
+
364
+ context "is compatible with older hook scripts" do
365
+ it "#current_role returns the first role" do
366
+ expect(deploy_hook('current_roles' => %w(a b)).instance_eval('current_role')).to eq('a')
367
+ end
368
+
369
+ it "has info, warning, debug, logged_system, and access to shell" do
370
+ expect(deploy_hook.instance_eval('respond_to?(:info) ')).to be_truthy
371
+ expect(deploy_hook.instance_eval('respond_to?(:warning) ')).to be_truthy
372
+ expect(deploy_hook.instance_eval('respond_to?(:debug) ')).to be_truthy
373
+ expect(deploy_hook.instance_eval('respond_to?(:logged_system)')).to be_truthy
374
+ expect(deploy_hook.instance_eval('respond_to?(:shell) ')).to be_truthy
375
+ end
376
+ end
377
+ end
378
+ end