whisk_deploy 0.6.26

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 (177) hide show
  1. data/CHANGELOG +292 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.integration_specs +24 -0
  4. data/README.markdown +832 -0
  5. data/Rakefile +105 -0
  6. data/VERSION +1 -0
  7. data/WHY.txt +45 -0
  8. data/bin/wd +61 -0
  9. data/bin/wd_role +42 -0
  10. data/examples/deploy-configs.yml +13 -0
  11. data/examples/deploy-local.yml +4 -0
  12. data/examples/deploy-multiple-remotes.yml +26 -0
  13. data/examples/deploy-staging.yml +8 -0
  14. data/examples/deploy.rake +11 -0
  15. data/examples/deploy.yml +16 -0
  16. data/init.rb +1 -0
  17. data/install.rb +5 -0
  18. data/lib/whiskey_disk.rb +327 -0
  19. data/lib/whiskey_disk/config.rb +127 -0
  20. data/lib/whiskey_disk/config/abstract_filter.rb +19 -0
  21. data/lib/whiskey_disk/config/filter.rb +48 -0
  22. data/lib/whiskey_disk/config/filters/add_environment_name_filter.rb +11 -0
  23. data/lib/whiskey_disk/config/filters/add_project_name_filter.rb +11 -0
  24. data/lib/whiskey_disk/config/filters/check_for_duplicate_domains_filter.rb +21 -0
  25. data/lib/whiskey_disk/config/filters/convert_role_strings_to_list_filter.rb +20 -0
  26. data/lib/whiskey_disk/config/filters/default_config_target_filter.rb +12 -0
  27. data/lib/whiskey_disk/config/filters/default_domain_filter.rb +12 -0
  28. data/lib/whiskey_disk/config/filters/drop_empty_domain_roles_filter.rb +32 -0
  29. data/lib/whiskey_disk/config/filters/environment_scope_filter.rb +20 -0
  30. data/lib/whiskey_disk/config/filters/hashify_domain_entries_filter.rb +29 -0
  31. data/lib/whiskey_disk/config/filters/localize_domains_filter.rb +24 -0
  32. data/lib/whiskey_disk/config/filters/modules/scope_helper.rb +11 -0
  33. data/lib/whiskey_disk/config/filters/normalize_ssh_options_filter.rb +29 -0
  34. data/lib/whiskey_disk/config/filters/project_scope_filter.rb +34 -0
  35. data/lib/whiskey_disk/config/filters/select_project_and_environment_filter.rb +12 -0
  36. data/lib/whiskey_disk/config/filters/stringify_hash_keys_filter.rb +25 -0
  37. data/lib/whiskey_disk/helpers.rb +50 -0
  38. data/lib/whiskey_disk/rake.rb +47 -0
  39. data/scenarios/git_repositories/config.git/HEAD +1 -0
  40. data/scenarios/git_repositories/config.git/config +5 -0
  41. data/scenarios/git_repositories/config.git/description +1 -0
  42. data/scenarios/git_repositories/config.git/git-daemon-export-ok +0 -0
  43. data/scenarios/git_repositories/config.git/hooks/applypatch-msg.sample +15 -0
  44. data/scenarios/git_repositories/config.git/hooks/commit-msg.sample +24 -0
  45. data/scenarios/git_repositories/config.git/hooks/post-commit.sample +8 -0
  46. data/scenarios/git_repositories/config.git/hooks/post-receive.sample +15 -0
  47. data/scenarios/git_repositories/config.git/hooks/post-update.sample +8 -0
  48. data/scenarios/git_repositories/config.git/hooks/pre-applypatch.sample +14 -0
  49. data/scenarios/git_repositories/config.git/hooks/pre-commit.sample +46 -0
  50. data/scenarios/git_repositories/config.git/hooks/pre-rebase.sample +169 -0
  51. data/scenarios/git_repositories/config.git/hooks/prepare-commit-msg.sample +36 -0
  52. data/scenarios/git_repositories/config.git/hooks/update.sample +128 -0
  53. data/scenarios/git_repositories/config.git/info/exclude +6 -0
  54. data/scenarios/git_repositories/config.git/objects/0d/b14dd6ddc54017c0a11960dcda82ed802cde69 +0 -0
  55. data/scenarios/git_repositories/config.git/objects/0e/e781f5ce80d64db32a74a7aae7b5248dafe112 +3 -0
  56. data/scenarios/git_repositories/config.git/objects/17/6bf54cf17d1d1c24556dc059c4144a5df230e8 +0 -0
  57. data/scenarios/git_repositories/config.git/objects/20/e9ff3feaa8ede30f707e5f1b4356e3c02bb7ec +0 -0
  58. data/scenarios/git_repositories/config.git/objects/45/117b1c775f0de415478dbf08ed9d667ab17d13 +0 -0
  59. data/scenarios/git_repositories/config.git/objects/51/3954c9aca090e6ce40359f0e9fde30ea78eb8c +0 -0
  60. data/scenarios/git_repositories/config.git/objects/66/947a7a11a6f5d3d561fe95de284ced3010819a +0 -0
  61. data/scenarios/git_repositories/config.git/objects/6b/bc79311bfac47d3ed724aa82a4814e0dda4c67 +0 -0
  62. data/scenarios/git_repositories/config.git/objects/71/eb5df52676e8e6efba471050b46978173af110 +1 -0
  63. data/scenarios/git_repositories/config.git/objects/84/17d2fe3e8fcc0825249c517b29b0f9ea8b8b31 +2 -0
  64. data/scenarios/git_repositories/config.git/objects/8b/384fcfcf7c0dee7c3c1d5636bee9e645d9cf38 +0 -0
  65. data/scenarios/git_repositories/config.git/objects/bb/59da633ba74296b0c2f9ff70784ac155ddb599 +0 -0
  66. data/scenarios/git_repositories/config.git/objects/cc/b86b26189afbf45d8eb9165812ab86dbdfca63 +0 -0
  67. data/scenarios/git_repositories/config.git/objects/d1/0bcd51fec41f854001e4d61f99d9e282a695d3 +0 -0
  68. data/scenarios/git_repositories/config.git/objects/d8/a8b0f5b1fd66844efb141d9544965ea0065f2d +0 -0
  69. data/scenarios/git_repositories/config.git/objects/e6/b02c66ad632e6b8535c4630cb8fe07732a72fc +0 -0
  70. data/scenarios/git_repositories/config.git/objects/e8/b8bfeeba735c0a1a873082554cb4d7256ac125 +0 -0
  71. data/scenarios/git_repositories/config.git/objects/f9/0181466a1a60b793ca9cc9abd584c18d4e3887 +0 -0
  72. data/scenarios/git_repositories/config.git/objects/f9/49d5d8a4f12c91471e34d4e277239c35ebd10d +0 -0
  73. data/scenarios/git_repositories/config.git/refs/heads/master +1 -0
  74. data/scenarios/git_repositories/project.git/HEAD +1 -0
  75. data/scenarios/git_repositories/project.git/config +5 -0
  76. data/scenarios/git_repositories/project.git/description +1 -0
  77. data/scenarios/git_repositories/project.git/git-daemon-export-ok +0 -0
  78. data/scenarios/git_repositories/project.git/hooks/applypatch-msg.sample +15 -0
  79. data/scenarios/git_repositories/project.git/hooks/commit-msg.sample +24 -0
  80. data/scenarios/git_repositories/project.git/hooks/post-commit.sample +8 -0
  81. data/scenarios/git_repositories/project.git/hooks/post-receive.sample +15 -0
  82. data/scenarios/git_repositories/project.git/hooks/post-update.sample +8 -0
  83. data/scenarios/git_repositories/project.git/hooks/pre-applypatch.sample +14 -0
  84. data/scenarios/git_repositories/project.git/hooks/pre-commit.sample +46 -0
  85. data/scenarios/git_repositories/project.git/hooks/pre-rebase.sample +169 -0
  86. data/scenarios/git_repositories/project.git/hooks/prepare-commit-msg.sample +36 -0
  87. data/scenarios/git_repositories/project.git/hooks/update.sample +128 -0
  88. data/scenarios/git_repositories/project.git/info/exclude +6 -0
  89. data/scenarios/git_repositories/project.git/objects/04/26e152e66c8cd42974279bdcae09be9839c172 +0 -0
  90. data/scenarios/git_repositories/project.git/objects/04/f4de85eaf72ef1631dc6d7424045c0a749b757 +1 -0
  91. data/scenarios/git_repositories/project.git/objects/06/13fe277280cbcdb2856e1eefc70bdaff011b20 +0 -0
  92. data/scenarios/git_repositories/project.git/objects/06/7aca89b86265eee211387434c3e50f37ccf009 +0 -0
  93. data/scenarios/git_repositories/project.git/objects/09/445dacc4822722612d60833c9948219ecdd8f5 +0 -0
  94. data/scenarios/git_repositories/project.git/objects/11/c4ec64326de35462f4e79d0f4229bf8e26e0c5 +0 -0
  95. data/scenarios/git_repositories/project.git/objects/20/1c7641c2e42b0b904e5c1f793489d8b858e4da +2 -0
  96. data/scenarios/git_repositories/project.git/objects/23/979639da60d2d31e9744468df1c1221b101e64 +0 -0
  97. data/scenarios/git_repositories/project.git/objects/27/a3fff2c4c45ab5513a405f694c0a042cb5d417 +1 -0
  98. data/scenarios/git_repositories/project.git/objects/2c/0c33cfba8e1af15df88522c0db2b10a6a94138 +2 -0
  99. data/scenarios/git_repositories/project.git/objects/38/b574660305ecb5fec6b2daa7ee1e0dbf1b6003 +0 -0
  100. data/scenarios/git_repositories/project.git/objects/4a/57abb5e4e426cfc9101b3af22ac83ccbd8e2ad +0 -0
  101. data/scenarios/git_repositories/project.git/objects/4c/77ebdd985e57afe7988480720c5dc77ec525c9 +0 -0
  102. data/scenarios/git_repositories/project.git/objects/51/c94da6f1b8aa9d2346088d3d362475b60c7f32 +0 -0
  103. data/scenarios/git_repositories/project.git/objects/5b/a96acf9cc9b87babe37c032676f53bf1ba9ae7 +2 -0
  104. data/scenarios/git_repositories/project.git/objects/5d/f555601d60f1c2a84d2364af0ad640612c3ba5 +0 -0
  105. data/scenarios/git_repositories/project.git/objects/71/03b5ac94940d596c2160a5cfcd55ca4ccac41f +0 -0
  106. data/scenarios/git_repositories/project.git/objects/73/3fc331098b03523f414f3509b9ae6e637c6866 +0 -0
  107. data/scenarios/git_repositories/project.git/objects/80/26076649ceccbe96a6292f2432652f08483035 +0 -0
  108. data/scenarios/git_repositories/project.git/objects/86/d1ef0976be4567de562224e1b51fbf9820c53a +1 -0
  109. data/scenarios/git_repositories/project.git/objects/87/a9d8b09b3401d21b23d90253332d6b28b47db2 +0 -0
  110. data/scenarios/git_repositories/project.git/objects/8b/030ba688255c917d189ae3f87d7c5ccd226bc2 +0 -0
  111. data/scenarios/git_repositories/project.git/objects/95/c9d5ad9b1c90e4c805516783105fc2037dedeb +2 -0
  112. data/scenarios/git_repositories/project.git/objects/95/d82d043af35a80eabfd56c0d705abfa3488787 +2 -0
  113. data/scenarios/git_repositories/project.git/objects/96/0bf34bb0b46d0aeb0be87f688f4ef06a4b35e1 +0 -0
  114. data/scenarios/git_repositories/project.git/objects/a3/860106dc1d148c7831cd45ae38829b4ed47702 +2 -0
  115. data/scenarios/git_repositories/project.git/objects/a8/506d6439b71784a72ac72d284b2ad53088f573 +0 -0
  116. data/scenarios/git_repositories/project.git/objects/ad/22ea6c7563777936ecfbe50d8e2cf8120fd525 +0 -0
  117. data/scenarios/git_repositories/project.git/objects/ae/3900de54aff557c61c81146d00f9d38e55a265 +1 -0
  118. data/scenarios/git_repositories/project.git/objects/bf/5e3740d52b80abb0378b3f85f93a53b1294521 +1 -0
  119. data/scenarios/git_repositories/project.git/objects/bf/b59811cdbc069418dee14b171e6e7e979784b7 +0 -0
  120. data/scenarios/git_repositories/project.git/objects/cc/5ac0afb24e727d5de344cc26a425f4fb7fd17d +3 -0
  121. data/scenarios/git_repositories/project.git/objects/d1/091aa2dd76885108461110c639e6b33a297fce +0 -0
  122. data/scenarios/git_repositories/project.git/objects/d8/913f6650eb2b7bf2a633732d8452008ca23dcb +0 -0
  123. data/scenarios/git_repositories/project.git/objects/db/d1b9667f1b26b13331ac0c321dced8be1aeab0 +3 -0
  124. data/scenarios/git_repositories/project.git/objects/e4/3b9107e9b1908ce415025e64eb83a493d329b7 +0 -0
  125. data/scenarios/git_repositories/project.git/objects/ef/2a88894d5421920b9dfe67a9a4d8043830e62e +0 -0
  126. data/scenarios/git_repositories/project.git/objects/f4/0123a1ff20c65d8dc15a38a83222647908e6f7 +0 -0
  127. data/scenarios/git_repositories/project.git/objects/f5/0af315b75ca0b12c720dec6d916b76b968c319 +0 -0
  128. data/scenarios/git_repositories/project.git/objects/f6/0215709b7b23f3738e9cbaf634b1c86bbd376a +0 -0
  129. data/scenarios/git_repositories/project.git/refs/heads/bad_rakefile +1 -0
  130. data/scenarios/git_repositories/project.git/refs/heads/hook_with_changed +1 -0
  131. data/scenarios/git_repositories/project.git/refs/heads/master +1 -0
  132. data/scenarios/git_repositories/project.git/refs/heads/no_rake_hooks +1 -0
  133. data/scenarios/git_repositories/project.git/refs/heads/post_rake_tasks +1 -0
  134. data/scenarios/invalid/deploy.yml +1 -0
  135. data/scenarios/local/deploy.yml.erb +17 -0
  136. data/scenarios/remote/deploy.yml +119 -0
  137. data/scenarios/setup/vagrant/.gitignore +3 -0
  138. data/scenarios/setup/vagrant/Vagrantfile +10 -0
  139. data/scenarios/setup/vagrant/manifests/integration.pp +32 -0
  140. data/scenarios/setup/vagrant/pids/.gitignore +1 -0
  141. data/spec/.bacon +0 -0
  142. data/spec/init_spec.rb +9 -0
  143. data/spec/install_spec.rb +43 -0
  144. data/spec/integration/branch_switching_spec.rb +41 -0
  145. data/spec/integration/deployment_failures_spec.rb +106 -0
  146. data/spec/integration/helper_spec.rb +90 -0
  147. data/spec/integration/invalid_configuration_spec.rb +39 -0
  148. data/spec/integration/local_deployments_spec.rb +230 -0
  149. data/spec/integration/post_rake_tasks_spec.rb +226 -0
  150. data/spec/integration/post_scripts_spec.rb +246 -0
  151. data/spec/integration/remote_deployments_spec.rb +166 -0
  152. data/spec/integration/staleness_checks_spec.rb +72 -0
  153. data/spec/spec_helper.rb +117 -0
  154. data/spec/wd_command_spec.rb +986 -0
  155. data/spec/wd_role_command_spec.rb +49 -0
  156. data/spec/whiskey_disk/config/filter_spec.rb +77 -0
  157. data/spec/whiskey_disk/config/filters/add_environment_name_filter_spec.rb +20 -0
  158. data/spec/whiskey_disk/config/filters/add_project_name_filter_spec.rb +19 -0
  159. data/spec/whiskey_disk/config/filters/check_for_duplicate_domains_filter_spec.rb +29 -0
  160. data/spec/whiskey_disk/config/filters/convert_role_strings_to_list_filter_spec.rb +48 -0
  161. data/spec/whiskey_disk/config/filters/default_config_target_filter_spec.rb +19 -0
  162. data/spec/whiskey_disk/config/filters/default_domain_filter_spec.rb +18 -0
  163. data/spec/whiskey_disk/config/filters/drop_empty_domain_roles_filter_spec.rb +60 -0
  164. data/spec/whiskey_disk/config/filters/environment_scope_filter_spec.rb +32 -0
  165. data/spec/whiskey_disk/config/filters/hashify_domain_entries_filter_spec.rb +41 -0
  166. data/spec/whiskey_disk/config/filters/localize_domains_filter_spec.rb +30 -0
  167. data/spec/whiskey_disk/config/filters/normalize_ssh_options_filter_spec.rb +56 -0
  168. data/spec/whiskey_disk/config/filters/project_scope_filter_spec.rb +75 -0
  169. data/spec/whiskey_disk/config/filters/select_project_and_environment_filter_spec.rb +30 -0
  170. data/spec/whiskey_disk/config/filters/stringify_hash_keys_filter_spec.rb +40 -0
  171. data/spec/whiskey_disk/config_spec.rb +754 -0
  172. data/spec/whiskey_disk/helpers_spec.rb +443 -0
  173. data/spec/whiskey_disk/rake_spec.rb +261 -0
  174. data/spec/whiskey_disk_spec.rb +1224 -0
  175. data/tasks/deploy.rake +2 -0
  176. data/whisk_deploy.gemspec +215 -0
  177. metadata +241 -0
