kumade 0.0.2 → 0.0.3

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.
@@ -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