engineyard-serverside 2.8.0.pre4 → 2.8.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 (261) hide show
  1. checksums.yaml +4 -4
  2. data/features/enable_maintenance/step_definitions/enable_maintenance_steps.rb +43 -0
  3. data/features/hook/running-a-deploy-hook.feature +277 -0
  4. data/features/hook/step_definitions/running-a-deploy-hook-steps.rb +200 -0
  5. data/features/step_definitions/app_steps.rb +10 -0
  6. data/features/step_definitions/command_steps.rb +8 -0
  7. data/features/step_definitions/server_steps.rb +14 -0
  8. data/features/step_definitions/version_steps.rb +5 -0
  9. data/features/support/env.rb +63 -0
  10. data/features/support/error_codes.rb +17 -0
  11. data/features/support/fs_helpers.rb +82 -0
  12. data/features/support/output_helpers.rb +7 -0
  13. data/features/support/runner.rb +41 -0
  14. data/features/version.feature +7 -0
  15. data/lib/engineyard-serverside/cli/app.rb +6 -0
  16. data/lib/engineyard-serverside/shell.rb +38 -10
  17. data/lib/engineyard-serverside/version.rb +1 -1
  18. data/spec/engineyard-serverside/callbacks/collection/combined_spec.rb +232 -0
  19. data/spec/engineyard-serverside/callbacks/collection/deploy_hooks_spec.rb +170 -0
  20. data/spec/engineyard-serverside/callbacks/collection/service_hooks/collection_spec.rb +171 -0
  21. data/spec/engineyard-serverside/callbacks/collection/service_hooks/combined_spec.rb +174 -0
  22. data/spec/engineyard-serverside/callbacks/collection/service_hooks_spec.rb +31 -0
  23. data/spec/engineyard-serverside/callbacks/collection_spec.rb +49 -0
  24. data/spec/engineyard-serverside/callbacks/distributor/remote_spec.rb +135 -0
  25. data/spec/engineyard-serverside/callbacks/distributor/viability_filter_spec.rb +208 -0
  26. data/spec/engineyard-serverside/callbacks/distributor_spec.rb +43 -0
  27. data/spec/engineyard-serverside/callbacks/executor/executable_spec.rb +386 -0
  28. data/spec/engineyard-serverside/callbacks/executor/ruby/context_spec.rb +538 -0
  29. data/spec/engineyard-serverside/callbacks/executor/ruby/executor_spec.rb +313 -0
  30. data/spec/engineyard-serverside/callbacks/executor/ruby_spec.rb +35 -0
  31. data/spec/engineyard-serverside/callbacks/executor_spec.rb +45 -0
  32. data/spec/engineyard-serverside/callbacks_spec.rb +31 -0
  33. data/spec/engineyard-serverside/cli/workflows/base_spec.rb +237 -0
  34. data/spec/engineyard-serverside/cli/workflows/calling_deploy_hooks_spec.rb +65 -0
  35. data/spec/engineyard-serverside/cli/workflows/deploying_applications_spec.rb +61 -0
  36. data/spec/engineyard-serverside/cli/workflows/disabling_maintenance_spec.rb +61 -0
  37. data/spec/engineyard-serverside/cli/workflows/enabling_maintenance_spec.rb +61 -0
  38. data/spec/engineyard-serverside/cli/workflows/helpers_spec.rb +64 -0
  39. data/spec/engineyard-serverside/cli/workflows/rolling_back_applications_spec.rb +61 -0
  40. data/spec/engineyard-serverside/cli/workflows/showing_maintenance_status_spec.rb +60 -0
  41. data/spec/engineyard-serverside/cli/workflows_spec.rb +87 -0
  42. data/spec/engineyard-serverside/dependency_manager/base_spec.rb +139 -0
  43. data/spec/engineyard-serverside/paths_spec.rb +820 -0
  44. data/spec/engineyard-serverside/propagator_spec.rb +56 -0
  45. data/spec/engineyard-serverside/server_spec.rb +390 -0
  46. data/spec/engineyard-serverside/shell/helpers_spec.rb +98 -0
  47. data/spec/engineyard-serverside/shell/yieldio_spec.rb +33 -0
  48. data/spec/engineyard-serverside/shell_spec.rb +543 -0
  49. data/spec/engineyard-serverside/slug/distributor_spec.rb +199 -0
  50. data/spec/engineyard-serverside/slug/enabler_spec.rb +191 -0
  51. data/spec/engineyard-serverside/slug/failure_handler_spec.rb +114 -0
  52. data/spec/engineyard-serverside/slug/finalizer_spec.rb +191 -0
  53. data/spec/engineyard-serverside/slug/generator_spec.rb +82 -0
  54. data/spec/engineyard-serverside/slug/migrator_spec.rb +137 -0
  55. data/spec/engineyard-serverside/slug/restarter_spec.rb +226 -0
  56. data/spec/engineyard-serverside/slug/source/updater_spec.rb +710 -0
  57. data/spec/engineyard-serverside/slug/source_spec.rb +40 -0
  58. data/spec/engineyard-serverside/source_spec.rb +171 -0
  59. data/spec/railway_spec.rb +130 -0
  60. data/spec/result/failure_spec.rb +113 -0
  61. data/spec/result/success_spec.rb +109 -0
  62. data/spec/result_spec.rb +23 -0
  63. data/spec/spec_helper.rb +3 -349
  64. metadata +182 -404
  65. data/spec/archive_deploy_spec.rb +0 -53
  66. data/spec/basic_deploy_spec.rb +0 -26
  67. data/spec/bundler_deploy_spec.rb +0 -160
  68. data/spec/configuration_spec.rb +0 -206
  69. data/spec/custom_deploy_spec.rb +0 -128
  70. data/spec/deploy_hook_spec.rb +0 -378
  71. data/spec/deprecation_spec.rb +0 -23
  72. data/spec/ey_yml_customized_deploy_spec.rb +0 -99
  73. data/spec/fixtures/gitrepo.tar.gz +0 -0
  74. data/spec/fixtures/invalid_hook.rb +0 -1
  75. data/spec/fixtures/lockfiles/0.9-no-bundler +0 -111
  76. data/spec/fixtures/lockfiles/0.9-with-bundler +0 -117
  77. data/spec/fixtures/lockfiles/1.0-no-bundler +0 -54
  78. data/spec/fixtures/lockfiles/1.0.0.rc.1-with-bundler +0 -162
  79. data/spec/fixtures/lockfiles/1.0.18-do_mysql +0 -88
  80. data/spec/fixtures/lockfiles/1.0.18-do_postgres +0 -79
  81. data/spec/fixtures/lockfiles/1.0.18-mysql +0 -43
  82. data/spec/fixtures/lockfiles/1.0.18-mysql2 +0 -43
  83. data/spec/fixtures/lockfiles/1.0.18-pg +0 -43
  84. data/spec/fixtures/lockfiles/1.0.6-no-bundler +0 -51
  85. data/spec/fixtures/lockfiles/1.0.6-with-any-bundler +0 -52
  86. data/spec/fixtures/lockfiles/1.0.6-with-bundler +0 -52
  87. data/spec/fixtures/lockfiles/1.15.1-no-bundler +0 -51
  88. data/spec/fixtures/lockfiles/1.3.1-rails-3.2.13 +0 -112
  89. data/spec/fixtures/lockfiles/not-a-lockfile +0 -1
  90. data/spec/fixtures/repos/assets_detected/Gemfile +0 -5
  91. data/spec/fixtures/repos/assets_detected/Gemfile.lock +0 -88
  92. data/spec/fixtures/repos/assets_detected/README +0 -1
  93. data/spec/fixtures/repos/assets_detected/Rakefile +0 -5
  94. data/spec/fixtures/repos/assets_detected/app/assets/empty +0 -0
  95. data/spec/fixtures/repos/assets_detected/config/application.rb +0 -5
  96. data/spec/fixtures/repos/assets_detected/config/ey.yml +0 -3
  97. data/spec/fixtures/repos/assets_disabled/Gemfile +0 -5
  98. data/spec/fixtures/repos/assets_disabled/Gemfile.lock +0 -88
  99. data/spec/fixtures/repos/assets_disabled/README +0 -1
  100. data/spec/fixtures/repos/assets_disabled/Rakefile +0 -6
  101. data/spec/fixtures/repos/assets_disabled/app/assets/empty +0 -0
  102. data/spec/fixtures/repos/assets_disabled/config/application.rb +0 -5
  103. data/spec/fixtures/repos/assets_disabled/config/ey.yml +0 -3
  104. data/spec/fixtures/repos/assets_disabled_in_ey_yml/Gemfile +0 -5
  105. data/spec/fixtures/repos/assets_disabled_in_ey_yml/Gemfile.lock +0 -88
  106. data/spec/fixtures/repos/assets_disabled_in_ey_yml/README +0 -1
  107. data/spec/fixtures/repos/assets_disabled_in_ey_yml/Rakefile +0 -6
  108. data/spec/fixtures/repos/assets_disabled_in_ey_yml/app/assets/empty +0 -0
  109. data/spec/fixtures/repos/assets_disabled_in_ey_yml/config/application.rb +0 -5
  110. data/spec/fixtures/repos/assets_disabled_in_ey_yml/config/ey.yml +0 -5
  111. data/spec/fixtures/repos/assets_disabled_utf8/Gemfile +0 -5
  112. data/spec/fixtures/repos/assets_disabled_utf8/Gemfile.lock +0 -88
  113. data/spec/fixtures/repos/assets_disabled_utf8/README +0 -3
  114. data/spec/fixtures/repos/assets_disabled_utf8/Rakefile +0 -5
  115. data/spec/fixtures/repos/assets_disabled_utf8/app/assets/empty +0 -0
  116. data/spec/fixtures/repos/assets_disabled_utf8/config/application.rb +0 -7
  117. data/spec/fixtures/repos/assets_disabled_utf8/config/ey.yml +0 -3
  118. data/spec/fixtures/repos/assets_enabled_all/Gemfile +0 -5
  119. data/spec/fixtures/repos/assets_enabled_all/Gemfile.lock +0 -88
  120. data/spec/fixtures/repos/assets_enabled_all/README +0 -1
  121. data/spec/fixtures/repos/assets_enabled_all/app/assets/empty +0 -0
  122. data/spec/fixtures/repos/assets_enabled_all/config/application.rb +0 -5
  123. data/spec/fixtures/repos/assets_enabled_all/config/ey.yml +0 -6
  124. data/spec/fixtures/repos/assets_enabled_all/script/assets +0 -5
  125. data/spec/fixtures/repos/assets_enabled_all/tmp/obstruction +0 -1
  126. data/spec/fixtures/repos/assets_enabled_in_ey_yml/Gemfile +0 -3
  127. data/spec/fixtures/repos/assets_enabled_in_ey_yml/Gemfile.lock +0 -10
  128. data/spec/fixtures/repos/assets_enabled_in_ey_yml/README +0 -1
  129. data/spec/fixtures/repos/assets_enabled_in_ey_yml/Rakefile +0 -8
  130. data/spec/fixtures/repos/assets_enabled_in_ey_yml/config/ey.yml +0 -4
  131. data/spec/fixtures/repos/assets_enabled_util_only/Gemfile +0 -5
  132. data/spec/fixtures/repos/assets_enabled_util_only/Gemfile.lock +0 -88
  133. data/spec/fixtures/repos/assets_enabled_util_only/README +0 -1
  134. data/spec/fixtures/repos/assets_enabled_util_only/Rakefile +0 -6
  135. data/spec/fixtures/repos/assets_enabled_util_only/app/assets/empty +0 -0
  136. data/spec/fixtures/repos/assets_enabled_util_only/config/application.rb +0 -5
  137. data/spec/fixtures/repos/assets_enabled_util_only/config/ey.yml +0 -6
  138. data/spec/fixtures/repos/assets_error/Gemfile +0 -5
  139. data/spec/fixtures/repos/assets_error/Gemfile.lock +0 -88
  140. data/spec/fixtures/repos/assets_error/README +0 -1
  141. data/spec/fixtures/repos/assets_error/Rakefile +0 -4
  142. data/spec/fixtures/repos/assets_error/app/assets/empty +0 -0
  143. data/spec/fixtures/repos/assets_error/config/application.rb +0 -5
  144. data/spec/fixtures/repos/assets_error/config/ey.yml +0 -4
  145. data/spec/fixtures/repos/assets_in_hook/Gemfile +0 -5
  146. data/spec/fixtures/repos/assets_in_hook/Gemfile.lock +0 -88
  147. data/spec/fixtures/repos/assets_in_hook/README +0 -2
  148. data/spec/fixtures/repos/assets_in_hook/Rakefile +0 -5
  149. data/spec/fixtures/repos/assets_in_hook/app/assets/empty +0 -0
  150. data/spec/fixtures/repos/assets_in_hook/config/application.rb +0 -5
  151. data/spec/fixtures/repos/assets_in_hook/config/ey.yml +0 -3
  152. data/spec/fixtures/repos/assets_in_hook/deploy/before_compile_assets.rb +0 -2
  153. data/spec/fixtures/repos/bundle_fails/Gemfile +0 -1
  154. data/spec/fixtures/repos/bundle_fails/README +0 -1
  155. data/spec/fixtures/repos/bundle_fails/deploy/after_bundle.rb +0 -1
  156. data/spec/fixtures/repos/bundler_disabled/Gemfile +0 -4
  157. data/spec/fixtures/repos/bundler_disabled/Gemfile.lock +0 -12
  158. data/spec/fixtures/repos/bundler_disabled/README +0 -1
  159. data/spec/fixtures/repos/bundler_disabled/config/ey.yml +0 -2
  160. data/spec/fixtures/repos/bundler_disabled/deploy/after_bundle.rb +0 -1
  161. data/spec/fixtures/repos/bundler_disabled/deploy/before_bundle.rb +0 -1
  162. data/spec/fixtures/repos/bundler_old/Gemfile +0 -5
  163. data/spec/fixtures/repos/bundler_old/Gemfile.lock +0 -15
  164. data/spec/fixtures/repos/bundler_old/README +0 -1
  165. data/spec/fixtures/repos/default/Gemfile +0 -4
  166. data/spec/fixtures/repos/default/Gemfile.lock +0 -12
  167. data/spec/fixtures/repos/default/README +0 -5
  168. data/spec/fixtures/repos/default/ey.yml +0 -3
  169. data/spec/fixtures/repos/executable_hooks/README +0 -1
  170. data/spec/fixtures/repos/executable_hooks/deploy/before_restart +0 -72
  171. data/spec/fixtures/repos/executable_hooks_not_executable/README +0 -3
  172. data/spec/fixtures/repos/executable_hooks_not_executable/deploy/before_restart +0 -3
  173. data/spec/fixtures/repos/ey_yml/Gemfile +0 -4
  174. data/spec/fixtures/repos/ey_yml/Gemfile.lock +0 -12
  175. data/spec/fixtures/repos/ey_yml/README +0 -1
  176. data/spec/fixtures/repos/ey_yml/config/ey.yml +0 -18
  177. data/spec/fixtures/repos/ey_yml/deploy/before_migrate.rb +0 -6
  178. data/spec/fixtures/repos/ey_yml_alt/Gemfile +0 -4
  179. data/spec/fixtures/repos/ey_yml_alt/Gemfile.lock +0 -12
  180. data/spec/fixtures/repos/ey_yml_alt/README +0 -1
  181. data/spec/fixtures/repos/ey_yml_alt/deploy/before_migrate.rb +0 -6
  182. data/spec/fixtures/repos/ey_yml_alt/ey.yml +0 -12
  183. data/spec/fixtures/repos/hook_fails/README +0 -1
  184. data/spec/fixtures/repos/hook_fails/deploy/before_deploy.rb +0 -1
  185. data/spec/fixtures/repos/hooks/README +0 -1
  186. data/spec/fixtures/repos/hooks/deploy/after_bundle.rb +0 -1
  187. data/spec/fixtures/repos/hooks/deploy/after_compile_assets.rb +0 -1
  188. data/spec/fixtures/repos/hooks/deploy/after_deploy.rb +0 -1
  189. data/spec/fixtures/repos/hooks/deploy/after_migrate.rb +0 -1
  190. data/spec/fixtures/repos/hooks/deploy/after_restart.rb +0 -1
  191. data/spec/fixtures/repos/hooks/deploy/after_symlink.rb +0 -1
  192. data/spec/fixtures/repos/hooks/deploy/before_bundle.rb +0 -1
  193. data/spec/fixtures/repos/hooks/deploy/before_compile_assets.rb +0 -1
  194. data/spec/fixtures/repos/hooks/deploy/before_deploy.rb +0 -1
  195. data/spec/fixtures/repos/hooks/deploy/before_migrate.rb +0 -1
  196. data/spec/fixtures/repos/hooks/deploy/before_restart.rb +0 -1
  197. data/spec/fixtures/repos/hooks/deploy/before_symlink.rb +0 -1
  198. data/spec/fixtures/repos/multi_dep_manager/README +0 -1
  199. data/spec/fixtures/repos/multi_dep_manager/composer.json +0 -5
  200. data/spec/fixtures/repos/multi_dep_manager/composer.lock +0 -462
  201. data/spec/fixtures/repos/multi_dep_manager/package.json +0 -7
  202. data/spec/fixtures/repos/multi_dep_manager/public/index.php +0 -4
  203. data/spec/fixtures/repos/no_ey_config/Gemfile +0 -3
  204. data/spec/fixtures/repos/no_ey_config/Gemfile.lock +0 -10
  205. data/spec/fixtures/repos/no_ey_config/README +0 -1
  206. data/spec/fixtures/repos/no_ey_config/ey.yml +0 -3
  207. data/spec/fixtures/repos/no_ey_config_no_warning/Gemfile +0 -3
  208. data/spec/fixtures/repos/no_ey_config_no_warning/Gemfile.lock +0 -10
  209. data/spec/fixtures/repos/no_ey_config_no_warning/README +0 -1
  210. data/spec/fixtures/repos/no_ey_config_no_warning/ey.yml +0 -5
  211. data/spec/fixtures/repos/no_gemfile_lock/Gemfile +0 -4
  212. data/spec/fixtures/repos/no_gemfile_lock/README +0 -1
  213. data/spec/fixtures/repos/no_gemfile_lock/ey.yml +0 -3
  214. data/spec/fixtures/repos/nodejs/README +0 -1
  215. data/spec/fixtures/repos/nodejs/package.json +0 -7
  216. data/spec/fixtures/repos/not_bundled/README +0 -1
  217. data/spec/fixtures/repos/npm_disabled/README +0 -1
  218. data/spec/fixtures/repos/npm_disabled/config/ey.yml +0 -2
  219. data/spec/fixtures/repos/npm_disabled/package.json +0 -7
  220. data/spec/fixtures/repos/php_composer_disabled/README +0 -1
  221. data/spec/fixtures/repos/php_composer_disabled/composer.json +0 -5
  222. data/spec/fixtures/repos/php_composer_disabled/composer.lock +0 -462
  223. data/spec/fixtures/repos/php_composer_disabled/config/ey.yml +0 -2
  224. data/spec/fixtures/repos/php_composer_disabled/public/index.php +0 -4
  225. data/spec/fixtures/repos/php_composer_lock/README +0 -1
  226. data/spec/fixtures/repos/php_composer_lock/composer.json +0 -5
  227. data/spec/fixtures/repos/php_composer_lock/composer.lock +0 -462
  228. data/spec/fixtures/repos/php_composer_lock/public/index.php +0 -4
  229. data/spec/fixtures/repos/php_no_composer_lock/README +0 -1
  230. data/spec/fixtures/repos/php_no_composer_lock/composer.json +0 -21
  231. data/spec/fixtures/repos/php_no_composer_lock/public/index.php +0 -4
  232. data/spec/fixtures/repos/public_system/Gemfile +0 -4
  233. data/spec/fixtures/repos/public_system/Gemfile.lock +0 -12
  234. data/spec/fixtures/repos/public_system/README +0 -5
  235. data/spec/fixtures/repos/public_system/ey.yml +0 -3
  236. data/spec/fixtures/repos/public_system/public/system/cant_touch_this.txt +0 -3
  237. data/spec/fixtures/repos/sqlite3/Gemfile +0 -4
  238. data/spec/fixtures/repos/sqlite3/Gemfile.lock +0 -89
  239. data/spec/fixtures/repos/sqlite3/README +0 -1
  240. data/spec/fixtures/retwisj.war +0 -0
  241. data/spec/fixtures/valid_hook.rb +0 -1
  242. data/spec/git_strategy_spec.rb +0 -34
  243. data/spec/lockfile_parser_spec.rb +0 -126
  244. data/spec/maintenance_spec.rb +0 -44
  245. data/spec/multi_dependency_manager_spec.rb +0 -25
  246. data/spec/nodejs_deploy_spec.rb +0 -30
  247. data/spec/php_deploy_spec.rb +0 -81
  248. data/spec/platform_configure_spec.rb +0 -61
  249. data/spec/rails31_deploy_spec.rb +0 -172
  250. data/spec/restart_spec.rb +0 -43
  251. data/spec/rollback_spec.rb +0 -87
  252. data/spec/server_spec.rb +0 -70
  253. data/spec/services_deploy_spec.rb +0 -165
  254. data/spec/shell_spec.rb +0 -57
  255. data/spec/source/archive_spec.rb +0 -33
  256. data/spec/source/git_spec.rb +0 -44
  257. data/spec/sqlite3_deploy_spec.rb +0 -38
  258. data/spec/support/integration.rb +0 -103
  259. data/spec/support/source_doubles.rb +0 -28
  260. data/spec/support/timecop.rb +0 -5
  261. data/spec/symlink_spec.rb +0 -15