@@ -0,0 +1,56 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'normalize_ssh_options_filter'))
4
+
5
+ describe 'normalizing SSH options' do
6
+ before do
7
+ @config = WhiskeyDisk::Config.new
8
+ @filter = WhiskeyDisk::Config::NormalizeSshOptionsFilter.new(@config)
9
+ end
10
+
11
+ it 'eliminates ssh options with nil, or empty values' do
12
+ @data = {
13
+ 'domain' => [
14
+ { 'name' => 'foo', 'ssh_options' => nil },
15
+ { 'name' => 'bar', 'ssh_options' => '' },
16
+ { 'name' => 'baz', 'ssh_options' => [] },
17
+ { 'name' => 'xyzzy', 'ssh_options' => ['', ''] },
18
+ { 'name' => 'quux', 'ssh_options' => [nil, '', nil] },
19
+ ]
20
+ }
21
+
22
+ @filter.filter(@data).should == {
23
+ 'domain' => [
24
+ { 'name' => 'foo' },
25
+ { 'name' => 'bar' },
26
+ { 'name' => 'baz' },
27
+ { 'name' => 'xyzzy' },
28
+ { 'name' => 'quux' }
29
+ ]
30
+ }
31
+ end
32
+
33
+ it 'preserves non-empty ssh options' do
34
+ @data = {
35
+ 'domain' => [
36
+ { 'name' => 'foo', 'ssh_options' => nil },
37
+ { 'name' => 'bar', 'ssh_options' => 'c' },
38
+ { 'name' => 'baz', 'ssh_options' => [] },
39
+ { 'name' => 'xyzzy', 'ssh_options' => ['', 'c'] },
40
+ { 'name' => 'quux', 'ssh_options' => [nil, '', 'a', nil, 'b' ] },
41
+ { 'name' => 'wut', 'ssh_options' => [nil, '', 'x', 'a', 'a', nil, 'b' ] },
42
+ ]
43
+ }
44
+
45
+ @filter.filter(@data).should == {
46
+ 'domain' => [
47
+ { 'name' => 'foo' },
48
+ { 'name' => 'bar', 'ssh_options' => [ 'c' ] },
49
+ { 'name' => 'baz' },
50
+ { 'name' => 'xyzzy', 'ssh_options' => [ 'c' ] },
51
+ { 'name' => 'quux', 'ssh_options' => [ 'a', 'b' ] },
52
+ { 'name' => 'wut', 'ssh_options' => [ 'x', 'a', 'a', 'b' ] }
53
+ ]
54
+ }
55
+ end
56
+ end
@@ -0,0 +1,75 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'project_scope_filter'))
4
+
5
+ describe 'filtering configuration data by adding project scoping' do
6
+ before do
7
+ ENV['to'] = @env = 'foo:staging'
8
+
9
+ @config = WhiskeyDisk::Config.new
10
+ @filter = WhiskeyDisk::Config::ProjectScopeFilter.new(@config)
11
+
12
+ @bare_data = { 'staging' => { 'repository' => 'git://foo/bar.git', 'domain' => [ { :name => 'ogc@ogtastic.com' } ] } }
13
+ @proj_data = { 'foo' => @bare_data }
14
+ end
15
+
16
+ it 'fails if the configuration data is not a hash' do
17
+ lambda { @filter.filter([]) }.should.raise
18
+ end
19
+
20
+ describe 'when no project name is specified via ENV["to"]' do
21
+ before do
22
+ ENV['to'] = @env = 'staging'
23
+ end
24
+
25
+ it 'returns the original data if it has both project and environment scoping' do
26
+ @filter.filter(@proj_data).should == @proj_data
27
+ end
28
+
29
+ describe 'when no project name is specified in the bare config hash' do
30
+ it 'returns the original data wrapped in project scope, using a dummy project, if it has environment scoping but no project scoping' do
31
+ @filter.filter(@bare_data).should == { 'unnamed_project' => @bare_data }
32
+ end
33
+ end
34
+
35
+ describe 'when a project name is specified in the bare config hash' do
36
+ before do
37
+ @bare_data['staging']['project'] = 'whiskey_disk'
38
+ end
39
+
40
+ it 'returns the original data wrapped in project scope if it has environment scoping but no project scoping' do
41
+ @filter.filter(@bare_data).should == { 'whiskey_disk' => @bare_data }
42
+ end
43
+ end
44
+ end
45
+
46
+ describe 'when a project name is specified via ENV["to"]' do
47
+ before do
48
+ ENV['to'] = @env = 'whiskey_disk:staging'
49
+ end
50
+
51
+ describe 'when a project name is not specified in the bare config hash' do
52
+ it 'returns the original data if it has both project and environment scoping' do
53
+ @filter.filter(@proj_data).should == @proj_data
54
+ end
55
+
56
+ it 'returns the original data wrapped in project scope if it has environment scoping but no project scoping' do
57
+ @filter.filter(@bare_data).should == { 'whiskey_disk' => @bare_data }
58
+ end
59
+ end
60
+
61
+ describe 'when a project name is specified in the bare config hash' do
62
+ before do
63
+ @bare_data['staging']['project'] = 'whiskey_disk'
64
+ end
65
+
66
+ it 'returns the original data if it has both project and environment scoping' do
67
+ @filter.filter(@proj_data).should == @proj_data
68
+ end
69
+
70
+ it 'returns the original data wrapped in project scope if it has environment scoping but no project scoping' do
71
+ @filter.filter(@bare_data).should == { 'whiskey_disk' => @bare_data }
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,30 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'select_project_and_environment_filter'))
4
+
5
+ describe 'filtering configuration data by selecting the data for the project and environment' do
6
+ before do
7
+ @config = WhiskeyDisk::Config.new
8
+ @filter = WhiskeyDisk::Config::SelectProjectAndEnvironmentFilter.new(@config)
9
+
10
+ @data = {
11
+ 'project' => { 'environment' => { 'a' => 'b' } },
12
+ 'other' => { 'missing' => { 'c' => 'd' } },
13
+ }
14
+ end
15
+
16
+ it 'fails when the specified project cannot be found' do
17
+ ENV['to'] = @env = 'something:environment'
18
+ lambda { @filter.filter(@data) }.should.raise
19
+ end
20
+
21
+ it 'fails when the specified environment cannot be found for the specified project' do
22
+ ENV['to'] = @env = 'other:environment'
23
+ lambda { @filter.filter(@data) }.should.raise
24
+ end
25
+
26
+ it 'returns only the data for the specified project and environment' do
27
+ ENV['to'] = @env = 'project:environment'
28
+ @filter.filter(@data).should == @data['project']['environment']
29
+ end
30
+ end
@@ -0,0 +1,40 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'stringify_hash_keys_filter'))
4
+
5
+ describe 'filtering configuration data to only have symbol hash keys' do
6
+ before do
7
+ @config = WhiskeyDisk::Config.new
8
+ @filter = WhiskeyDisk::Config::StringifyHashKeysFilter.new(@config)
9
+ @data = {
10
+ 'a' => {
11
+ :x => 'y',
12
+ 'c' => 'd',
13
+ :e => {
14
+ 'f' => ['a', 'b', 'c']
15
+ }
16
+ },
17
+ :b => [ '1', '2', '3' ]
18
+ }
19
+ end
20
+
21
+ it 'recursively stringifies hash keys in the provided data structure' do
22
+ @filter.filter(@data).should == {
23
+ 'a' => {
24
+ 'x' => 'y',
25
+ 'c' => 'd',
26
+ 'e' => {
27
+ 'f' => [ 'a', 'b', 'c' ]
28
+ }
29
+ },
30
+ 'b' => [ '1', '2', '3' ]
31
+ }
32
+ end
33
+
34
+ it 'clones value data so that the original data structure is not shared' do
35
+ original = @data.clone
36
+ result = @filter.filter(@data)
37
+ result['a']['e']['f'] << 'd'
38
+ @data.should == original
39
+ end
40
+ end
@@ -0,0 +1,754 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper.rb'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'whiskey_disk', 'config'))
3
+ require 'yaml'
4
+ require 'tmpdir'
5
+ require 'fileutils'
6
+
7
+ # create a file at the specified path
8
+ def make(path)
9
+ FileUtils.mkdir_p(File.dirname(path))
10
+ FileUtils.touch(path)
11
+ end
12
+
13
+ def build_temp_dir
14
+ return Dir.mktmpdir(nil, '/private/tmp') if File.exists?('/private/tmp')
15
+ Dir.mktmpdir
16
+ end
17
+
18
+ def write_config_file(data)
19
+ File.open(@config_file, 'w') { |f| f.puts YAML.dump(data) }
20
+ end
21
+
22
+ # class for testing .open calls -- for use with URL config paths
23
+ class TestURLConfig < WhiskeyDisk::Config
24
+ def set_response(data)
25
+ @fake_response = YAML.dump(data)
26
+ end
27
+
28
+ def open(path)
29
+ @fake_response || raise
30
+ end
31
+ end
32
+
33
+ describe WhiskeyDisk::Config do
34
+ before do
35
+ @config = WhiskeyDisk::Config.new
36
+ end
37
+
38
+ describe 'when computing the environment name' do
39
+ it 'returns false when there is no ENV["to"] setting' do
40
+ ENV['to'] = nil
41
+ @config.environment_name.should == false
42
+ end
43
+
44
+ it 'returns false when the ENV["to"] setting is blank' do
45
+ ENV['to'] = ''
46
+ @config.environment_name.should == false
47
+ end
48
+
49
+ it 'returns the ENV["to"] setting when it is non-blank' do
50
+ ENV['to'] = 'staging'
51
+ @config.environment_name.should == 'staging'
52
+ end
53
+
54
+ it 'returns the environment portion of the ENV["to"] setting when a project is specified' do
55
+ ENV['to'] = 'project:staging'
56
+ @config.environment_name.should == 'staging'
57
+ end
58
+ end
59
+
60
+ describe 'when determining whether to do a staleness check before updating' do
61
+ it 'returns false when there is no ENV["check"] setting' do
62
+ ENV['check'] = nil
63
+ @config.check_staleness?.should == false
64
+ end
65
+
66
+ it 'returns false when the ENV["check"] setting is blank' do
67
+ ENV['check'] = ''
68
+ @config.check_staleness?.should == false
69
+ end
70
+
71
+ it 'returns true if the ENV["check"] setting is "t"' do
72
+ ENV['check'] = 't'
73
+ @config.check_staleness?.should == true
74
+ end
75
+
76
+ it 'returns true if the ENV["check"] setting is "true"' do
77
+ ENV['check'] = 'true'
78
+ @config.check_staleness?.should == true
79
+ end
80
+
81
+ it 'returns true if the ENV["check"] setting is "y"' do
82
+ ENV['check'] = 'y'
83
+ @config.check_staleness?.should == true
84
+ end
85
+
86
+ it 'returns true if the ENV["check"] setting is "yes"' do
87
+ ENV['check'] = 'yes'
88
+ @config.check_staleness?.should == true
89
+ end
90
+
91
+ it 'returns true if the ENV["check"] setting is "1"' do
92
+ ENV['check'] = '1'
93
+ @config.check_staleness?.should == true
94
+ end
95
+ end
96
+
97
+ describe 'when determining whether there is a domain limit set' do
98
+ it 'returns false when ENV["only"] is nil' do
99
+ ENV['only'] = nil
100
+ @config.domain_limit.should == false
101
+ end
102
+
103
+ it 'returns false when ENV["only"] is empty' do
104
+ ENV['only'] = ''
105
+ @config.domain_limit.should == false
106
+ end
107
+
108
+ it 'returns the value in ENV["only"] when it is non-empty' do
109
+ ENV['only'] = 'somedomain'
110
+ @config.domain_limit.should == 'somedomain'
111
+ end
112
+ end
113
+
114
+ describe 'when determining whether to turn debug mode on' do
115
+ it 'returns false when there is no ENV["debug"] setting' do
116
+ ENV['debug'] = nil
117
+ @config.debug?.should == false
118
+ end
119
+
120
+ it 'returns false when the ENV["debug"] setting is blank' do
121
+ ENV['debug'] = ''
122
+ @config.debug?.should == false
123
+ end
124
+
125
+ it 'returns true if the ENV["debug"] setting is "t"' do
126
+ ENV['debug'] = 't'
127
+ @config.debug?.should == true
128
+ end
129
+
130
+ it 'returns true if the ENV["debug"] setting is "true"' do
131
+ ENV['debug'] = 'true'
132
+ @config.debug?.should == true
133
+ end
134
+
135
+ it 'returns true if the ENV["debug"] setting is "y"' do
136
+ ENV['debug'] = 'y'
137
+ @config.debug?.should == true
138
+ end
139
+
140
+ it 'returns true if the ENV["debug"] setting is "yes"' do
141
+ ENV['debug'] = 'yes'
142
+ @config.debug?.should == true
143
+ end
144
+
145
+ it 'returns true if the ENV["debug"] setting is "1"' do
146
+ ENV['debug'] = '1'
147
+ @config.debug?.should == true
148
+ end
149
+ end
150
+
151
+ describe 'when fetching configuration' do
152
+ describe 'and path specified is an URL' do
153
+ before do
154
+ ENV['to'] = @env = 'foo:staging'
155
+ ENV['path'] = 'https://www.example.com/foo/bar/deploy.yml'
156
+ @config = TestURLConfig.new
157
+ end
158
+
159
+ it 'fails if the current environment cannot be determined' do
160
+ ENV['to'] = nil
161
+ lambda { @config.fetch }.should.raise
162
+ end
163
+
164
+ it 'fails if the configuration data cannot be retrieved' do
165
+ @config.stub!(:open).and_raise(RuntimeError)
166
+ lambda { @config.fetch }.should.raise
167
+ end
168
+
169
+ it 'fails if the retrieved configuration data is invalid' do
170
+ @config.stub!(:open).and_return("}")
171
+ lambda { @config.fetch }.should.raise
172
+ end
173
+
174
+ it 'fails if the retrieved configuration data does not define data for this environment' do
175
+ @config.set_response('foo' => { 'production' => { 'a' => 'b'} })
176
+ lambda { @config.fetch }.should.raise
177
+ end
178
+
179
+ it 'returns the retrieved configuration yaml data for this environment as a hash' do
180
+ staging = { 'foo' => 'bar', 'repository' => 'xyzzy' }
181
+ @config.set_response('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
182
+ result = @config.fetch
183
+ staging.each_pair do |k,v|
184
+ result[k].should == v
185
+ end
186
+ end
187
+
188
+ it 'does not include configuration information for other environments in the returned hash' do
189
+ staging = { 'foo' => 'bar', 'baz' => 'xyzzy' }
190
+ @config.set_response('production' => { 'repository' => 'c', 'a' => 'b'}, 'staging' => staging)
191
+ @config.fetch['a'].should.be.nil
192
+ end
193
+
194
+ it 'includes the environment in the hash' do
195
+ staging = { 'foo' => 'bar', 'baz' => 'xyzzy' }
196
+ @config.set_response('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
197
+ @config.fetch['environment'].should == 'staging'
198
+ end
199
+
200
+ it 'does not allow overriding the environment in the configuration file' do
201
+ staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'environment' => 'production' }
202
+ @config.set_response('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
203
+ @config.fetch['environment'].should == 'staging'
204
+ end
205
+
206
+ it 'includes the project handle in the hash' do
207
+ staging = { 'foo' => 'bar', 'repository' => 'xyzzy' }
208
+ @config.set_response('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
209
+ @config.fetch['project'].should == 'foo'
210
+ end
211
+
212
+ it 'does not allow overriding the project handle in the configuration file when a project root is specified' do
213
+ staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }
214
+ @config.set_response('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
215
+ @config.fetch['project'].should == 'foo'
216
+ end
217
+
218
+ it 'allows overriding the project handle in the configuration file when a project root is not specified' do
219
+ ENV['to'] = @env = 'staging'
220
+ staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }
221
+ @config.set_response('production' => { 'repository' => 'b'}, 'staging' => staging)
222
+ @config.fetch['project'].should == 'diskey_whisk'
223
+ end
224
+
225
+ it 'includes the environment name as the config_target setting when no config_target is specified' do
226
+ staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }
227
+ @config.set_response('production' => { 'repository' => 'b'}, 'staging' => staging)
228
+ @config.fetch['config_target'].should == 'staging'
229
+ end
230
+
231
+ it 'includes the config_target setting when a config_target is specified' do
232
+ staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk', 'config_target' => 'testing' }
233
+ @config.set_response('production' => { 'repository' => 'b'}, 'staging' => staging)
234
+ @config.fetch['config_target'].should == 'testing'
235
+ end
236
+
237
+ it 'fails if the named target cannot be found' do
238
+ ENV['to'] = @env = 'bogus:thing'
239
+ lambda { @config.fetch }.should.raise
240
+ end
241
+ end
242
+
243
+ describe 'and path specified is not an URL' do
244
+ before do
245
+ ENV['to'] = @env = 'foo:staging'
246
+ @path = build_temp_dir
247
+ ENV['path'] = @config_file = File.join(@path, 'deploy.yml')
248
+ end
249
+
250
+ after do
251
+ FileUtils.rm_rf(@path)
252
+ end
253
+
254
+ it 'fails if the current environment cannot be determined' do
255
+ ENV['to'] = nil
256
+ lambda { @config.fetch }.should.raise
257
+ end
258
+
259
+ it 'fails if the configuration file does not exist' do
260
+ lambda { @config.fetch }.should.raise
261
+ end
262
+
263
+ it 'fails if the configuration file cannot be read' do
264
+ Dir.mkdir(File.join(@path, 'tmp'))
265
+ lambda { @config.fetch }.should.raise
266
+ end
267
+
268
+ it 'fails if the configuration file is invalid' do
269
+ File.open(@config_file, 'w') {|f| f.puts "}" }
270
+ lambda { @config.fetch }.should.raise
271
+ end
272
+
273
+ it 'fails if the configuration file does not define data for this environment' do
274
+ write_config_file('foo' => { 'production' => { 'a' => 'b'} })
275
+ lambda { @config.fetch }.should.raise
276
+ end
277
+
278
+ it 'returns the configuration yaml file data for this environment as a hash' do
279
+ staging = { 'foo' => 'bar', 'repository' => 'xyzzy' }
280
+ write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
281
+ result = @config.fetch
282
+ staging.each_pair do |k,v|
283
+ result[k].should == v
284
+ end
285
+ end
286
+
287
+ it 'does not include configuration information for other environments in the returned hash' do
288
+ staging = { 'foo' => 'bar', 'baz' => 'xyzzy' }
289
+ write_config_file('production' => { 'repository' => 'c', 'a' => 'b'}, 'staging' => staging)
290
+ @config.fetch['a'].should.be.nil
291
+ end
292
+
293
+ it 'includes the environment in the hash' do
294
+ staging = { 'foo' => 'bar', 'baz' => 'xyzzy' }
295
+ write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
296
+ @config.fetch['environment'].should == 'staging'
297
+ end
298
+
299
+ it 'does not allow overriding the environment in the configuration file' do
300
+ staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'environment' => 'production' }
301
+ write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
302
+ @config.fetch['environment'].should == 'staging'
303
+ end
304
+
305
+ it 'includes the project handle in the hash' do
306
+ staging = { 'foo' => 'bar', 'repository' => 'xyzzy' }
307
+ write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
308
+ @config.fetch['project'].should == 'foo'
309
+ end
310
+
311
+ it 'does not allow overriding the project handle in the configuration file when a project root is specified' do
312
+ staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }
313
+ write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
314
+ @config.fetch['project'].should == 'foo'
315
+ end
316
+
317
+ it 'allows overriding the project handle in the configuration file when a project root is not specified' do
318
+ ENV['to'] = @env = 'staging'
319
+ staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }
320
+ write_config_file('production' => { 'repository' => 'b'}, 'staging' => staging)
321
+ @config.fetch['project'].should == 'diskey_whisk'
322
+ end
323
+
324
+ it 'includes the environment name as the config_target setting when no config_target is specified' do
325
+ staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }
326
+ write_config_file('production' => { 'repository' => 'b'}, 'staging' => staging)
327
+ @config.fetch['config_target'].should == 'staging'
328
+ end
329
+
330
+ it 'includes the config_target setting when a config_target is specified' do
331
+ staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk', 'config_target' => 'testing' }
332
+ write_config_file('production' => { 'repository' => 'b'}, 'staging' => staging)
333
+ @config.fetch['config_target'].should == 'testing'
334
+ end
335
+
336
+ it 'fails if the named target cannot be found' do
337
+ ENV['to'] = @env = 'bogus:thing'
338
+ lambda { @config.fetch }.should.raise
339
+ end
340
+ end
341
+ end
342
+
343
+ describe 'returning configuration data from a configuration file' do
344
+ before do
345
+ @path = build_temp_dir
346
+ ENV['path'] = @config_file = File.join(@path, 'deploy.yml')
347
+ end
348
+
349
+ after do
350
+ FileUtils.rm_rf(@path)
351
+ end
352
+
353
+ it 'fails if the configuration file does not exist' do
354
+ lambda { @config.configuration_data }.should.raise
355
+ end
356
+
357
+ it 'returns the contents of the configuration file' do
358
+ File.open(@config_file, 'w') { |f| f.puts "file contents" }
359
+ @config.configuration_data.should == "file contents\n"
360
+ end
361
+ end
362
+
363
+ describe 'loading data from the configuration file' do
364
+ before do
365
+ ENV['to'] = 'foo:bar'
366
+ @path = build_temp_dir
367
+ ENV['path'] = @config_file = File.join(@path, 'deploy.yml')
368
+ end
369
+
370
+ after do
371
+ FileUtils.rm_rf(@path)
372
+ end
373
+
374
+ it 'fails if the configuration data cannot be loaded' do
375
+ lambda { @config.load_data }.should.raise
376
+ end
377
+
378
+ it 'fails if converting the configuration data from YAML fails' do
379
+ File.open(@config_file, 'w') { |f| f.puts "}" }
380
+ lambda { @config.load_data }.should.raise
381
+ end
382
+
383
+ it 'returns the un-YAMLized configuration data' do
384
+ write_config_file('repository' => 'x')
385
+ @config.load_data.should == { 'repository' => 'x' }
386
+ end
387
+ end
388
+
389
+ describe 'computing the project name' do
390
+ it 'returns the project name from the ENV["to"] setting when it is available' do
391
+ ENV['to'] = 'foo:staging'
392
+ @config.project_name.should == 'foo'
393
+ end
394
+
395
+ it 'returns "unnamed_project" when ENV["to"] is unset' do
396
+ ENV['to'] = ''
397
+ @config.project_name.should == 'unnamed_project'
398
+ end
399
+
400
+ it 'returns "unnamed_project" when no ENV["to"] project setting is available' do
401
+ ENV['to'] = 'staging'
402
+ @config.project_name.should == 'unnamed_project'
403
+ end
404
+ end
405
+
406
+ describe 'finding the configuration file' do
407
+ before do
408
+ ENV['to'] = @env = 'staging'
409
+ end
410
+
411
+ describe 'and no path is specified' do
412
+ before do
413
+ ENV['path'] = @path = nil
414
+ @original_path = Dir.pwd
415
+ @base_path = build_temp_dir
416
+ Dir.chdir(@base_path)
417
+ FileUtils.touch(File.join(@base_path, 'Rakefile'))
418
+ @dir = File.join(@base_path, 'config')
419
+ Dir.mkdir(@dir)
420
+
421
+ [
422
+ "/deploy/foo/staging.yml",
423
+ "/deploy/foo.yml",
424
+ "/deploy/staging.yml",
425
+ "/staging.yml",
426
+ "/deploy.yml"
427
+ ].each { |file| make(File.join(@dir, file)) }
428
+ end
429
+
430
+ after do
431
+ FileUtils.rm_rf(@base_path)
432
+ Dir.chdir(@original_path)
433
+ end
434
+
435
+ describe 'and a project name is specified in ENV["to"]' do
436
+ before do
437
+ ENV['to'] = @env = 'foo:staging'
438
+ end
439
+
440
+ it 'returns the path to deploy/foo/<environment>.yml under the project base path if it exists' do
441
+ @config.configuration_file.should == "#{@dir}/deploy/foo/staging.yml"
442
+ end
443
+
444
+ it 'returns the path to deploy/foo.yml under the project base path if it exists' do
445
+ File.unlink("#{@dir}/deploy/foo/staging.yml")
446
+ @config.configuration_file.should == "#{@dir}/deploy/foo.yml"
447
+ end
448
+
449
+ it 'returns the path to a per-environment configuration file in the deploy/ directory under the project base path if it exists' do
450
+ File.unlink("#{@dir}/deploy/foo/staging.yml")
451
+ File.unlink("#{@dir}/deploy/foo.yml")
452
+ @config.configuration_file.should == "#{@dir}/deploy/staging.yml"
453
+ end
454
+
455
+ it 'returns the path to a per-environment configuration file under the project base path if it exists' do
456
+ File.unlink("#{@dir}/deploy/foo/staging.yml")
457
+ File.unlink("#{@dir}/deploy/foo.yml")
458
+ File.unlink("#{@dir}/deploy/staging.yml")
459
+ @config.configuration_file.should == "#{@dir}/staging.yml"
460
+ end
461
+
462
+ it 'returns the path to deploy.yml under the project base path' do
463
+ File.unlink("#{@dir}/deploy/foo/staging.yml")
464
+ File.unlink("#{@dir}/deploy/foo.yml")
465
+ File.unlink("#{@dir}/deploy/staging.yml")
466
+ File.unlink("#{@dir}/staging.yml")
467
+ @config.configuration_file.should == "#{@dir}/deploy.yml"
468
+ end
469
+
470
+ it 'fails if no per-environment config file nor deploy.yml exists under the project base path' do
471
+ File.unlink("#{@dir}/deploy/foo/staging.yml")
472
+ File.unlink("#{@dir}/deploy/foo.yml")
473
+ File.unlink("#{@dir}/deploy/staging.yml")
474
+ File.unlink("#{@dir}/staging.yml")
475
+ File.unlink("#{@dir}/deploy.yml")
476
+ lambda { @config.configuration_file }.should.raise
477
+ end
478
+ end
479
+
480
+ describe 'and no project name is specified in ENV["to"]' do
481
+ it 'returns the path to a per-environment configuration file in the deploy/ directory under the project base path if it exists' do
482
+ @config.configuration_file.should == "#{@dir}/deploy/staging.yml"
483
+ end
484
+
485
+ it 'returns the path to a per-environment configuration file under the project base path if it exists' do
486
+ File.unlink("#{@dir}/deploy/staging.yml")
487
+ @config.configuration_file.should == "#{@dir}/staging.yml"
488
+ end
489
+
490
+ it 'returns the path to deploy.yml under the project base path' do
491
+ File.unlink("#{@dir}/deploy/staging.yml")
492
+ File.unlink("#{@dir}/staging.yml")
493
+ @config.configuration_file.should == "#{@dir}/deploy.yml"
494
+ end
495
+
496
+ it 'fails if no per-environment config file nor deploy.yml exists under the project base path' do
497
+ File.unlink("#{@dir}/deploy/staging.yml")
498
+ File.unlink("#{@dir}/staging.yml")
499
+ File.unlink("#{@dir}/deploy.yml")
500
+ lambda { @config.configuration_file }.should.raise
501
+ end
502
+ end
503
+ end
504
+
505
+ describe 'and looking up a file' do
506
+ before do
507
+ @path = build_temp_dir
508
+ ENV['path'] = @config_file = File.join(@path, 'deploy.yml')
509
+ end
510
+
511
+ after do
512
+ FileUtils.rm_rf(@path)
513
+ end
514
+
515
+ it 'fails if a path is specified which does not exist' do
516
+ lambda { @config.configuration_file }.should.raise
517
+ end
518
+
519
+ it 'returns the file path when a path which points to an existing file is specified' do
520
+ FileUtils.touch(@config_file)
521
+ @config.configuration_file.should == @config_file
522
+ end
523
+ end
524
+
525
+ describe 'and a path which points to a directory is specified' do
526
+ before do
527
+ ENV['path'] = @path = build_temp_dir
528
+
529
+ [
530
+ "/deploy/foo/staging.yml",
531
+ "/deploy/foo.yml",
532
+ "/deploy/staging.yml",
533
+ "/staging.yml",
534
+ "/deploy.yml"
535
+ ].each { |file| make(File.join(@path, file)) }
536
+ end
537
+
538
+ after do
539
+ FileUtils.rm_rf(@path)
540
+ end
541
+
542
+ describe 'and a project name is specified in ENV["to"]' do
543
+ before do
544
+ ENV['to'] = @env = 'foo:staging'
545
+ end
546
+
547
+ it 'returns the path to deploy/foo/<environment>.yml under the project base path if it exists' do
548
+ @config.configuration_file.should == File.join(@path, 'deploy', 'foo' ,'staging.yml')
549
+ end
550
+
551
+ it 'returns the path to deploy/foo.yml under the project base path if it exists' do
552
+ File.unlink(File.join(@path, 'deploy', 'foo', 'staging.yml'))
553
+ @config.configuration_file.should == File.join(@path, 'deploy', 'foo.yml')
554
+ end
555
+
556
+ it 'returns the path to a per-environment configuration file under deploy/ in the path specified if that file exists' do
557
+ File.unlink(File.join(@path, 'deploy', 'foo', 'staging.yml'))
558
+ File.unlink(File.join(@path, 'deploy', 'foo.yml'))
559
+ @config.configuration_file.should == File.join(@path, 'deploy', 'staging.yml')
560
+ end
561
+
562
+ it 'returns the path to a per-environment configuration file in the path specified if that file exists' do
563
+ File.unlink(File.join(@path, 'deploy', 'foo', 'staging.yml'))
564
+ File.unlink(File.join(@path, 'deploy', 'foo.yml'))
565
+ File.unlink(File.join(@path, 'deploy', 'staging.yml'))
566
+ @config.configuration_file.should == File.join(@path, 'staging.yml')
567
+ end
568
+
569
+ it 'returns the path to deploy.yaml in the path specified if deploy.yml exists' do
570
+ File.unlink(File.join(@path, 'deploy', 'foo', 'staging.yml'))
571
+ File.unlink(File.join(@path, 'deploy', 'foo.yml'))
572
+ File.unlink(File.join(@path, 'deploy', 'staging.yml'))
573
+ File.unlink(File.join(@path, 'staging.yml'))
574
+ @config.configuration_file.should == File.join(@path, 'deploy.yml')
575
+ end
576
+
577
+ it 'fails if no per-environment configuration file nor deploy.yml exists in the path specified' do
578
+ File.unlink(File.join(@path, 'deploy', 'foo', 'staging.yml'))
579
+ File.unlink(File.join(@path, 'deploy', 'foo.yml'))
580
+ File.unlink(File.join(@path, 'deploy', 'staging.yml'))
581
+ File.unlink(File.join(@path, 'staging.yml'))
582
+ File.unlink(File.join(@path, 'deploy.yml'))
583
+ lambda { @config.configuration_file }.should.raise
584
+ end
585
+ end
586
+
587
+ describe 'and no project name is specified in ENV["to"]' do
588
+ it 'returns the path to a per-environment configuration file under deploy/ in the path specified if that file exists' do
589
+ @config.configuration_file.should == File.join(@path, 'deploy', 'staging.yml')
590
+ end
591
+
592
+ it 'returns the path to a per-environment configuration file in the path specified if that file exists' do
593
+ File.unlink(File.join(@path, 'deploy', 'staging.yml'))
594
+ @config.configuration_file.should == File.join(@path, 'staging.yml')
595
+ end
596
+
597
+ it 'returns the path to deploy.yaml in the path specified if deploy.yml exists' do
598
+ File.unlink(File.join(@path, 'deploy', 'staging.yml'))
599
+ File.unlink(File.join(@path, 'staging.yml'))
600
+ @config.configuration_file.should == File.join(@path, 'deploy.yml')
601
+ end
602
+
603
+ it 'fails if no per-environment configuration file nor deploy.yml exists in the path specified' do
604
+ File.unlink(File.join(@path, 'deploy', 'staging.yml'))
605
+ File.unlink(File.join(@path, 'staging.yml'))
606
+ File.unlink(File.join(@path, 'deploy.yml'))
607
+ lambda { @config.configuration_file }.should.raise
608
+ end
609
+ end
610
+ end
611
+ end
612
+
613
+ describe 'filtering configuration data' do
614
+ before do
615
+ ENV['to'] = @env = 'foo:erl'
616
+ @data = {
617
+ 'foo' => {
618
+ 'xyz' => { 'repository' => 'x' },
619
+ 'eee' => { 'repository' => 'x', 'domain' => '' },
620
+ 'abc' => { 'repository' => 'x', 'domain' => 'what@example.com' },
621
+ 'baz' => { 'repository' => 'x', 'domain' => [ 'bar@example.com', 'baz@domain.com' ]},
622
+ 'bar' => { 'repository' => 'x', 'domain' => [ 'user@example.com', nil, 'foo@domain.com' ]},
623
+ 'bat' => { 'repository' => 'x', 'domain' => [ 'user@example.com', 'foo@domain.com', '' ]},
624
+ 'hsh' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com' }, { 'name' => 'baz@domain.com' } ]},
625
+ 'mix' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com' }, 'baz@domain.com' ]},
626
+ 'erl' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => nil },
627
+ { 'name' => 'baz@domain.com', 'roles' => '' },
628
+ { 'name' => 'aok@domain.com', 'roles' => [] } ]},
629
+ 'rol' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => [ 'web', 'db' ] },
630
+ { 'name' => 'baz@domain.com', 'roles' => [ 'db' ] },
631
+ { 'name' => 'aok@domain.com', 'roles' => 'app' } ]},
632
+ 'wow' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => [ 'web', 'db' ] },
633
+ { 'name' => 'baz@domain.com', 'roles' => [ 'db' ] },
634
+ '', 'foo@bar.example.com',
635
+ { 'name' => 'aok@domain.com', 'roles' => 'app' } ]},
636
+ },
637
+
638
+ 'zyx' => {
639
+ 'xyz' => { 'repository' => 'x' },
640
+ 'eee' => { 'repository' => 'x', 'domain' => '' },
641
+ 'abc' => { 'repository' => 'x', 'domain' => 'what@example.com' },
642
+ 'hij' => { 'repository' => 'x', 'domain' => [ 'bar@example.com', 'baz@domain.com' ]},
643
+ 'def' => { 'repository' => 'x', 'domain' => [ 'user@example.com', nil, 'foo@domain.com' ]},
644
+ 'dex' => { 'repository' => 'x', 'domain' => [ 'user@example.com', 'foo@domain.com', '' ]},
645
+ 'hsh' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com' }, { 'name' => 'baz@domain.com' } ]},
646
+ 'mix' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com' }, 'baz@domain.com' ]},
647
+ 'erl' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => nil },
648
+ { 'name' => 'baz@domain.com', 'roles' => '' },
649
+ { 'name' => 'aok@domain.com', 'roles' => [] } ]},
650
+ 'rol' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => [ 'web', 'db' ] },
651
+ { 'name' => 'baz@domain.com', 'roles' => [ 'db' ] },
652
+ { 'name' => 'aok@domain.com', 'roles' => 'app' } ]},
653
+ 'wow' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => [ 'web', 'db' ] },
654
+ { 'name' => 'baz@domain.com', 'roles' => [ 'db' ] },
655
+ '', 'foo@bar.example.com',
656
+ { 'name' => 'aok@domain.com', 'roles' => 'app' } ]},
657
+ }
658
+ }
659
+ end
660
+
661
+ it 'should apply all available filters' do
662
+ @config.filter_data(@data).should == {
663
+ "repository" => "x",
664
+ "project" => "foo",
665
+ "config_target" => "erl",
666
+ "environment" => "erl",
667
+ "domain" => [
668
+ { 'name' => "bar@example.com" },
669
+ { 'name' => "baz@domain.com" },
670
+ { 'name' => "aok@domain.com" }
671
+ ]
672
+ }
673
+ end
674
+ end
675
+
676
+ describe 'computing the base path for the project' do
677
+ before do
678
+ @original_path = Dir.pwd
679
+ ENV['path'] = @path = nil
680
+ end
681
+
682
+ after do
683
+ Dir.chdir(@original_path)
684
+ end
685
+
686
+ describe 'and a "path" environment variable is set' do
687
+ before do
688
+ ENV['path'] = @path = build_temp_dir
689
+ @original_path = Dir.pwd
690
+ end
691
+
692
+ after do
693
+ FileUtils.rm_rf(@path)
694
+ Dir.chdir(@original_path)
695
+ end
696
+
697
+ it 'returns the path set in the "path" environment variable' do
698
+ @config.base_path.should == @path
699
+ end
700
+
701
+ it 'leaves the current working path the same as when the base path lookup started' do
702
+ @config.base_path
703
+ Dir.pwd.should == @original_path
704
+ end
705
+ end
706
+
707
+ describe 'and there is no Rakefile in the root path to the current directory' do
708
+ before do
709
+ @original_path = Dir.pwd
710
+ @path = build_temp_dir
711
+ Dir.chdir(@path)
712
+ end
713
+
714
+ after do
715
+ Dir.chdir(@original_path)
716
+ FileUtils.rm_rf(@path)
717
+ end
718
+
719
+ it 'returns the config directory under the current directory if there is no Rakefile along the root path to the current directory' do
720
+ @config.base_path.should == File.join(@path, 'config')
721
+ end
722
+
723
+ it 'leaves the current working path the same as when the base path lookup started' do
724
+ prior = Dir.pwd
725
+ @config.base_path
726
+ Dir.pwd.should == prior
727
+ end
728
+ end
729
+
730
+ describe 'and there is a Rakefile in the root path to the current directory' do
731
+ before do
732
+ @original_path = Dir.pwd
733
+ @path = build_temp_dir
734
+ Dir.chdir(@path)
735
+ FileUtils.touch(File.join(@path, 'Rakefile'))
736
+ end
737
+
738
+ after do
739
+ Dir.chdir(@original_path)
740
+ FileUtils.rm_rf(@path)
741
+ end
742
+
743
+ it 'return the config directory in the nearest enclosing path with a Rakefile along the root path to the current directory' do
744
+ @config.base_path.should == File.join(@path, 'config')
745
+ end
746
+
747
+ it 'leaves the current working path the same as when the base path lookup started' do
748
+ prior = Dir.pwd
749
+ @config.base_path
750
+ Dir.pwd.should == prior
751
+ end
752
+ end
753
+ end
754
+ end