kumade 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ require 'thor'
2
+
3
+ module Kumade
4
+ class ThorTask < Thor
5
+ default_task :deploy
6
+
7
+ desc "deploy [ENV]", "Deploy to ENV (default: staging)"
8
+ method_option :pretend, :aliases => "-p", :desc => "Pretend Mode - print out what kumade would do"
9
+ def deploy(environment = 'staging')
10
+ say("==> In Pretend Mode", :red) if options[:pretend]
11
+ say "==> Deploying to: #{environment}"
12
+
13
+ Deployer.new(options[:pretend]).deploy_to(environment)
14
+
15
+ say "==> Deployed to: #{environment}", :green
16
+ end
17
+ end
18
+ end
@@ -1,3 +1,3 @@
1
- class Kumade
2
- VERSION = "0.0.2"
1
+ module Kumade
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1,586 @@
1
+ require 'spec_helper'
2
+ require 'jammit'
3
+
4
+ module Kumade
5
+ describe Deployer, "#pre_deploy" do
6
+ before { subject.stub(:say) }
7
+
8
+ it "calls the correct methods in order" do
9
+ %w(
10
+ ensure_clean_git
11
+ ensure_rake_passes
12
+ package_assets
13
+ git_push
14
+ ).each do |task|
15
+ subject.should_receive(task).ordered.and_return(true)
16
+ end
17
+
18
+ subject.pre_deploy
19
+ end
20
+
21
+ it "pushes to origin" do
22
+ %w(
23
+ ensure_clean_git
24
+ ensure_rake_passes
25
+ package_assets
26
+ ).each do |task|
27
+ subject.stub(task)
28
+ end
29
+
30
+ subject.should_receive(:git_push).with('origin')
31
+ subject.pre_deploy
32
+ end
33
+ end
34
+
35
+ describe Deployer, "#deploy_to" do
36
+ let(:remote_name){ 'staging' }
37
+ let(:app_name){ 'kumade-staging' }
38
+
39
+ before do
40
+ subject.stub(:say)
41
+ force_add_heroku_remote(remote_name, app_name)
42
+ end
43
+
44
+ after { remove_remote(remote_name) }
45
+
46
+ it "calls the correct methods in order" do
47
+ subject.stub(:run => true)
48
+
49
+ subject.should_receive(:ensure_heroku_remote_exists_for).
50
+ ordered.
51
+ with(remote_name)
52
+
53
+ subject.should_receive(:pre_deploy).
54
+ ordered.
55
+ and_return(true)
56
+
57
+ subject.should_receive(:git_force_push).
58
+ ordered.
59
+ and_return(true)
60
+
61
+ subject.should_receive(:heroku_migrate).
62
+ ordered.
63
+ with(remote_name)
64
+
65
+ subject.deploy_to(remote_name)
66
+ end
67
+
68
+ it "deploys to the correct remote" do
69
+ subject.stub(:ensure_heroku_remote_exists_for => true,
70
+ :pre_deploy => true,
71
+ :run => true)
72
+
73
+ subject.should_receive(:git_force_push).with(remote_name)
74
+
75
+ subject.deploy_to(remote_name)
76
+ end
77
+ end
78
+
79
+ describe Deployer, "#git_push" do
80
+ let(:remote){ 'origin' }
81
+
82
+ before { subject.stub(:say) }
83
+
84
+ it "calls `git push`" do
85
+ subject.should_receive(:run).
86
+ with("git push #{remote} master").
87
+ and_return(true)
88
+ subject.git_push(remote)
89
+ end
90
+
91
+ context "when `git push` fails" do
92
+ before { subject.stub(:run => false) }
93
+
94
+ it "prints an error message" do
95
+ subject.should_receive(:error).with("Failed to push master -> #{remote}")
96
+
97
+ subject.git_push(remote)
98
+ end
99
+ end
100
+
101
+ context "when `git push` succeeds" do
102
+ before { subject.stub(:run => true) }
103
+
104
+ it "does not raise an error" do
105
+ subject.should_not_receive(:error)
106
+ subject.git_push(remote)
107
+ end
108
+
109
+ it "prints a success message" do
110
+ subject.should_receive(:success).with("Pushed master -> #{remote}")
111
+
112
+ subject.git_push(remote)
113
+ end
114
+ end
115
+ end
116
+
117
+ describe Deployer, "#git_force_push" do
118
+ let(:remote){ 'origin' }
119
+ before { subject.stub(:say) }
120
+
121
+ it "calls `git push -f`" do
122
+ subject.should_receive(:run).
123
+ with("git push -f #{remote} master").
124
+ and_return(true)
125
+ subject.git_force_push(remote)
126
+ end
127
+
128
+ context "when `git push -f` fails" do
129
+ before do
130
+ subject.stub(:run => false)
131
+ end
132
+
133
+ it "prints an error" do
134
+ subject.should_receive(:error).with("Failed to force push master -> #{remote}")
135
+ subject.git_force_push(remote)
136
+ end
137
+ end
138
+
139
+ context "when `git push -f` succeeds" do
140
+ before do
141
+ subject.stub(:run => true)
142
+ subject.stub(:say)
143
+ end
144
+
145
+ it "does not raise an error" do
146
+ subject.should_not_receive(:error)
147
+ subject.git_force_push(remote)
148
+ end
149
+
150
+ it "prints a success message" do
151
+ subject.should_receive(:success).
152
+ with("Force pushed master -> #{remote}")
153
+
154
+ subject.git_force_push(remote)
155
+ end
156
+ end
157
+ end
158
+
159
+ describe Deployer, "#ensure_clean_git" do
160
+ before { subject.stub(:say) }
161
+
162
+ context "when git is dirty" do
163
+ before { subject.stub(:git_dirty? => true) }
164
+
165
+ it "prints an error" do
166
+ subject.should_receive(:error).with("Cannot deploy: repo is not clean.")
167
+ subject.ensure_clean_git
168
+ end
169
+ end
170
+
171
+ context "when git is clean" do
172
+ before { subject.stub(:git_dirty? => false) }
173
+
174
+ it "prints a success message" do
175
+ subject.should_not_receive(:error)
176
+ subject.should_receive(:success).with("Git repo is clean")
177
+
178
+ subject.ensure_clean_git
179
+ end
180
+ end
181
+ end
182
+
183
+ describe Deployer, "#ensure_rake_passes" do
184
+ context "with a default task" do
185
+ before do
186
+ subject.stub(:default_task_exists? => true)
187
+ end
188
+
189
+ it "prints a success message if the default task succeeds" do
190
+ subject.stub(:rake_succeeded? => true)
191
+ subject.should_not_receive(:error)
192
+ subject.should_receive(:success).with("Rake passed")
193
+
194
+ subject.ensure_rake_passes
195
+ end
196
+
197
+ it "prints an error if the default task failse" do
198
+ subject.stub(:rake_succeeded? => false)
199
+ subject.should_receive(:error).with("Cannot deploy: tests did not pass")
200
+
201
+ subject.ensure_rake_passes
202
+ end
203
+ end
204
+ end
205
+
206
+ describe Deployer, "#default_task_exists?" do
207
+ it "returns true because a default task does exist" do
208
+ subject.default_task_exists?.should be_true
209
+ end
210
+ end
211
+
212
+ describe Deployer, "#rake_succeeded?" do
213
+ it "returns true if the default task passed" do
214
+ subject.should_receive(:system).with("bundle exec rake").and_return(true)
215
+
216
+ subject.rake_succeeded?.should be_true
217
+ end
218
+
219
+ it "returns false if the default task failed" do
220
+ subject.should_receive(:system).with("bundle exec rake").and_raise("blerg")
221
+ subject.rake_succeeded?.should be_false
222
+ end
223
+ end
224
+
225
+ describe Deployer, "#package_assets" do
226
+ context "with Jammit installed" do
227
+ it "calls package_with_jammit" do
228
+ subject.should_receive(:package_with_jammit)
229
+ subject.package_assets
230
+ end
231
+ end
232
+
233
+ context "with Jammit not installed" do
234
+ before { subject.stub(:jammit_installed? => false) }
235
+ it "does not call package_with_jammit" do
236
+ subject.should_not_receive(:package_with_jammit)
237
+ subject.package_assets
238
+ end
239
+ end
240
+
241
+ context "with More installed" do
242
+ before do
243
+ subject.stub(:jammit_installed? => false)
244
+ subject.stub(:more_installed? => true)
245
+ end
246
+
247
+ it "calls package_with_more" do
248
+ subject.should_receive(:package_with_more)
249
+ subject.package_assets
250
+ end
251
+ end
252
+
253
+ context "with More not installed" do
254
+ before do
255
+ subject.stub(:jammit_installed? => false)
256
+ subject.stub(:more_installed? => false)
257
+ end
258
+
259
+ it "does not call package_with_more" do
260
+ subject.should_not_receive(:package_with_more)
261
+ subject.package_assets
262
+ end
263
+ end
264
+ end
265
+
266
+ describe Deployer, "#package_with_jammit" do
267
+ before do
268
+ subject.stub(:git_add_and_commit_all_assets_in)
269
+ subject.stub(:say)
270
+ Jammit.stub(:package!)
271
+ end
272
+
273
+ it "calls Jammit.package!" do
274
+ Jammit.should_receive(:package!).once
275
+ subject.package_with_jammit
276
+ end
277
+
278
+ context "with updated assets" do
279
+ before { subject.stub(:git_dirty? => true) }
280
+
281
+ it "prints the correct message" do
282
+ subject.should_receive(:success).with("Packaged assets with Jammit")
283
+
284
+ subject.package_with_jammit
285
+ end
286
+
287
+ it "calls git_add_and_commit_all_assets_in" do
288
+ subject.stub(:jammit_assets_path => 'jammit-assets')
289
+ subject.should_receive(:git_add_and_commit_all_assets_in).
290
+ with('jammit-assets').
291
+ and_return(true)
292
+
293
+ subject.package_with_jammit
294
+ end
295
+ end
296
+
297
+ it "prints an error if packaging failed" do
298
+ Jammit.stub(:package!) do
299
+ raise Jammit::MissingConfiguration.new("random Jammit error")
300
+ end
301
+ subject.should_receive(:error).with("Error: Jammit::MissingConfiguration: random Jammit error")
302
+
303
+ subject.package_with_jammit
304
+ end
305
+
306
+ context "no assets were added" do
307
+ before { subject.stub(:git_dirty? => false) }
308
+
309
+ it "does not call git_add_and_commit_all_jammit_assets" do
310
+ subject.should_not_receive(:git_add_and_commit_all_assets_in)
311
+
312
+ subject.package_with_jammit
313
+ end
314
+
315
+ it "does not print a success message" do
316
+ subject.should_not_receive(:success)
317
+ subject.package_with_jammit
318
+ end
319
+ end
320
+ end
321
+
322
+ describe Deployer, "#package_with_more" do
323
+ before do
324
+ subject.stub(:git_add_and_commit_all_assets_in => true,
325
+ :more_assets_path => 'assets')
326
+ subject.stub(:say)
327
+ end
328
+
329
+ it "calls the more:generate task" do
330
+ subject.should_receive(:system).with("bundle exec rake more:generate")
331
+ subject.package_with_more
332
+ end
333
+
334
+ context "with changed assets" do
335
+ it "prints a success message" do
336
+ subject.stub(:system).with("bundle exec rake more:generate")
337
+ subject.stub(:git_dirty? => true)
338
+ subject.should_receive(:success).with("Packaged assets with More")
339
+
340
+ subject.package_with_more
341
+ end
342
+
343
+ it "calls git_add_and_commit_all_assets_in if assets were added" do
344
+ subject.stub(:git_dirty? => true,
345
+ :more_assets_path => 'blerg')
346
+ subject.stub(:system).with("bundle exec rake more:generate")
347
+ subject.should_receive(:git_add_and_commit_all_assets_in).
348
+ with('blerg').
349
+ and_return(true)
350
+
351
+ subject.package_with_more
352
+ end
353
+ end
354
+
355
+ context "with no changed assets" do
356
+ it "prints no message" do
357
+ subject.stub(:system).with("bundle exec rake more:generate")
358
+ subject.stub(:git_dirty? => false)
359
+ subject.should_not_receive(:say)
360
+
361
+ subject.package_with_more
362
+ end
363
+
364
+ it "does not call git_add_and_commit_all_more_assets" do
365
+ subject.stub(:system).with("bundle exec rake more:generate")
366
+ subject.stub(:git_dirty? => false)
367
+ subject.should_not_receive(:git_add_and_commit_all_assets_in)
368
+
369
+ subject.package_with_more
370
+ end
371
+ end
372
+
373
+ it "prints an error if packaging failed" do
374
+ subject.stub(:system) do |arg|
375
+ if arg == "bundle exec rake more:generate"
376
+ raise "blerg"
377
+ end
378
+ end
379
+
380
+ subject.should_receive(:error).with("Error: RuntimeError: blerg")
381
+
382
+ subject.package_with_more
383
+ end
384
+ end
385
+
386
+ describe Deployer, "#git_add_and_commit_all_assets_in" do
387
+ before do
388
+ subject.stub(:run => true)
389
+ subject.stub(:say)
390
+ end
391
+
392
+ it "prints a success message" do
393
+ subject.should_receive(:success).with("Added and committed all assets")
394
+
395
+ subject.git_add_and_commit_all_assets_in('blerg')
396
+ end
397
+
398
+ it "runs the correct commands" do
399
+ subject.should_receive(:run).
400
+ with("git add blerg && git commit -m 'Assets'")
401
+
402
+ subject.git_add_and_commit_all_assets_in('blerg')
403
+ end
404
+
405
+ it "prints an error if it could not add and commit assets" do
406
+ subject.stub(:run => false)
407
+ subject.should_receive(:error).with("Cannot deploy: couldn't commit assets")
408
+
409
+ subject.git_add_and_commit_all_assets_in('blerg')
410
+ end
411
+ end
412
+
413
+ describe Deployer, "#jammit_assets_path" do
414
+ it "returns the correct asset path" do
415
+ Jammit.stub(:package_path => 'blerg')
416
+ current_dir = File.expand_path(Dir.pwd)
417
+ subject.jammit_assets_path.should == File.join(current_dir, 'public', 'blerg')
418
+ end
419
+ end
420
+
421
+ describe Deployer, "#more_assets_path" do
422
+ it "returns the correct asset path" do
423
+ module ::Less
424
+ class More
425
+ def self.destination_path
426
+ 'blerg'
427
+ end
428
+ end
429
+ end
430
+ subject.more_assets_path.should == 'public/blerg'
431
+ end
432
+ end
433
+
434
+ describe Deployer, "#jammit_installed?" do
435
+ it "returns true because it's loaded by the Gemfile" do
436
+ subject.jammit_installed?.should be_true
437
+ end
438
+ end
439
+
440
+ describe Deployer, "#more_installed?" do
441
+ before do
442
+ if defined?(Less)
443
+ Object.send(:remove_const, :Less)
444
+ end
445
+ end
446
+
447
+ it "returns false if it does not find Less::More" do
448
+ subject.more_installed?.should be_false
449
+ end
450
+
451
+ it "returns true if it finds Less::More" do
452
+ module Less
453
+ class More
454
+ end
455
+ end
456
+ subject.more_installed?.should be_true
457
+ end
458
+ end
459
+
460
+ describe Deployer, "#heroku_migrate" do
461
+ let(:environment){ 'staging' }
462
+ let(:app_name){ 'sushi' }
463
+
464
+ before do
465
+ subject.stub(:say)
466
+ force_add_heroku_remote(environment, app_name)
467
+ end
468
+
469
+ after { remove_remote(environment) }
470
+
471
+ it "runs db:migrate with the correct app" do
472
+ subject.should_receive(:run).
473
+ with("bundle exec heroku rake db:migrate --app #{app_name}")
474
+ subject.should_receive(:success).with("Migrated #{app_name}")
475
+
476
+ subject.heroku_migrate(environment)
477
+ end
478
+ end
479
+
480
+ describe Deployer, "#string_present?" do
481
+ it "returns false for nil" do
482
+ subject.string_present?(nil).should be_false
483
+ end
484
+
485
+ it "returns false for false" do
486
+ subject.string_present?(false).should be_false
487
+ end
488
+
489
+ it "returns false for true" do
490
+ subject.string_present?(true).should be_false
491
+ end
492
+
493
+ it "returns false for an empty string" do
494
+ subject.string_present?('').should be_false
495
+ end
496
+
497
+ it "returns true for a non-empty string" do
498
+ subject.string_present?('abc').should be_true
499
+ end
500
+ end
501
+
502
+ describe Deployer, "#ensure_heroku_remote_exists_for" do
503
+ let(:environment){ 'staging' }
504
+ let(:bad_environment){ 'bad' }
505
+ let(:staging_app_name) { 'staging-sushi' }
506
+
507
+ before do
508
+ subject.stub(:say)
509
+ force_add_heroku_remote(environment, staging_app_name)
510
+ `git remote add #{bad_environment} blerg@example.com`
511
+ end
512
+
513
+ after do
514
+ remove_remote(environment)
515
+ remove_remote(bad_environment)
516
+ end
517
+
518
+ context "when the remote points to Heroku" do
519
+ it "does not print an error" do
520
+ subject.should_not_receive(:error)
521
+
522
+ subject.ensure_heroku_remote_exists_for(environment)
523
+ end
524
+
525
+ it "prints a success message" do
526
+ subject.should_receive(:success).with("#{environment} is a Heroku remote")
527
+
528
+ subject.ensure_heroku_remote_exists_for(environment)
529
+ end
530
+ end
531
+
532
+
533
+ context "when the remote does not exist" do
534
+ before { remove_remote(environment) }
535
+
536
+ it "prints an error" do
537
+ subject.should_receive(:error).with(%{Cannot deploy: "#{environment}" remote does not exist})
538
+
539
+ subject.ensure_heroku_remote_exists_for(environment)
540
+ end
541
+ end
542
+
543
+ context "when the remote does not point to Heroku" do
544
+ it "prints an error" do
545
+ subject.should_receive(:error).with(%{Cannot deploy: "#{bad_environment}" remote does not point to Heroku})
546
+
547
+ subject.ensure_heroku_remote_exists_for(bad_environment)
548
+ end
549
+ end
550
+ end
551
+
552
+ describe Deployer, "#remote_exists?" do
553
+ let(:remote_name){ 'staging' }
554
+
555
+ before { force_add_heroku_remote(remote_name, 'i-am-a-heroku-app') }
556
+ after { remove_remote(remote_name) }
557
+
558
+ it "returns true if the remote exists" do
559
+ subject.remote_exists?(remote_name).should be_true
560
+ end
561
+
562
+ it "returns false if the remote does not exist" do
563
+ remove_remote(remote_name)
564
+
565
+ subject.remote_exists?(remote_name).should be_false
566
+ end
567
+ end
568
+
569
+ describe Deployer, "#announce" do
570
+ it "exists" do
571
+ subject.should respond_to(:announce)
572
+ end
573
+ end
574
+
575
+ describe Deployer, "#success" do
576
+ it "exists" do
577
+ subject.should respond_to(:success)
578
+ end
579
+ end
580
+
581
+ describe Deployer, "#error" do
582
+ it "exists" do
583
+ subject.should respond_to(:error)
584
+ end
585
+ end
586
+ end