@@ -0,0 +1,313 @@
1
+ require 'spec_helper'
2
+
3
+ require 'result'
4
+
5
+ require 'engineyard-serverside/callbacks/executor/ruby/executor'
6
+
7
+ module EY
8
+ module Serverside
9
+ module Callbacks
10
+ module Executor
11
+
12
+ module Ruby
13
+ describe Executor do
14
+ let(:config) {Object.new}
15
+ let(:shell) {Object.new}
16
+ let(:paths) {Object.new}
17
+ let(:hook) {Object.new}
18
+ let(:active_release_path) {'/path/to/the/active/release'}
19
+ let(:hook_path) {'/path/to/the/dang/hook.rb'}
20
+ let(:hook_content) {
21
+ 'puts "My sausages turned to gold!"'
22
+ }
23
+ let(:syntax_error) {'OMG what bad syntax'}
24
+
25
+ let(:executor) {described_class.new(config, shell, hook)}
26
+
27
+ before(:each) do
28
+ allow(hook).to receive(:path).and_return(hook_path)
29
+ allow(hook).to receive(:read).and_return(hook_content)
30
+
31
+ allow(shell).to receive(:info)
32
+ allow(shell).to receive(:fatal)
33
+ allow(shell).to receive(:warning)
34
+
35
+ allow(config).to receive(:paths).and_return(paths)
36
+
37
+ allow(paths).to receive(:active_release).and_return(active_release_path)
38
+ end
39
+
40
+ it 'is a Railway' do
41
+ expect(executor).to be_a(Railway)
42
+ end
43
+
44
+ it 'has the exact steps for executing a Ruby hook' do
45
+ steps = described_class.steps.map {|s| s[:name]}
46
+
47
+ expect(steps).to eql(
48
+ [
49
+ :validate_hook,
50
+ :display_deprecation_warnings,
51
+ :announce_execution,
52
+ :context_eval
53
+ ]
54
+ )
55
+ end
56
+
57
+ describe '#validate_hook' do
58
+ let(:input) {
59
+ {}
60
+ }
61
+
62
+ let(:result) {executor.validate_hook}
63
+
64
+ context 'when ruby reports good syntax' do
65
+ before(:each) do
66
+ allow(executor).
67
+ to receive(:`).
68
+ and_return('Syntax OK')
69
+ end
70
+
71
+ it 'is a Success' do
72
+ expect(result).to be_a(Result::Success)
73
+ end
74
+
75
+ it 'contains the hook code' do
76
+ expect(result.value[:code]).to eql(hook_content)
77
+ end
78
+ end
79
+
80
+ context 'when ruby reports bad syntax' do
81
+ before(:each) do
82
+ allow(executor).
83
+ to receive(:`).
84
+ and_return(syntax_error)
85
+ end
86
+
87
+ it 'is a failure' do
88
+ expect(result).to be_a(Result::Failure)
89
+ end
90
+
91
+ it 'the reason for the failure is a syntax error' do
92
+ expect(result.error[:reason]).to eql(:syntax_error)
93
+ end
94
+
95
+ it 'contains the actual syntax error' do
96
+ expect(result.error[:syntax_error]).to eql(syntax_error)
97
+ end
98
+
99
+ end
100
+ end
101
+
102
+ describe '#display_deprecation_warnings' do
103
+ let(:input) {
104
+ {
105
+ :code => hook_content
106
+ }
107
+ }
108
+
109
+ let(:result) {executor.display_deprecation_warnings(input)}
110
+
111
+ context 'when there are @configuration references in the hook' do
112
+ let(:hook_content) {'@configuration == "my jam"'}
113
+ let(:warning_message) {
114
+ "Use of `@configuration` in deploy hooks is deprecated.\nPlease use `config`, which provides access to the same object.\n\tin #{hook_path}"
115
+ }
116
+
117
+ it 'prints a warning regarding that usage' do
118
+ expect(shell).
119
+ to receive(:warning).
120
+ with(warning_message)
121
+
122
+ result
123
+ end
124
+ end
125
+
126
+ context 'when there are @node references in the hook' do
127
+ let(:hook_content) {'@node == "my jam"'}
128
+ let(:warning_message) {
129
+ "Use of `@node` in deploy hooks is deprecated.\nPlease use `config.node`, which provides access to the same object.\n\tin #{hook_path}"
130
+ }
131
+
132
+ it 'prints a warning regarding that usage' do
133
+ expect(shell).
134
+ to receive(:warning).
135
+ with(warning_message)
136
+
137
+ result
138
+ end
139
+ end
140
+
141
+ it 'is a Success' do
142
+ expect(result).to be_a(Result::Success)
143
+ end
144
+
145
+ it 'does not alter the input' do
146
+ expect(result.value).to eql(input)
147
+ end
148
+
149
+ end
150
+
151
+ describe '#announce_execution' do
152
+ let(:input) {
153
+ {
154
+ :code => hook_content
155
+ }
156
+ }
157
+
158
+ let(:result) {executor.announce_execution(input)}
159
+
160
+ it 'lets the user know that the hook is being executed' do
161
+ expect(shell).to receive(:info).with("Executing #{hook_path} ...")
162
+
163
+ result
164
+ end
165
+
166
+ it 'is a Success' do
167
+ expect(result).to be_a(Result::Success)
168
+ end
169
+
170
+ it 'does not alter the input' do
171
+ expect(result.value).to eql(input)
172
+ end
173
+ end
174
+
175
+ describe '#context_eval' do
176
+ let(:ruby_context) {Object.new}
177
+ let(:input) {
178
+ {
179
+ :code => hook_content
180
+ }
181
+ }
182
+
183
+ let(:result) {executor.context_eval(input)}
184
+
185
+ before(:each) do
186
+ allow(Dir).to receive(:chdir).and_yield
187
+
188
+ allow(Context).
189
+ to receive(:new).
190
+ and_return(ruby_context)
191
+
192
+ allow(ruby_context).to receive(:instance_eval)
193
+ end
194
+
195
+ it 'switches to the active release directory' do
196
+ expect(Dir).to receive(:chdir).with(active_release_path).and_yield
197
+
198
+ result
199
+ end
200
+
201
+ it 'attempts to execute the hook via a new context' do
202
+ expect(ruby_context).to receive(:instance_eval).with(hook_content)
203
+
204
+ result
205
+ end
206
+
207
+ context 'when the hook executes without issue' do
208
+ it 'is a Success' do
209
+ expect(result).to be_a(Result::Success)
210
+ end
211
+
212
+ it 'does not modify its input' do
213
+ expect(result.value).to eql(input)
214
+ end
215
+ end
216
+
217
+ context 'when the hook raises an exception' do
218
+ let(:exception_message) {'nine kinds of calamity'}
219
+
220
+ before(:each) do
221
+ allow(ruby_context).
222
+ to receive(:instance_eval).
223
+ with(hook_content).
224
+ and_raise(exception_message)
225
+ end
226
+
227
+ it 'is a Failure' do
228
+ expect(result).to be_a(Result::Failure)
229
+ end
230
+
231
+ it 'has a failed execution reason' do
232
+ expect(result.error[:reason]).to eql(:execution_failed)
233
+ end
234
+
235
+ it 'includes the raised exception' do
236
+ expect(result.error[:exception].to_s).
237
+ to eql(exception_message)
238
+ end
239
+ end
240
+ end
241
+
242
+ describe '#handle_failure' do
243
+ let(:reason) {nil}
244
+ let(:exception) {nil}
245
+
246
+ let(:payload) {
247
+ {
248
+ :code => hook_content,
249
+ :reason => reason,
250
+ :exception => exception,
251
+ :syntax_error => syntax_error
252
+ }
253
+ }
254
+
255
+ let(:result) {executor.handle_failure(payload)}
256
+
257
+ before(:each) do
258
+ allow(executor).to receive(:abort)
259
+ end
260
+
261
+ context 'when the failure was due to a failed execution' do
262
+ let(:exception_message) {'cats have cute little nosies'}
263
+ let(:exception) {RuntimeError.new(exception_message)}
264
+ let(:reason) {:execution_failed}
265
+
266
+ it 'logs the exception' do
267
+ expect(shell).to receive(:fatal).with(" Exception raised in hook #{hook_path}.\n\n RuntimeError: #{exception_message}\n\n Please fix this error before retrying.\n")
268
+
269
+ begin
270
+ result
271
+ rescue
272
+ end
273
+ end
274
+
275
+ it 're-raises the exception' do
276
+ expect {result}.to raise_exception(exception)
277
+ end
278
+ end
279
+
280
+ context 'when the failure was due to a syntax error' do
281
+ let(:reason) {:syntax_error}
282
+ let(:abort_message) {
283
+ "*** [Error] Invalid Ruby syntax in hook: #{hook_path} ***\n*** #{syntax_error} ***"
284
+ }
285
+
286
+ it 'aborts with a message regarding the syntax error' do
287
+ expect(executor).to receive(:abort).with(abort_message)
288
+
289
+ result
290
+ end
291
+ end
292
+
293
+ context 'when the failure was due to some unknown problem' do
294
+ let(:reason) {nil}
295
+ let(:abort_message) {
296
+ "*** [Error] An unknown error occurred for hook: #{hook_path} ***"
297
+ }
298
+
299
+ it 'abors with a message regarding the unknown error' do
300
+ expect(executor).to receive(:abort).with(abort_message)
301
+
302
+ result
303
+ end
304
+
305
+ end
306
+ end
307
+ end
308
+
309
+ end
310
+ end
311
+ end
312
+ end
313
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ require 'result'
4
+
5
+ require 'engineyard-serverside/callbacks/executor/ruby'
6
+
7
+ module EY
8
+ module Serverside
9
+ module Callbacks
10
+ module Executor
11
+
12
+ describe Ruby do
13
+ let(:config) {Object.new}
14
+ let(:shell) {Object.new}
15
+ let(:hook) {Object.new}
16
+
17
+ describe '.execute' do
18
+ let(:result) {described_class.execute(config, shell, hook)}
19
+
20
+ it 'forwards the execution to a ruby executor' do
21
+ expect(described_class::Executor).
22
+ to receive(:execute).
23
+ with(config, shell, hook)
24
+
25
+ result
26
+ end
27
+
28
+ end
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+ end
35
+
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ require 'pathname'
4
+
5
+ require 'result'
6
+ require 'engineyard-serverside/callbacks/executor'
7
+
8
+ module EY
9
+ module Serverside
10
+ module Callbacks
11
+
12
+ describe Executor do
13
+ let(:config) {Object.new}
14
+ let(:shell) {Object.new}
15
+ let(:ruby_hook) {Object.new}
16
+ let(:executable_hook) {Object.new}
17
+ let(:hooks) {[ruby_hook, executable_hook]}
18
+
19
+ before(:each) do
20
+ allow(ruby_hook).to receive(:flavor).and_return(:ruby)
21
+ allow(executable_hook).to receive(:flavor).and_return(:executable)
22
+ end
23
+
24
+ describe '.execute' do
25
+ let(:result) {described_class.execute(config, shell, hooks)}
26
+
27
+ it 'dispatches each hook to the proper executor' do
28
+ expect(described_class::Ruby).
29
+ to receive(:execute).
30
+ with(config, shell, ruby_hook)
31
+
32
+ expect(described_class::Executable).
33
+ to receive(:execute).
34
+ with(config, shell, executable_hook)
35
+
36
+ result
37
+ end
38
+
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ require 'engineyard-serverside/callbacks'
4
+
5
+ module EY
6
+ module Serverside
7
+ describe Callbacks do
8
+ describe '.load' do
9
+ let(:paths) {Object.new}
10
+ let(:collection) {Object.new}
11
+ let(:result) {described_class.load(paths)}
12
+
13
+ before(:each) do
14
+ allow(described_class::Collection).
15
+ to receive(:load).
16
+ and_return(collection)
17
+ end
18
+
19
+ it 'loads a collection' do
20
+ expect(described_class::Collection).to receive(:load).with(paths)
21
+
22
+ result
23
+ end
24
+
25
+ it 'is a callbacks collection' do
26
+ expect(result).to eql(collection)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,237 @@
1
+ require 'spec_helper'
2
+
3
+ require 'engineyard-serverside/cli/workflows/base'
4
+
5
+ module EY
6
+ module Serverside
7
+ module CLI
8
+ module Workflows
9
+ describe Base do
10
+ let(:shell) {Object.new}
11
+ let(:config) {Object.new}
12
+ let(:options) {{}}
13
+ let(:workflow) {described_class.new(options)}
14
+
15
+ before(:each) do
16
+ # Both the Shell and Deploy::Configuration classes are used in
17
+ # the Workflow private API. However, since we're not actually
18
+ # testing their behavior (nor that of an actual workflow) here,
19
+ # we'll need to make sure that we can use them in a predictable
20
+ # way.
21
+ allow(EY::Serverside::Shell).
22
+ to receive(:new).
23
+ and_return(shell)
24
+
25
+ allow(EY::Serverside::Deploy::Configuration).
26
+ to receive(:new).
27
+ and_return(config)
28
+
29
+ allow(shell).to receive(:fatal)
30
+ allow(shell).to receive(:debug)
31
+
32
+ allow(config).to receive(:verbose)
33
+ allow(config).to receive(:app)
34
+ end
35
+
36
+ describe '#options' do
37
+ it 'is the options passed in during creation' do
38
+ expect(workflow.options).to eql(options)
39
+ end
40
+ end
41
+
42
+ describe '#perform' do
43
+ let(:perform) {workflow.perform}
44
+
45
+ before(:each) do
46
+ # Technically, this is against the rules, because I'm stubbing
47
+ # methods on the object under test. They're private methods,
48
+ # though, so I reckon that's probably acceptable.
49
+ allow(workflow).to receive(:procedure)
50
+ allow(workflow).to receive(:task_name)
51
+ end
52
+
53
+ it 'announces the serverside init' do
54
+ expect(shell).
55
+ to receive(:debug).
56
+ with("Initializing #{EY::Serverside::About.name_with_version}.")
57
+
58
+ perform
59
+ end
60
+
61
+ it 'calls its internal procedure' do
62
+ expect(workflow).to receive(:procedure)
63
+
64
+ perform
65
+ end
66
+
67
+ context 'when the procedure raises a remote failure' do
68
+ let(:error_message) {'onoes'}
69
+
70
+ before(:each) do
71
+ allow(workflow).
72
+ to receive(:procedure).
73
+ and_raise(EY::Serverside::RemoteFailure.new(error_message))
74
+
75
+ end
76
+
77
+ it 'logs a fatal error and re-raises' do
78
+ expect(shell).to receive(:fatal).with(error_message)
79
+
80
+ expect {perform}.to raise_error(EY::Serverside::RemoteFailure)
81
+ end
82
+ end
83
+
84
+ context 'when the procedure raises an unhandled exception' do
85
+ let(:error_message) {'the system is down'}
86
+ let(:exception) {Exception.new(error_message)}
87
+
88
+ before(:each) do
89
+ allow(workflow).
90
+ to receive(:procedure).
91
+ and_raise(exception)
92
+
93
+ # Apparently, instantiating an exception in specs gets a bit
94
+ # wonky.
95
+ allow(exception).to receive(:backtrace).and_return(['darn'])
96
+ end
97
+
98
+ it 'logs a fatal error and re-raises' do
99
+ expect(shell).
100
+ to receive(:fatal).
101
+ with("#{exception.backtrace[0]}: #{exception.message} (#{exception.class})")
102
+
103
+ expect {perform}.to raise_error(exception)
104
+ end
105
+ end
106
+
107
+ end
108
+
109
+ describe '.perform' do
110
+ let(:dummy) {Object.new}
111
+ let(:perform) {described_class.perform(options)}
112
+
113
+ it 'calls #perform on a new instance' do
114
+ expect(described_class).
115
+ to receive(:new).
116
+ with(options).
117
+ and_return(dummy)
118
+
119
+ expect(dummy).to receive(:perform)
120
+
121
+ perform
122
+ end
123
+ end
124
+
125
+ context 'private API' do
126
+ describe '#procedure' do
127
+ let(:procedure) {workflow.instance_eval {procedure}}
128
+
129
+ it 'must be defined in a subclass' do
130
+ expect {procedure}.
131
+ to raise_error(
132
+ Undefined,
133
+ "You must define the private procedure method for your workflow."
134
+ )
135
+ end
136
+ end
137
+
138
+ describe '#task_name' do
139
+ let(:task_name) {workflow.instance_eval {task_name}}
140
+
141
+ it 'must be defined in a subclass' do
142
+ expect {task_name}.
143
+ to raise_error(
144
+ Undefined,
145
+ "You must define the private task_name method for your workflow."
146
+ )
147
+ end
148
+ end
149
+
150
+ describe '#config' do
151
+ it 'is a Deploy Configuration for our options' do
152
+ expect(EY::Serverside::Deploy::Configuration).
153
+ to receive(:new).
154
+ with(options).
155
+ and_return(config)
156
+
157
+ expect(workflow.instance_eval {config}).to eql(config)
158
+ end
159
+ end
160
+
161
+ describe '#shell' do
162
+ before(:each) do
163
+ allow(config).to receive(:app).and_return('denied')
164
+ allow(workflow).to receive(:task_name).and_return('george')
165
+ end
166
+
167
+ it 'is a Shell' do
168
+ expect(EY::Serverside::Shell).
169
+ to receive(:new).
170
+ with(
171
+ :verbose => config.verbose,
172
+ :log_path => File.join(
173
+ ENV['HOME'],
174
+ "#{config.app}-#{workflow.instance_eval {task_name}}.log"
175
+ )
176
+ ).
177
+ and_return(shell)
178
+
179
+ expect(workflow.instance_eval {shell}).to eql(shell)
180
+ end
181
+ end
182
+
183
+ describe '#servers' do
184
+ let(:server_hashes) {[]}
185
+ let(:collection) {Object.new}
186
+ let(:servers) {workflow.instance_eval {servers}}
187
+
188
+ before(:each) do
189
+ allow(workflow).to receive(:task_name)
190
+ end
191
+
192
+ it 'is the servers applicable to the workflow' do
193
+ expect(EY::Serverside::CLI::ServerHashExtractor).
194
+ to receive(:hashes).
195
+ with(options, config).
196
+ and_return(server_hashes)
197
+
198
+ expect(EY::Serverside::Servers).
199
+ to receive(:from_hashes).
200
+ with(server_hashes, shell).
201
+ and_return(collection)
202
+
203
+ expect(servers).to eql(collection)
204
+ end
205
+ end
206
+
207
+ describe '#propagate_serverside' do
208
+ let(:servers) {Object.new}
209
+
210
+ let(:propagate_serverside) {
211
+ workflow.instance_eval {propagate_serverside}
212
+ }
213
+
214
+ before(:each) do
215
+ allow(workflow).to receive(:task_name)
216
+ end
217
+
218
+ it 'propagates engineyard-serverside to the workflow servers' do
219
+ expect(workflow).to receive(:servers).and_return(servers)
220
+
221
+ expect(EY::Serverside::Propagator).
222
+ to receive(:propagate).
223
+ with(servers, shell)
224
+
225
+ propagate_serverside
226
+ end
227
+ end
228
+
229
+
230
+
231
+ end
232
+
233
+ end
234
+ end
235
+ end
236
+ end
237
+ end