whiskey_disk 0.5.4 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +129 -0
- data/README.markdown +21 -2
- data/VERSION +1 -1
- data/examples/deploy-local.yml +4 -0
- data/examples/deploy-multiple-remotes.yml +14 -0
- data/lib/whiskey_disk/config.rb +12 -1
- data/lib/whiskey_disk/rake.rb +6 -0
- data/lib/whiskey_disk.rb +42 -3
- data/spec/whiskey_disk/config_spec.rb +82 -11
- data/spec/whiskey_disk/rake_spec.rb +40 -6
- data/spec/whiskey_disk_spec.rb +147 -10
- data/whiskey_disk.gemspec +37 -36
- metadata +10 -8
- data/.gitignore +0 -1
data/CHANGELOG
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
|
2
|
+
0.6.0 / 2010-12-22
|
3
|
+
==================
|
4
|
+
|
5
|
+
* Version bump to 0.6.0
|
6
|
+
* Merge branch 'feature/multiple-domain-support' into develop
|
7
|
+
* adding a set of multi-domain examples
|
8
|
+
* adding a local deployment example
|
9
|
+
* updating output summary to be more readable
|
10
|
+
* updating README to document multi-domain deployments
|
11
|
+
* rake exit statuses reflect overall deployment/setup success
|
12
|
+
* adding WhiskeyDisk.success? method
|
13
|
+
* We now summarize runs, both local and remote.
|
14
|
+
* record results for local runs as well as remote ones
|
15
|
+
* now run SSH commands on multiple domains, serially, synchronously
|
16
|
+
* propagating changes allowed by normalizing 'domain' in config data
|
17
|
+
* normalize 'domain' values pulled from config files
|
18
|
+
* refactor config file writing in config spec
|
19
|
+
* WD.remote? now understands arrays of 'domain' entries in the config
|
20
|
+
* Merge branch 'release/0.5.4' into develop
|
21
|
+
* bump gemspec for 0.5.4 release
|
22
|
+
* Version bump to 0.5.4
|
23
|
+
* Removing Jeweler warning from Rakefile
|
24
|
+
* Merge branch 'feature/reduce-mocking-code-in-tests' into develop
|
25
|
+
* eliminating more stubbing specs from config_spec
|
26
|
+
* Removing more stub! calls from config specs
|
27
|
+
* removing YAML.load exception stub
|
28
|
+
* replacing some configuration_data stubs in config spec
|
29
|
+
* Remove CURRENT_FILE from config specs
|
30
|
+
* Removing CURRENT from config specs
|
31
|
+
* Removing more File.exists? stubs from config spec.
|
32
|
+
* Removing File.exists? stubs in config specs
|
33
|
+
* spec refactorings
|
34
|
+
* Removing has_config_repo? stubs from rake specs
|
35
|
+
* Using non-stubbed configuration in rake specs
|
36
|
+
* removing useless stub of :register_configuration
|
37
|
+
* And removing unneeded spec helper
|
38
|
+
* removing whiskey_disk config stubbing
|
39
|
+
* introducing use_config() spec helper
|
40
|
+
* Merge branch 'release/0.5.3' into develop
|
41
|
+
* updating gemspec for 0.5.3
|
42
|
+
* updating Contributors section of README
|
43
|
+
* Version bump to 0.5.3
|
44
|
+
* Merge branch 'feature/merge-pull-request-2' into develop
|
45
|
+
* Cosmetic and naming change in new config method
|
46
|
+
* fixing spec example description
|
47
|
+
* Reworking the config to append project name overrides to the env, since everything else is dependent thereupon
|
48
|
+
* tidying up the spec
|
49
|
+
* Allowing a manually specified project name in the bare config hash to be used as the parent project in the absence of one specified from the 'to' env setting
|
50
|
+
* Merge branch 'release/0.5.2' into develop
|
51
|
+
* updating gemspec for version 0.5.2
|
52
|
+
* Bumping version to 0.5.2
|
53
|
+
* Merge branch 'feature/ensure_target_needs_no_ruby' into develop
|
54
|
+
* Updating TODO list
|
55
|
+
* Updating README
|
56
|
+
* Merge branch 'feature/make_check_a_wd_option' into develop
|
57
|
+
* Updating TODO list
|
58
|
+
* Adding --check flag to wd command-line script
|
59
|
+
* Updating README with --check changes
|
60
|
+
* Merge branch 'feature/use_shallow_clone_on_setup' into develop
|
61
|
+
* Updating TODO list
|
62
|
+
* Adding lightning talk info to README
|
63
|
+
* Making shallow clones on initial setup
|
64
|
+
* Merge branch 'release/0.5.0' into develop
|
65
|
+
* updating gemspec for 0.5.0
|
66
|
+
* Version bump to 0.5.0
|
67
|
+
* Merge branch 'feature/alternate-hook-mechanism' into develop
|
68
|
+
* TODO list updates
|
69
|
+
* Make the rake test task do right by bacon
|
70
|
+
* Adding post_setup_script support
|
71
|
+
* Adding post_deploy_script support
|
72
|
+
* Reordering specs for post-setup/deployment tasks
|
73
|
+
* Updating README for post_*_script functionality
|
74
|
+
* TODO file updates
|
75
|
+
* Merge branch 'release/0.4.5' into develop
|
76
|
+
* new gemspec for 0.4.5 release
|
77
|
+
* Version bump to 0.4.5
|
78
|
+
* ENV settings now available to rake when searching for tasks
|
79
|
+
* Merge branch 'feature/refactor-methods' into develop
|
80
|
+
* refactoring common code for rake tasks
|
81
|
+
* further refactoring of clone_repository
|
82
|
+
* refactoring update checkout methods
|
83
|
+
* renaming conditional_clone
|
84
|
+
* Refactoring rake task code
|
85
|
+
* Merge branch 'release/0.4.4' into develop
|
86
|
+
* 0.4.4 gemspec
|
87
|
+
* Version bump to 0.4.4
|
88
|
+
* Merge branch 'feature/readme-updates' into develop
|
89
|
+
* TODO list tweakage
|
90
|
+
* README updates
|
91
|
+
* Merge branch 'release/0.4.3' into develop
|
92
|
+
* updating gemspec
|
93
|
+
* Version bump to 0.4.3
|
94
|
+
* Updating TODO
|
95
|
+
* Smarter setups
|
96
|
+
* TODO updates
|
97
|
+
* Version bump to 0.4.2
|
98
|
+
* Taking a different approach to rake task detection
|
99
|
+
* bumping gemspec
|
100
|
+
* Version bump to 0.4.1
|
101
|
+
* Fixing post_* hook edge case
|
102
|
+
* More README updates
|
103
|
+
* updating README
|
104
|
+
* updated gemspec
|
105
|
+
* adding staleness check docs to README
|
106
|
+
* Version bump to 0.4.0
|
107
|
+
* Make the staleness check actually work with bash.
|
108
|
+
* Adding "else" block to provide feedback when not stale
|
109
|
+
* More complete implementation of staleness checks
|
110
|
+
* Removing earlier abortive implementation of staleness checking
|
111
|
+
* Support for staleness checks
|
112
|
+
* Adding first pass at conditional staleness checks
|
113
|
+
* updating TODO list
|
114
|
+
* README note about post_* rake task dependencies
|
115
|
+
* updated gemspec
|
116
|
+
* Version bump to 0.3.1
|
117
|
+
* No longer require a Rakefile when --path isn't used
|
118
|
+
* We no longer do per-target config file overrides
|
119
|
+
* Don't run post_{setup,deploy} rake tasks without a deployed Rakefile
|
120
|
+
* use 'target' instead of 'environment' in README
|
121
|
+
* encoding < and >
|
122
|
+
* more README tweaks
|
123
|
+
* readme formatting tweak
|
124
|
+
* make sure README.markdown is displayed on install
|
125
|
+
* new and improved README
|
126
|
+
* adding a simple deploy.yml example to the README
|
127
|
+
* add link to live presentation to README
|
128
|
+
* adding a check flag for use with staleness checks
|
129
|
+
* english spike of staleness check in todo file
|
data/README.markdown
CHANGED
@@ -57,6 +57,12 @@ current local checkout.
|
|
57
57
|
do hands-free automated deployments whenever code is pushed to your
|
58
58
|
deployment branch of choice!
|
59
59
|
|
60
|
+
- You can deploy to multiple remote targets at once. Currently this is limited
|
61
|
+
to one-after-the-other synchronous deployments, but we're thinking about
|
62
|
+
doing them in parallel once we're happy with the stability of this (new)
|
63
|
+
feature.
|
64
|
+
|
65
|
+
|
60
66
|
### Assumptions ###
|
61
67
|
|
62
68
|
- your project is managed via git
|
@@ -100,7 +106,7 @@ As a rails plugin:
|
|
100
106
|
|
101
107
|
Known config file settings (if you're familiar with capistrano and vlad these should seem eerily familiar):
|
102
108
|
|
103
|
-
domain: host on which to deploy (
|
109
|
+
domain: host or list of hosts on which to deploy (these are ssh connect strings)
|
104
110
|
deploy_to: path to which to deploy main application
|
105
111
|
repository: git repo path for main application
|
106
112
|
branch: git branch to deploy from main application git repo (default: master)
|
@@ -116,7 +122,7 @@ Known config file settings (if you're familiar with capistrano and vlad these sh
|
|
116
122
|
A simple config/deploy.yml might look like:
|
117
123
|
|
118
124
|
qa:
|
119
|
-
domain: "ogc@
|
125
|
+
domain: "ogc@qa.ogtastic.com"
|
120
126
|
deploy_to: "/var/www/www.ogtastic.com"
|
121
127
|
repository: "git@ogtastic.com:www.ogtastic.com.git"
|
122
128
|
branch: "stable"
|
@@ -132,6 +138,19 @@ of deploy:setup
|
|
132
138
|
at the end of deploy:now
|
133
139
|
|
134
140
|
|
141
|
+
For deploying to multiple hosts, the config/deploy.yml might look like:
|
142
|
+
|
143
|
+
qa:
|
144
|
+
domain:
|
145
|
+
- "ogc@qa1.ogtastic.com"
|
146
|
+
- "ogc@qa2.ogtastic.com""
|
147
|
+
deploy_to: "/var/www/www.ogtastic.com"
|
148
|
+
repository: "git@ogtastic.com:www.ogtastic.com.git"
|
149
|
+
branch: "stable"
|
150
|
+
rake_env:
|
151
|
+
RAILS_ENV: 'production'
|
152
|
+
|
153
|
+
|
135
154
|
### post\_deploy\_script and post\_setup\_script ###
|
136
155
|
|
137
156
|
Whiskey\_disk provides rake task hooks (deploy:post\_setup and deploy:post\_deploy) to allow running custom
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.0
|
@@ -0,0 +1,14 @@
|
|
1
|
+
multi:
|
2
|
+
domain:
|
3
|
+
- "ogc@hoenir.websages.com"
|
4
|
+
- "ogc@nerthus.websages.com"
|
5
|
+
deploy_to: "/tmp/test-deployment/"
|
6
|
+
repository: "git@git.ogtastic.com:whiskey_disk.git"
|
7
|
+
branch: "develop"
|
8
|
+
badmulti:
|
9
|
+
domain:
|
10
|
+
- "ogc@hoenir.websages.com"
|
11
|
+
- "ogc@bogus.example.com"
|
12
|
+
deploy_to: "/tmp/test-deployment/"
|
13
|
+
repository: "git@git.ogtastic.com:whiskey_disk.git"
|
14
|
+
branch: "develop"
|
data/lib/whiskey_disk/config.rb
CHANGED
@@ -103,9 +103,20 @@ class WhiskeyDisk
|
|
103
103
|
override_project_name!(data)
|
104
104
|
{ project_name => data }
|
105
105
|
end
|
106
|
+
|
107
|
+
def normalize_domain(data)
|
108
|
+
data.each_pair do |project, project_data|
|
109
|
+
project_data.each_pair do |target, target_data|
|
110
|
+
if target_data['domain']
|
111
|
+
cleaned = [ target_data['domain'] ].flatten.delete_if { |m| m.nil? or m == '' }
|
112
|
+
target_data['domain'] = (cleaned.empty? ? nil : cleaned)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
106
117
|
|
107
118
|
def normalize_data(data)
|
108
|
-
add_project_scoping(add_environment_scoping(data.clone))
|
119
|
+
normalize_domain(add_project_scoping(add_environment_scoping(data.clone)))
|
109
120
|
end
|
110
121
|
|
111
122
|
def load_data
|
data/lib/whiskey_disk/rake.rb
CHANGED
@@ -13,6 +13,9 @@ namespace :deploy do
|
|
13
13
|
WhiskeyDisk.refresh_configuration if WhiskeyDisk.has_config_repo?
|
14
14
|
WhiskeyDisk.run_post_setup_hooks
|
15
15
|
WhiskeyDisk.flush
|
16
|
+
WhiskeyDisk.summarize
|
17
|
+
|
18
|
+
exit(1) unless WhiskeyDisk.success?
|
16
19
|
end
|
17
20
|
|
18
21
|
desc "Deploy now."
|
@@ -23,6 +26,9 @@ namespace :deploy do
|
|
23
26
|
WhiskeyDisk.refresh_configuration if WhiskeyDisk.has_config_repo?
|
24
27
|
WhiskeyDisk.run_post_deploy_hooks
|
25
28
|
WhiskeyDisk.flush
|
29
|
+
WhiskeyDisk.summarize
|
30
|
+
|
31
|
+
exit(1) unless WhiskeyDisk.success?
|
26
32
|
end
|
27
33
|
|
28
34
|
task :post_setup do
|
data/lib/whiskey_disk.rb
CHANGED
@@ -3,11 +3,13 @@ require File.expand_path(File.join(File.dirname(__FILE__), 'whiskey_disk', 'conf
|
|
3
3
|
class WhiskeyDisk
|
4
4
|
class << self
|
5
5
|
attr_writer :configuration
|
6
|
+
attr_reader :results
|
6
7
|
|
7
8
|
def reset
|
8
9
|
@configuration = nil
|
9
10
|
@buffer = nil
|
10
11
|
@staleness_checks = nil
|
12
|
+
@results = nil
|
11
13
|
end
|
12
14
|
|
13
15
|
def buffer
|
@@ -39,7 +41,7 @@ class WhiskeyDisk
|
|
39
41
|
end
|
40
42
|
|
41
43
|
def remote?
|
42
|
-
|
44
|
+
!! self[:domain]
|
43
45
|
end
|
44
46
|
|
45
47
|
def has_config_repo?
|
@@ -109,11 +111,48 @@ class WhiskeyDisk
|
|
109
111
|
|
110
112
|
def run(cmd)
|
111
113
|
needs(:domain)
|
112
|
-
|
114
|
+
self[:domain].each do |domain|
|
115
|
+
status = system('ssh', '-v', domain, "set -x; " + cmd)
|
116
|
+
record_result(domain, status)
|
117
|
+
end
|
113
118
|
end
|
114
119
|
|
115
120
|
def flush
|
116
|
-
|
121
|
+
return run(bundle) if remote?
|
122
|
+
record_result('local', system(bundle))
|
123
|
+
end
|
124
|
+
|
125
|
+
def record_result(domain, status)
|
126
|
+
@results ||= []
|
127
|
+
@results << { :domain => domain, :status => status }
|
128
|
+
end
|
129
|
+
|
130
|
+
def summarize
|
131
|
+
puts
|
132
|
+
puts "Results:"
|
133
|
+
if results and not results.empty?
|
134
|
+
successes = failures = total = 0
|
135
|
+
results.each do |result|
|
136
|
+
total += 1
|
137
|
+
if result[:status]
|
138
|
+
successes += 1
|
139
|
+
else
|
140
|
+
failures += 1
|
141
|
+
end
|
142
|
+
|
143
|
+
puts "#{result[:domain]} => #{result[:status] ? 'succeeded' : 'failed'}."
|
144
|
+
end
|
145
|
+
puts "Total: #{total} deployment#{total == 1 ? '' : 's'}, " +
|
146
|
+
"#{successes} success#{successes == 1 ? '' : 'es'}, " +
|
147
|
+
"#{failures} failure#{failures == 1 ? '' : 's'}."
|
148
|
+
else
|
149
|
+
puts "No deployments to report."
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def success?
|
154
|
+
return true if !results or results.empty?
|
155
|
+
results.all? {|result| result[:status] }
|
117
156
|
end
|
118
157
|
|
119
158
|
def if_file_present(path, cmd)
|
@@ -15,6 +15,10 @@ def build_temp_dir
|
|
15
15
|
Dir.mktmpdir
|
16
16
|
end
|
17
17
|
|
18
|
+
def write_config_file(data)
|
19
|
+
File.open(@config_file, 'w') { |f| f.puts YAML.dump(data) }
|
20
|
+
end
|
21
|
+
|
18
22
|
describe WhiskeyDisk::Config do
|
19
23
|
describe 'when computing the environment name' do
|
20
24
|
it 'should return false when there is no ENV["to"] setting' do
|
@@ -106,53 +110,53 @@ describe WhiskeyDisk::Config do
|
|
106
110
|
end
|
107
111
|
|
108
112
|
it 'should fail if the configuration file does not define data for this environment' do
|
109
|
-
|
113
|
+
write_config_file('foo' => { 'production' => { 'a' => 'b'} })
|
110
114
|
lambda { WhiskeyDisk::Config.fetch }.should.raise
|
111
115
|
end
|
112
116
|
|
113
117
|
it 'should return the configuration yaml file data for this environment as a hash' do
|
114
118
|
staging = { 'foo' => 'bar', 'repository' => 'xyzzy' }
|
115
|
-
|
119
|
+
write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
|
116
120
|
result = WhiskeyDisk::Config.fetch
|
117
121
|
staging.each_pair do |k,v|
|
118
122
|
result[k].should == v
|
119
123
|
end
|
120
124
|
end
|
121
|
-
|
125
|
+
|
122
126
|
it 'should not include configuration information for other environments in the returned hash' do
|
123
127
|
staging = { 'foo' => 'bar', 'baz' => 'xyzzy' }
|
124
|
-
|
128
|
+
write_config_file('production' => { 'repository' => 'c', 'a' => 'b'}, 'staging' => staging)
|
125
129
|
WhiskeyDisk::Config.fetch['a'].should.be.nil
|
126
130
|
end
|
127
131
|
|
128
132
|
it 'should include the environment in the hash' do
|
129
133
|
staging = { 'foo' => 'bar', 'baz' => 'xyzzy' }
|
130
|
-
|
134
|
+
write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
|
131
135
|
WhiskeyDisk::Config.fetch['environment'].should == 'staging'
|
132
136
|
end
|
133
137
|
|
134
138
|
it 'should not allow overriding the environment in the configuration file' do
|
135
139
|
staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'environment' => 'production' }
|
136
|
-
|
140
|
+
write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
|
137
141
|
WhiskeyDisk::Config.fetch['environment'].should == 'staging'
|
138
142
|
end
|
139
143
|
|
140
144
|
it 'should include the project handle in the hash' do
|
141
145
|
staging = { 'foo' => 'bar', 'repository' => 'xyzzy' }
|
142
|
-
|
146
|
+
write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
|
143
147
|
WhiskeyDisk::Config.fetch['project'].should == 'foo'
|
144
148
|
end
|
145
149
|
|
146
150
|
it 'should not allow overriding the project handle in the configuration file when a project root is specified' do
|
147
151
|
staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }
|
148
|
-
|
152
|
+
write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
|
149
153
|
WhiskeyDisk::Config.fetch['project'].should == 'foo'
|
150
154
|
end
|
151
155
|
|
152
156
|
it 'should allow overriding the project handle in the configuration file when a project root is not specified' do
|
153
157
|
ENV['to'] = @env = 'staging'
|
154
158
|
staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }
|
155
|
-
|
159
|
+
write_config_file('production' => { 'repository' => 'b'}, 'staging' => staging)
|
156
160
|
WhiskeyDisk::Config.fetch['project'].should == 'diskey_whisk'
|
157
161
|
end
|
158
162
|
end
|
@@ -198,16 +202,83 @@ describe WhiskeyDisk::Config do
|
|
198
202
|
end
|
199
203
|
|
200
204
|
it 'should return a normalized version of the un-YAMLized configuration data' do
|
201
|
-
|
205
|
+
write_config_file('repository' => 'x')
|
202
206
|
WhiskeyDisk::Config.load_data.should == { 'foo' => { 'bar' => { 'repository' => 'x' } } }
|
203
207
|
end
|
208
|
+
|
209
|
+
describe 'normalizing domains' do
|
210
|
+
before do
|
211
|
+
write_config_file(
|
212
|
+
'foo' => {
|
213
|
+
'bar' => { 'repository' => 'x', 'domain' => [ 'user@example.com', nil, 'foo@domain.com', '' ]},
|
214
|
+
'baz' => { 'repository' => 'x', 'domain' => [ 'bar@example.com', 'baz@domain.com' ]},
|
215
|
+
'xyz' => { 'repository' => 'x' },
|
216
|
+
'abc' => { 'repository' => 'x', 'domain' => 'what@example.com' },
|
217
|
+
'eee' => { 'repository' => 'x', 'domain' => '' }
|
218
|
+
},
|
219
|
+
'zyx' => {
|
220
|
+
'def' => { 'repository' => 'x', 'domain' => [ 'user@example.com', nil, 'foo@domain.com', '' ]},
|
221
|
+
'hij' => { 'repository' => 'x', 'domain' => [ 'bar@example.com', 'baz@domain.com' ]},
|
222
|
+
'xyz' => { 'repository' => 'x' },
|
223
|
+
'abc' => { 'repository' => 'x', 'domain' => 'what@example.com' },
|
224
|
+
'eee' => { 'repository' => 'x', 'domain' => '' }
|
225
|
+
}
|
226
|
+
)
|
227
|
+
end
|
228
|
+
|
229
|
+
describe 'and no domain has been specified' do
|
230
|
+
it 'should leave the domain as nil' do
|
231
|
+
WhiskeyDisk::Config.load_data['foo']['xyz']['domain'].should.be.nil
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'should handle nil domains across all projects and targets' do
|
235
|
+
WhiskeyDisk::Config.load_data['zyx']['xyz']['domain'].should.be.nil
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
describe 'and a single domain has been specified' do
|
240
|
+
it 'should return domain as nil if the specified domain was empty' do
|
241
|
+
WhiskeyDisk::Config.load_data['foo']['eee']['domain'].should.be.nil
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'should handle empty specified domains across all projects and targets' do
|
245
|
+
WhiskeyDisk::Config.load_data['zyx']['eee']['domain'].should.be.nil
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'should return domain as a single list of the specified domain if the specified domain was not empty' do
|
249
|
+
WhiskeyDisk::Config.load_data['foo']['abc']['domain'].should == ['what@example.com']
|
250
|
+
end
|
251
|
+
|
252
|
+
it 'should handle single specified domains across all projects and targets' do
|
253
|
+
WhiskeyDisk::Config.load_data['zyx']['abc']['domain'].should == ['what@example.com']
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
describe 'and a list of domains was specified' do
|
258
|
+
it 'should return the list of domains' do
|
259
|
+
WhiskeyDisk::Config.load_data['foo']['baz']['domain'].should == [ 'bar@example.com', 'baz@domain.com' ]
|
260
|
+
end
|
261
|
+
|
262
|
+
it 'should handle lists of domains across all projects and targets' do
|
263
|
+
WhiskeyDisk::Config.load_data['zyx']['hij']['domain'].should == [ 'bar@example.com', 'baz@domain.com' ]
|
264
|
+
end
|
265
|
+
|
266
|
+
it 'should remove any blank or nil domains from the list' do
|
267
|
+
WhiskeyDisk::Config.load_data['foo']['bar']['domain'].should == ['user@example.com', 'foo@domain.com' ]
|
268
|
+
end
|
269
|
+
|
270
|
+
it 'should handle cleaning up blanks and nils across all projects and targets' do
|
271
|
+
WhiskeyDisk::Config.load_data['zyx']['def']['domain'].should == ['user@example.com', 'foo@domain.com' ]
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
204
275
|
end
|
205
276
|
|
206
277
|
describe 'normalizing YAML data from the configuration file' do
|
207
278
|
before do
|
208
279
|
ENV['to'] = @env = 'foo:staging'
|
209
280
|
|
210
|
-
@bare_data = { 'repository' => 'git://foo/bar.git', 'domain' => 'ogc@ogtastic.com' }
|
281
|
+
@bare_data = { 'repository' => 'git://foo/bar.git', 'domain' => ['ogc@ogtastic.com'] }
|
211
282
|
@env_data = { 'staging' => @bare_data }
|
212
283
|
@proj_data = { 'foo' => @env_data }
|
213
284
|
end
|
@@ -25,20 +25,23 @@ describe 'rake tasks' do
|
|
25
25
|
:update_configuration_repository_checkout,
|
26
26
|
:refresh_configuration,
|
27
27
|
:run_post_setup_hooks,
|
28
|
-
:flush
|
28
|
+
:flush,
|
29
|
+
:summarize
|
29
30
|
].each do |meth|
|
30
|
-
WhiskeyDisk.stub!(meth)
|
31
|
+
WhiskeyDisk.stub!(meth)
|
31
32
|
end
|
33
|
+
|
34
|
+
WhiskeyDisk.stub!(:success?).and_return(true)
|
32
35
|
end
|
33
36
|
|
34
37
|
it 'should make changes on the specified domain when a domain is specified' do
|
35
|
-
WhiskeyDisk.configuration = { 'domain' => 'some domain' }
|
38
|
+
WhiskeyDisk.configuration = { 'domain' => [ 'some domain' ] }
|
36
39
|
@rake["deploy:setup"].invoke
|
37
40
|
WhiskeyDisk.should.be.remote
|
38
41
|
end
|
39
42
|
|
40
43
|
it 'should make changes on the local system when no domain is specified' do
|
41
|
-
WhiskeyDisk.configuration = { 'domain' =>
|
44
|
+
WhiskeyDisk.configuration = { 'domain' => nil }
|
42
45
|
WhiskeyDisk.should.not.be.remote
|
43
46
|
end
|
44
47
|
|
@@ -126,6 +129,20 @@ describe 'rake tasks' do
|
|
126
129
|
WhiskeyDisk.should.receive(:flush)
|
127
130
|
@rake["deploy:setup"].invoke
|
128
131
|
end
|
132
|
+
|
133
|
+
it 'should summarize the results of the setup run' do
|
134
|
+
WhiskeyDisk.should.receive(:summarize)
|
135
|
+
@rake["deploy:setup"].invoke
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'should not exit in error if all setup runs were successful' do
|
139
|
+
lambda { @rake["deploy:setup"].invoke }.should.not.raise(SystemExit)
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'should exit in error if some setup run was unsuccessful' do
|
143
|
+
WhiskeyDisk.stub!(:success?).and_return(false)
|
144
|
+
lambda { @rake["deploy:setup"].invoke }.should.raise(SystemExit)
|
145
|
+
end
|
129
146
|
end
|
130
147
|
|
131
148
|
describe 'deploy:now' do
|
@@ -137,14 +154,17 @@ describe 'rake tasks' do
|
|
137
154
|
:update_configuration_repository_checkout,
|
138
155
|
:refresh_configuration,
|
139
156
|
:run_post_deploy_hooks,
|
140
|
-
:flush
|
157
|
+
:flush,
|
158
|
+
:summarize
|
141
159
|
].each do |meth|
|
142
160
|
WhiskeyDisk.stub!(meth)
|
143
161
|
end
|
162
|
+
|
163
|
+
WhiskeyDisk.stub!(:success?).and_return(true)
|
144
164
|
end
|
145
165
|
|
146
166
|
it 'should make changes on the specified domain when a domain is specified' do
|
147
|
-
WhiskeyDisk.configuration = { 'domain' => 'some domain'}
|
167
|
+
WhiskeyDisk.configuration = { 'domain' => [ 'some domain' ]}
|
148
168
|
@rake["deploy:now"].invoke
|
149
169
|
WhiskeyDisk.should.be.remote
|
150
170
|
end
|
@@ -202,6 +222,20 @@ describe 'rake tasks' do
|
|
202
222
|
WhiskeyDisk.should.receive(:flush)
|
203
223
|
@rake["deploy:now"].invoke
|
204
224
|
end
|
225
|
+
|
226
|
+
it 'should summarize the results of the deployment run' do
|
227
|
+
WhiskeyDisk.should.receive(:summarize)
|
228
|
+
@rake["deploy:now"].invoke
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'should not exit in error if all deployment runs were successful' do
|
232
|
+
lambda { @rake["deploy:now"].invoke }.should.not.raise(SystemExit)
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'should exit in error if some deployment run was unsuccessful' do
|
236
|
+
WhiskeyDisk.stub!(:success?).and_return(false)
|
237
|
+
lambda { @rake["deploy:now"].invoke }.should.raise(SystemExit)
|
238
|
+
end
|
205
239
|
end
|
206
240
|
|
207
241
|
describe 'deploy:post_setup' do
|
data/spec/whiskey_disk_spec.rb
CHANGED
@@ -2,6 +2,21 @@ require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper.rb'))
|
|
2
2
|
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'whiskey_disk'))
|
3
3
|
require 'rake'
|
4
4
|
|
5
|
+
# WhiskeyDisk subclass that allows us to test in what order ssh commands are
|
6
|
+
# issued by WhiskeyDisk.run
|
7
|
+
class TestOrderedExecution < WhiskeyDisk
|
8
|
+
class << self
|
9
|
+
def commands
|
10
|
+
@commands
|
11
|
+
end
|
12
|
+
|
13
|
+
def system(*args)
|
14
|
+
@commands ||= []
|
15
|
+
@commands << args.join(' ')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
5
20
|
describe 'requiring the main library' do
|
6
21
|
before do
|
7
22
|
Rake.application = @rake = Rake::Application.new
|
@@ -36,19 +51,19 @@ describe 'WhiskeyDisk' do
|
|
36
51
|
lambda { WhiskeyDisk.remote?(:foo) }.should.raise(ArgumentError)
|
37
52
|
end
|
38
53
|
|
39
|
-
it 'should return true if the configuration includes a non-empty domain setting' do
|
40
|
-
@parameters['domain'] = 'smeghost'
|
41
|
-
WhiskeyDisk.remote?.should == true
|
42
|
-
end
|
43
|
-
|
44
54
|
it 'should return false if the configuration includes a nil domain setting' do
|
45
55
|
@parameters['domain'] = nil
|
46
56
|
WhiskeyDisk.remote?.should == false
|
47
57
|
end
|
58
|
+
|
59
|
+
it 'should return true if the configuration includes a non-empty domain setting' do
|
60
|
+
@parameters['domain'] = ['smeghost']
|
61
|
+
WhiskeyDisk.remote?.should == true
|
62
|
+
end
|
48
63
|
|
49
|
-
it 'should return
|
50
|
-
@parameters['domain'] = ''
|
51
|
-
WhiskeyDisk.remote?.should ==
|
64
|
+
it 'should return true if the configuration includes a multiple domain settings' do
|
65
|
+
@parameters['domain'] = ['smeghost', 'faphost']
|
66
|
+
WhiskeyDisk.remote?.should == true
|
52
67
|
end
|
53
68
|
end
|
54
69
|
|
@@ -532,6 +547,7 @@ describe 'WhiskeyDisk' do
|
|
532
547
|
|
533
548
|
describe 'when running locally' do
|
534
549
|
before do
|
550
|
+
WhiskeyDisk.reset
|
535
551
|
WhiskeyDisk.configuration = { 'deploy_to' => '/path/to/main/repo' }
|
536
552
|
WhiskeyDisk.stub!(:bundle).and_return('command string')
|
537
553
|
WhiskeyDisk.stub!(:system)
|
@@ -548,6 +564,18 @@ describe 'WhiskeyDisk' do
|
|
548
564
|
WhiskeyDisk.should.receive(:system).with('command string')
|
549
565
|
WhiskeyDisk.flush
|
550
566
|
end
|
567
|
+
|
568
|
+
it 'should record a failure result when the system command fails' do
|
569
|
+
WhiskeyDisk.stub!(:system).and_return(false)
|
570
|
+
WhiskeyDisk.flush
|
571
|
+
WhiskeyDisk.results.should == [ { :domain => 'local', :status => false } ]
|
572
|
+
end
|
573
|
+
|
574
|
+
it 'should record a success result when the system command succeeds' do
|
575
|
+
WhiskeyDisk.stub!(:system).and_return(true)
|
576
|
+
WhiskeyDisk.flush
|
577
|
+
WhiskeyDisk.results.should == [ { :domain => 'local', :status => true } ]
|
578
|
+
end
|
551
579
|
end
|
552
580
|
end
|
553
581
|
|
@@ -753,6 +781,7 @@ describe 'WhiskeyDisk' do
|
|
753
781
|
|
754
782
|
describe 'when running a command string remotely' do
|
755
783
|
before do
|
784
|
+
WhiskeyDisk.reset
|
756
785
|
@domain = 'ogc@ogtastic.com'
|
757
786
|
WhiskeyDisk.configuration = { 'domain' => @domain }
|
758
787
|
WhiskeyDisk.stub!(:system)
|
@@ -770,11 +799,119 @@ describe 'WhiskeyDisk' do
|
|
770
799
|
WhiskeyDisk.configuration = {}
|
771
800
|
lambda { WhiskeyDisk.run('ls') }.should.raise
|
772
801
|
end
|
773
|
-
|
802
|
+
|
774
803
|
it 'should pass the string to ssh with verbosity enabled' do
|
775
804
|
WhiskeyDisk.should.receive(:system).with('ssh', '-v', @domain, "set -x; ls")
|
776
805
|
WhiskeyDisk.run('ls')
|
777
806
|
end
|
807
|
+
|
808
|
+
describe 'and multiple domains are specified' do
|
809
|
+
before do
|
810
|
+
@domains = [ 'ogc@ogtastic.com', 'foo@example.com' ]
|
811
|
+
end
|
812
|
+
|
813
|
+
it 'should run the command via ssh on each domain in the order specified in the configuration file' do
|
814
|
+
TestOrderedExecution.configuration = { 'domain' => @domains }
|
815
|
+
TestOrderedExecution.run('ls')
|
816
|
+
TestOrderedExecution.commands.should == [
|
817
|
+
"ssh -v ogc@ogtastic.com set -x; ls",
|
818
|
+
"ssh -v foo@example.com set -x; ls"
|
819
|
+
]
|
820
|
+
end
|
821
|
+
|
822
|
+
it 'should not fail if an ssh command fails' do
|
823
|
+
WhiskeyDisk.configuration = { 'domain' => @domains }
|
824
|
+
WhiskeyDisk.stub!(:system).with('ssh', '-v', 'ogc@ogtastic.com', 'set -x; ls').and_return(false)
|
825
|
+
lambda { WhiskeyDisk.run('ls') }.should.not.raise(RuntimeError)
|
826
|
+
end
|
827
|
+
|
828
|
+
it 'should continue to run the remaining ssh commands when an ssh fails' do
|
829
|
+
WhiskeyDisk.configuration = { 'domain' => @domains }
|
830
|
+
WhiskeyDisk.stub!(:system).with('ssh', '-v', 'ogc@ogtastic.com', 'set -x; ls').and_return(false)
|
831
|
+
WhiskeyDisk.should.receive(:system).with('ssh', '-v', 'foo@example.com', 'set -x; ls')
|
832
|
+
WhiskeyDisk.run('ls')
|
833
|
+
end
|
834
|
+
|
835
|
+
it 'should record failure and success status for issued ssh commands' do
|
836
|
+
WhiskeyDisk.configuration = { 'domain' => @domains }
|
837
|
+
WhiskeyDisk.stub!(:system).with('ssh', '-v', 'ogc@ogtastic.com', 'set -x; ls').and_return(false)
|
838
|
+
WhiskeyDisk.stub!(:system).with('ssh', '-v', 'foo@example.com', 'set -x; ls').and_return(true)
|
839
|
+
WhiskeyDisk.run('ls')
|
840
|
+
WhiskeyDisk.results.should == [ { :domain => 'ogc@ogtastic.com', :status => false },
|
841
|
+
{ :domain => 'foo@example.com', :status => true} ]
|
842
|
+
end
|
843
|
+
end
|
844
|
+
end
|
845
|
+
|
846
|
+
describe 'determining if all the deployments succeeded' do
|
847
|
+
before do
|
848
|
+
WhiskeyDisk.reset
|
849
|
+
end
|
850
|
+
|
851
|
+
it 'should work without arguments' do
|
852
|
+
lambda { WhiskeyDisk.success? }.should.not.raise(ArgumentError)
|
853
|
+
end
|
854
|
+
|
855
|
+
it 'should not allow arguments' do
|
856
|
+
lambda { WhiskeyDisk.success?(:foo) }.should.raise(ArgumentError)
|
857
|
+
end
|
858
|
+
|
859
|
+
it 'should return true if there are no results recorded' do
|
860
|
+
WhiskeyDisk.success?.should.be.true
|
861
|
+
end
|
862
|
+
|
863
|
+
it 'should return true if all recorded results have true statuses' do
|
864
|
+
WhiskeyDisk.record_result('1', true)
|
865
|
+
WhiskeyDisk.record_result('2', true)
|
866
|
+
WhiskeyDisk.record_result('3', true)
|
867
|
+
WhiskeyDisk.success?.should.be.true
|
868
|
+
end
|
869
|
+
|
870
|
+
it 'should return false if any recorded result has a false status' do
|
871
|
+
WhiskeyDisk.record_result('1', true)
|
872
|
+
WhiskeyDisk.record_result('2', false)
|
873
|
+
WhiskeyDisk.record_result('3', true)
|
874
|
+
WhiskeyDisk.success?.should.be.false
|
875
|
+
end
|
876
|
+
end
|
877
|
+
|
878
|
+
describe 'summarizing the results of a run' do
|
879
|
+
before do
|
880
|
+
WhiskeyDisk.reset
|
881
|
+
WhiskeyDisk.stub!(:puts)
|
882
|
+
end
|
883
|
+
|
884
|
+
it 'should work without arguments' do
|
885
|
+
lambda { WhiskeyDisk.summarize }.should.not.raise(ArgumentError)
|
886
|
+
end
|
887
|
+
|
888
|
+
it 'should not allow arguments' do
|
889
|
+
lambda { WhiskeyDisk.summarize(:foo) }.should.raise(ArgumentError)
|
890
|
+
end
|
891
|
+
|
892
|
+
it 'should output a no runs message when no results are recorded' do
|
893
|
+
WhiskeyDisk.should.receive(:puts).with('No deployments to report.')
|
894
|
+
WhiskeyDisk.summarize
|
895
|
+
end
|
896
|
+
|
897
|
+
describe 'and there are results recorded' do
|
898
|
+
before do
|
899
|
+
WhiskeyDisk.record_result('foo@bar.com', false)
|
900
|
+
WhiskeyDisk.record_result('ogc@ogtastic.com', true)
|
901
|
+
WhiskeyDisk.record_result('user@example.com', true)
|
902
|
+
end
|
903
|
+
|
904
|
+
it 'should output a status line for each recorded deployment run' do
|
905
|
+
WhiskeyDisk.should.receive(:puts).with('foo@bar.com => failed.')
|
906
|
+
WhiskeyDisk.should.receive(:puts).with('ogc@ogtastic.com => succeeded.')
|
907
|
+
WhiskeyDisk.should.receive(:puts).with('user@example.com => succeeded.')
|
908
|
+
WhiskeyDisk.summarize
|
909
|
+
end
|
910
|
+
|
911
|
+
it 'should output a summary line including the total runs, count of failures and count of successes.' do
|
912
|
+
WhiskeyDisk.should.receive(:puts).with('Total: 3 deployments, 2 successes, 1 failure.')
|
913
|
+
WhiskeyDisk.summarize
|
914
|
+
end
|
915
|
+
end
|
778
916
|
end
|
779
917
|
end
|
780
|
-
|
data/whiskey_disk.gemspec
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# Generated by jeweler
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{whiskey_disk}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.6.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Rick Bradley"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-12-22}
|
13
13
|
s.default_executable = %q{wd}
|
14
14
|
s.description = %q{Opinionated gem for doing fast git-based server deployments.}
|
15
15
|
s.email = %q{rick@rickbradley.com}
|
@@ -18,46 +18,47 @@ Gem::Specification.new do |s|
|
|
18
18
|
"README.markdown"
|
19
19
|
]
|
20
20
|
s.files = [
|
21
|
-
"
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
21
|
+
"CHANGELOG",
|
22
|
+
"MIT-LICENSE",
|
23
|
+
"README.markdown",
|
24
|
+
"Rakefile",
|
25
|
+
"TODO.txt",
|
26
|
+
"VERSION",
|
27
|
+
"WHY.txt",
|
28
|
+
"bin/wd",
|
29
|
+
"examples/deploy-local.yml",
|
30
|
+
"examples/deploy-multiple-remotes.yml",
|
31
|
+
"examples/deploy-staging.yml",
|
32
|
+
"examples/deploy.rake",
|
33
|
+
"examples/deploy.yml",
|
34
|
+
"init.rb",
|
35
|
+
"install.rb",
|
36
|
+
"lib/whiskey_disk.rb",
|
37
|
+
"lib/whiskey_disk/config.rb",
|
38
|
+
"lib/whiskey_disk/rake.rb",
|
39
|
+
"spec/.bacon",
|
40
|
+
"spec/init_spec.rb",
|
41
|
+
"spec/install_spec.rb",
|
42
|
+
"spec/spec_helper.rb",
|
43
|
+
"spec/wd_command_spec.rb",
|
44
|
+
"spec/whiskey_disk/config_spec.rb",
|
45
|
+
"spec/whiskey_disk/rake_spec.rb",
|
46
|
+
"spec/whiskey_disk_spec.rb",
|
47
|
+
"tasks/deploy.rake",
|
48
|
+
"whiskey_disk.gemspec"
|
47
49
|
]
|
48
50
|
s.homepage = %q{http://github.com/flogic/whiskey_disk}
|
49
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
50
51
|
s.require_paths = ["lib"]
|
51
52
|
s.rubygems_version = %q{1.3.7}
|
52
53
|
s.summary = %q{embarrassingly fast deployments.}
|
53
54
|
s.test_files = [
|
54
55
|
"spec/init_spec.rb",
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
56
|
+
"spec/install_spec.rb",
|
57
|
+
"spec/spec_helper.rb",
|
58
|
+
"spec/wd_command_spec.rb",
|
59
|
+
"spec/whiskey_disk/config_spec.rb",
|
60
|
+
"spec/whiskey_disk/rake_spec.rb",
|
61
|
+
"spec/whiskey_disk_spec.rb"
|
61
62
|
]
|
62
63
|
|
63
64
|
if s.respond_to? :specification_version then
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: whiskey_disk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 6
|
9
|
+
- 0
|
10
|
+
version: 0.6.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Rick Bradley
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-12-22 00:00:00 -05:00
|
19
19
|
default_executable: wd
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -41,7 +41,7 @@ extensions: []
|
|
41
41
|
extra_rdoc_files:
|
42
42
|
- README.markdown
|
43
43
|
files:
|
44
|
-
-
|
44
|
+
- CHANGELOG
|
45
45
|
- MIT-LICENSE
|
46
46
|
- README.markdown
|
47
47
|
- Rakefile
|
@@ -49,6 +49,8 @@ files:
|
|
49
49
|
- VERSION
|
50
50
|
- WHY.txt
|
51
51
|
- bin/wd
|
52
|
+
- examples/deploy-local.yml
|
53
|
+
- examples/deploy-multiple-remotes.yml
|
52
54
|
- examples/deploy-staging.yml
|
53
55
|
- examples/deploy.rake
|
54
56
|
- examples/deploy.yml
|
@@ -72,8 +74,8 @@ homepage: http://github.com/flogic/whiskey_disk
|
|
72
74
|
licenses: []
|
73
75
|
|
74
76
|
post_install_message:
|
75
|
-
rdoc_options:
|
76
|
-
|
77
|
+
rdoc_options: []
|
78
|
+
|
77
79
|
require_paths:
|
78
80
|
- lib
|
79
81
|
required_ruby_version: !ruby/object:Gem::Requirement
|
data/.gitignore
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
pkg/
|