kumade 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. data/README.md +9 -1
  2. data/features/kumade_executable.feature +11 -12
  3. data/features/kumade_without_jammit.feature +2 -2
  4. data/kumade.gemspec +1 -0
  5. data/lib/kumade.rb +7 -1
  6. data/lib/kumade/cli.rb +4 -4
  7. data/lib/kumade/command_line.rb +33 -0
  8. data/lib/kumade/configuration.rb +13 -6
  9. data/lib/kumade/deployer.rb +9 -9
  10. data/lib/kumade/git.rb +25 -20
  11. data/lib/kumade/heroku.rb +18 -11
  12. data/lib/kumade/outputter.rb +21 -0
  13. data/lib/kumade/packager.rb +23 -76
  14. data/lib/kumade/packager_list.rb +29 -0
  15. data/lib/kumade/packagers/jammit_packager.rb +20 -0
  16. data/lib/kumade/packagers/more_packager.rb +20 -0
  17. data/lib/kumade/packagers/noop_packager.rb +14 -0
  18. data/lib/kumade/rake_task_runner.rb +29 -0
  19. data/lib/kumade/version.rb +1 -1
  20. data/spec/kumade/cli_spec.rb +5 -5
  21. data/spec/kumade/command_line_spec.rb +107 -0
  22. data/spec/kumade/configuration_spec.rb +15 -2
  23. data/spec/kumade/deployer_spec.rb +39 -25
  24. data/spec/kumade/git_spec.rb +168 -57
  25. data/spec/kumade/heroku_spec.rb +19 -25
  26. data/spec/kumade/outputter_spec.rb +50 -0
  27. data/spec/kumade/packager_list_spec.rb +31 -0
  28. data/spec/kumade/packager_spec.rb +66 -275
  29. data/spec/kumade/packagers/jammit_packager_spec.rb +27 -0
  30. data/spec/kumade/packagers/more_packager_spec.rb +37 -0
  31. data/spec/kumade/packagers/noop_packager_spec.rb +9 -0
  32. data/spec/kumade/rake_task_runner_spec.rb +75 -0
  33. data/spec/spec_helper.rb +13 -2
  34. data/spec/support/define_constant.rb +41 -0
  35. data/spec/support/environments.rb +32 -0
  36. data/spec/support/git.rb +5 -0
  37. data/spec/support/heroku.rb +6 -6
  38. data/spec/support/shared_examples/packager.rb +6 -0
  39. metadata +65 -28
  40. data/lib/kumade/base.rb +0 -35
  41. data/spec/kumade/base_spec.rb +0 -99
data/README.md CHANGED
@@ -85,6 +85,14 @@ You can hook in any custom code you want to run there before deploying!
85
85
  Kumade ([pronunciation here](http://translate.google.com/#ja|en|熊手)) means
86
86
  "bamboo rake" in Japanese.
87
87
 
88
+ ## Credits
89
+
90
+ ![thoughtbot](http://thoughtbot.com/images/tm/logo.png)
91
+
92
+ Kumade is maintained and funded by [thoughtbot, inc](http://thoughtbot.com/community)
93
+
94
+ The names and logos for thoughtbot are trademarks of thoughtbot, inc.
95
+
88
96
  ## License
89
97
 
90
- kumade is Copyright © thoughtbot. It is free software, and may be redistributed under the terms specified in the LICENSE file.
98
+ Kumade is Copyright © 2011 thoughtbot. It is free software, and may be redistributed under the terms specified in the LICENSE file.
@@ -21,17 +21,16 @@ Feature: Kumade executable
21
21
  And the output should contain:
22
22
  """
23
23
  ==> Git repo is clean
24
- ==> Packaged assets with Jammit
25
- run git push origin master
24
+ ==> Packaged with Kumade::JammitPackager
25
+ git push origin master
26
26
  ==> Pushed master -> origin
27
- run git branch deploy
28
- run git push -f pretend-staging deploy:master
27
+ git branch deploy >/dev/null
28
+ git push -f pretend-staging deploy:master
29
29
  ==> Pushed deploy:master -> pretend-staging
30
30
  ==> Migrated pretend-staging
31
- run git checkout master && git branch -D deploy
32
31
  ==> Deployed to: pretend-staging
33
32
  """
34
- But the output should not contain "==> Packaged assets with More"
33
+ But the output should not contain "==> Packaged with Kumade::MorePackager"
35
34
 
36
35
  Scenario: Default environment is staging
37
36
  When I run kumade with "-p"
@@ -52,14 +51,13 @@ Feature: Kumade executable
52
51
  Then the output should contain:
53
52
  """
54
53
  ==> Git repo is clean
55
- ==> Packaged assets with Jammit
56
- run git push origin new_branch
54
+ ==> Packaged with Kumade::JammitPackager
55
+ git push origin new_branch
57
56
  ==> Pushed new_branch -> origin
58
- run git branch deploy
59
- run git push -f pretend-staging deploy:master
57
+ git branch deploy >/dev/null
58
+ git push -f pretend-staging deploy:master
60
59
  ==> Pushed deploy:master -> pretend-staging
61
60
  ==> Migrated pretend-staging
62
- run git checkout new_branch && git branch -D deploy
63
61
  ==> Deployed to: pretend-staging
64
62
  """
65
63
 
@@ -95,4 +93,5 @@ Feature: Kumade executable
95
93
  end
96
94
  """
97
95
  When I run kumade with "pretend-staging -p"
98
- Then the output should match /kumade:before_asset_compilation.*Packaged assets with Jammit/
96
+ Then the output should contain "kumade:before_asset_compilation"
97
+ And the output should contain "==> Packaged with Kumade::JammitPackager"
@@ -23,7 +23,7 @@ Feature: Kumade without jammit
23
23
  end
24
24
  """
25
25
  When I run kumade with "pretend-staging"
26
- Then the output should contain "Running kumade:before_asset_compilation task"
26
+ Then the output should contain "Running rake task: kumade:before_asset_compilation"
27
27
  And the output should contain "Hi!"
28
28
 
29
29
  Scenario: Don't run rake task in pretend mode
@@ -36,5 +36,5 @@ Feature: Kumade without jammit
36
36
  end
37
37
  """
38
38
  When I run kumade with "pretend-staging -p"
39
- Then the output should contain "Running kumade:before_asset_compilation task"
39
+ Then the output should contain "Running rake task: kumade:before_asset_compilation"
40
40
  And the output should not contain "Hi!"
@@ -26,5 +26,6 @@ Gem::Specification.new do |s|
26
26
  s.add_development_dependency('cucumber', '~> 1.0.2')
27
27
  s.add_development_dependency('aruba', '~> 0.4.3')
28
28
  s.add_development_dependency('jammit', '~> 0.6.3')
29
+ s.add_development_dependency('less', '~> 2.0')
29
30
  s.add_development_dependency('bourne')
30
31
  end
@@ -1,5 +1,4 @@
1
1
  module Kumade
2
- autoload :Base, "kumade/base"
3
2
  autoload :Git, "kumade/git"
4
3
  autoload :Deployer, "kumade/deployer"
5
4
  autoload :CLI, "kumade/cli"
@@ -8,6 +7,13 @@ module Kumade
8
7
  autoload :Configuration, "kumade/configuration"
9
8
  autoload :Heroku, "kumade/heroku"
10
9
  autoload :Packager, "kumade/packager"
10
+ autoload :MorePackager, "kumade/packagers/more_packager"
11
+ autoload :JammitPackager, "kumade/packagers/jammit_packager"
12
+ autoload :NoopPackager, "kumade/packagers/noop_packager"
13
+ autoload :PackagerList, "kumade/packager_list"
14
+ autoload :RakeTaskRunner, "kumade/rake_task_runner"
15
+ autoload :CommandLine, "kumade/command_line"
16
+ autoload :Outputter, "kumade/outputter"
11
17
 
12
18
  def self.configuration
13
19
  @@configuration ||= Configuration.new
@@ -16,7 +16,7 @@ module Kumade
16
16
  parse_arguments!(args)
17
17
 
18
18
  Kumade.configuration.pretending = !!@options[:pretend]
19
- Kumade.configuration.environment = args.shift || 'staging'
19
+ Kumade.configuration.environment = args.shift
20
20
 
21
21
  self.class.swapping_stdout_for(out, print_output?) do
22
22
  deploy
@@ -44,11 +44,11 @@ module Kumade
44
44
 
45
45
  def deploy
46
46
  if Kumade.configuration.pretending?
47
- puts "==> In Pretend Mode"
47
+ Kumade.configuration.outputter.info("In Pretend Mode")
48
48
  end
49
- puts "==> Deploying to: #{Kumade.configuration.environment}"
49
+ Kumade.configuration.outputter.info("Deploying to: #{Kumade.configuration.environment}")
50
50
  self.class.deployer.new.deploy
51
- puts "==> Deployed to: #{Kumade.configuration.environment}"
51
+ Kumade.configuration.outputter.info("Deployed to: #{Kumade.configuration.environment}")
52
52
  end
53
53
 
54
54
  def parse_arguments!(args)
@@ -0,0 +1,33 @@
1
+ require 'cocaine'
2
+
3
+ module Kumade
4
+ class CommandLine
5
+ def initialize(command_to_run)
6
+ @command_line = Cocaine::CommandLine.new(command_to_run)
7
+ end
8
+
9
+ def run_or_error(error_message = nil)
10
+ run_with_status || Kumade.configuration.outputter.error(error_message)
11
+ end
12
+
13
+ def run_with_status
14
+ Kumade.configuration.outputter.say_command(command)
15
+ Kumade.configuration.pretending? || run
16
+ end
17
+
18
+ def run
19
+ begin
20
+ @command_line.run
21
+ true
22
+ rescue Cocaine::ExitStatusError, Cocaine::CommandNotFoundError
23
+ false
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def command
30
+ @command_line.command
31
+ end
32
+ end
33
+ end
@@ -1,14 +1,21 @@
1
1
  module Kumade
2
2
  class Configuration
3
- def initialize(environment = 'staging', pretending = false )
4
- @environment = environment
5
- @pretending = pretending
6
- end
3
+ attr_writer :pretending, :environment
7
4
 
8
5
  def pretending?
9
- @pretending
6
+ @pretending || false
7
+ end
8
+
9
+ def environment
10
+ @environment || "staging"
10
11
  end
11
12
 
12
- attr_accessor :pretending, :environment
13
+ def outputter
14
+ @outputter ||= Outputter.new
15
+ end
16
+
17
+ def outputter=(new_outputter)
18
+ @outputter = new_outputter
19
+ end
13
20
  end
14
21
  end
@@ -2,11 +2,10 @@ require "rake"
2
2
  require 'cocaine'
3
3
 
4
4
  module Kumade
5
- class Deployer < Base
5
+ class Deployer
6
6
  attr_reader :git, :heroku, :packager
7
7
 
8
8
  def initialize
9
- super()
10
9
  @git = Git.new
11
10
  @heroku = Heroku.new
12
11
  @branch = @git.current_branch
@@ -19,7 +18,8 @@ module Kumade
19
18
  pre_deploy
20
19
  heroku.sync
21
20
  heroku.migrate_database
22
- rescue
21
+ rescue => deploying_error
22
+ Kumade.configuration.outputter.error("#{deploying_error.class}: #{deploying_error.message}")
23
23
  ensure
24
24
  post_deploy
25
25
  end
@@ -28,14 +28,14 @@ module Kumade
28
28
  def pre_deploy
29
29
  ensure_clean_git
30
30
  package_assets
31
- sync_github
31
+ sync_origin
32
32
  end
33
33
 
34
34
  def package_assets
35
- packager.run
35
+ @packager.run
36
36
  end
37
37
 
38
- def sync_github
38
+ def sync_origin
39
39
  git.push(@branch)
40
40
  end
41
41
 
@@ -50,12 +50,12 @@ module Kumade
50
50
  def ensure_heroku_remote_exists
51
51
  if git.remote_exists?(Kumade.configuration.environment)
52
52
  if git.heroku_remote?
53
- success("#{Kumade.configuration.environment} is a Heroku remote")
53
+ Kumade.configuration.outputter.success("#{Kumade.configuration.environment} is a Heroku remote")
54
54
  else
55
- error(%{Cannot deploy: "#{Kumade.configuration.environment}" remote does not point to Heroku})
55
+ Kumade.configuration.outputter.error(%{Cannot deploy: "#{Kumade.configuration.environment}" remote does not point to Heroku})
56
56
  end
57
57
  else
58
- error(%{Cannot deploy: "#{Kumade.configuration.environment}" remote does not exist})
58
+ Kumade.configuration.outputter.error(%{Cannot deploy: "#{Kumade.configuration.environment}" remote does not exist})
59
59
  end
60
60
  end
61
61
  end
@@ -1,10 +1,6 @@
1
1
  require 'cocaine'
2
2
  module Kumade
3
- class Git < Base
4
- def initialize
5
- super()
6
- end
7
-
3
+ class Git
8
4
  def heroku_remote?
9
5
  remote_url = `git config --get remote.#{Kumade.configuration.environment}.url`.strip
10
6
  !! remote_url.strip.match(/^git@heroku\..+:(.+)\.git$/)
@@ -20,25 +16,32 @@ module Kumade
20
16
  command << remote
21
17
  command << branch
22
18
  command = command.join(" ")
23
- run_or_error(command, "Failed to push #{branch} -> #{remote}")
24
- success("Pushed #{branch} -> #{remote}")
19
+
20
+ command_line = CommandLine.new(command)
21
+ command_line.run_or_error("Failed to push #{branch} -> #{remote}")
22
+ Kumade.configuration.outputter.success("Pushed #{branch} -> #{remote}")
25
23
  end
26
24
 
27
25
  def create(branch)
28
- unless branch_exist?(branch)
29
- run_or_error("git branch #{branch}", "Failed to create #{branch}")
26
+ unless has_branch?(branch)
27
+ CommandLine.new("git branch #{branch} >/dev/null").run_or_error("Failed to create #{branch}")
30
28
  end
31
29
  end
32
30
 
33
31
  def delete(branch_to_delete, branch_to_checkout)
34
- run_or_error("git checkout #{branch_to_checkout} && git branch -D #{branch_to_delete}",
35
- "Failed to clean up #{branch_to_delete} branch")
32
+ if has_branch?(branch_to_delete)
33
+ command_line = CommandLine.new("git checkout #{branch_to_checkout} 2>/dev/null && git branch -D #{branch_to_delete}")
34
+ command_line.run_or_error("Failed to clean up #{branch_to_delete} branch")
35
+ end
36
36
  end
37
37
 
38
- def add_and_commit_all_in(dir, branch, commit_message, success_output, error_output)
39
- run_or_error "git checkout -b #{branch} && git add -f #{dir} && git commit -m '#{commit_message}'",
40
- "Cannot deploy: #{error_output}"
41
- success success_output
38
+ def add_and_commit_all_assets_in(dir)
39
+ command = ["git checkout -b #{Kumade::Heroku::DEPLOY_BRANCH} 2>/dev/null",
40
+ "git add -f #{dir}",
41
+ "git commit -m 'Compiled assets.'"].join(' && ')
42
+ command_line = CommandLine.new(command)
43
+ command_line.run_or_error("Cannot deploy: couldn't commit assets")
44
+ Kumade.configuration.outputter.success("Added and committed all assets")
42
45
  end
43
46
 
44
47
  def current_branch
@@ -54,19 +57,21 @@ module Kumade
54
57
  end
55
58
 
56
59
  def dirty?
57
- !run("git diff --exit-code")
60
+ ! CommandLine.new("git diff --exit-code").run
58
61
  end
59
62
 
60
63
  def ensure_clean_git
61
64
  if ! Kumade.configuration.pretending? && dirty?
62
- error("Cannot deploy: repo is not clean.")
65
+ Kumade.configuration.outputter.error("Cannot deploy: repo is not clean.")
63
66
  else
64
- success("Git repo is clean")
67
+ Kumade.configuration.outputter.success("Git repo is clean")
65
68
  end
66
69
  end
67
70
 
68
- def branch_exist?(branch)
69
- run("git show-ref #{branch}")
71
+ private
72
+
73
+ def has_branch?(branch)
74
+ CommandLine.new("git show-ref #{branch}").run
70
75
  end
71
76
  end
72
77
  end
@@ -1,12 +1,11 @@
1
1
  require 'cocaine'
2
2
 
3
3
  module Kumade
4
- class Heroku < Base
4
+ class Heroku
5
5
  DEPLOY_BRANCH = "deploy"
6
6
  attr_reader :git
7
7
 
8
8
  def initialize
9
- super()
10
9
  @git = Git.new
11
10
  @branch = @git.current_branch
12
11
  end
@@ -18,7 +17,7 @@ module Kumade
18
17
 
19
18
  def migrate_database
20
19
  heroku("rake db:migrate") unless Kumade.configuration.pretending?
21
- success("Migrated #{Kumade.configuration.environment}")
20
+ Kumade.configuration.outputter.success("Migrated #{Kumade.configuration.environment}")
22
21
  end
23
22
 
24
23
  def delete_deploy_branch
@@ -26,21 +25,29 @@ module Kumade
26
25
  end
27
26
 
28
27
  def heroku(command)
29
- heroku_command = if cedar?
30
- "bundle exec heroku run"
31
- else
32
- "bundle exec heroku"
33
- end
34
- run_or_error("#{heroku_command} #{command} --remote #{Kumade.configuration.environment}",
35
- "Failed to run #{command} on Heroku")
28
+ full_heroku_command = "#{bundle_exec_heroku} #{command} --remote #{Kumade.configuration.environment}"
29
+ command_line = CommandLine.new(full_heroku_command)
30
+ command_line.run_or_error("Failed to run #{command} on Heroku")
36
31
  end
37
32
 
38
33
  def cedar?
39
34
  return @cedar unless @cedar.nil?
40
35
 
41
- @cedar = Cocaine::CommandLine.new("bundle exec heroku stack --remote #{Kumade.configuration.environment}").run.split("\n").grep(/\*/).any? do |line|
36
+ command_line = CommandLine.new("bundle exec heroku stack --remote #{Kumade.configuration.environment}")
37
+
38
+ @cedar = command_line.run_or_error.split("\n").grep(/\*/).any? do |line|
42
39
  line.include?("cedar")
43
40
  end
44
41
  end
42
+
43
+ private
44
+
45
+ def bundle_exec_heroku
46
+ if cedar?
47
+ "bundle exec heroku run"
48
+ else
49
+ "bundle exec heroku"
50
+ end
51
+ end
45
52
  end
46
53
  end
@@ -0,0 +1,21 @@
1
+ module Kumade
2
+ class Outputter
3
+ def success(message)
4
+ puts "==> #{message}"
5
+ end
6
+
7
+ def info(message)
8
+ puts "==> #{message}"
9
+ end
10
+
11
+ def error(message)
12
+ puts "==> ! #{message}"
13
+ raise Kumade::DeploymentError, message
14
+ end
15
+
16
+ def say_command(command)
17
+ prefix = " " * 8
18
+ puts "#{prefix}#{command}"
19
+ end
20
+ end
21
+ end
@@ -1,94 +1,41 @@
1
1
  module Kumade
2
- class Packager < Base
3
- attr_reader :git
4
-
5
- def initialize(git)
6
- super()
7
- @git = git
2
+ class Packager
3
+ def initialize(git, packager = Packager.available_packager)
4
+ @packager = packager
5
+ @git = git
8
6
  end
9
7
 
10
8
  def run
11
- invoke_custom_task if custom_task?
12
- package_with_jammit if jammit_installed?
13
- package_with_more if more_installed?
14
- end
15
-
16
- def invoke_custom_task
17
- success "Running kumade:before_asset_compilation task"
18
- Rake::Task["kumade:before_asset_compilation"].invoke unless Kumade.configuration.pretending?
9
+ precompile_assets
10
+ package
19
11
  end
20
12
 
21
- def custom_task?
22
- load("Rakefile") if File.exist?("Rakefile")
23
- Rake::Task.task_defined?("kumade:before_asset_compilation")
13
+ def self.available_packager
14
+ Kumade::PackagerList.new.first
24
15
  end
25
16
 
26
- def package_with_jammit
27
- begin
28
- success_message = "Packaged assets with Jammit"
29
-
30
- if Kumade.configuration.pretending?
31
- success(success_message)
32
- else
33
- Jammit.package!
17
+ private
34
18
 
35
- success(success_message)
36
- git_add_and_commit_all_assets_in(jammit_assets_path)
37
- end
38
- rescue => jammit_error
39
- error("Error: #{jammit_error.class}: #{jammit_error.message}")
40
- end
19
+ def precompile_assets
20
+ RakeTaskRunner.new("kumade:before_asset_compilation").invoke
41
21
  end
42
22
 
43
- def package_with_more
44
- success_message = "Packaged assets with More"
45
- if Kumade.configuration.pretending?
46
- success(success_message)
47
- else
48
- begin
49
- run "bundle exec rake more:generate"
50
- if git.dirty?
51
- success(success_message)
52
- git_add_and_commit_all_assets_in(more_assets_path)
53
- end
54
- rescue => more_error
55
- error("Error: #{more_error.class}: #{more_error.message}")
23
+ def package
24
+ return Kumade.configuration.outputter.success(success_message) if Kumade.configuration.pretending?
25
+
26
+ begin
27
+ @packager.package
28
+ if @git.dirty?
29
+ @git.add_and_commit_all_assets_in(@packager.assets_path)
30
+ Kumade.configuration.outputter.success(success_message)
56
31
  end
32
+ rescue => packager_exception
33
+ Kumade.configuration.outputter.error("Error: #{packager_exception.class}: #{packager_exception.message}")
57
34
  end
58
35
  end
59
36
 
60
- def git_add_and_commit_all_assets_in(dir)
61
- git.add_and_commit_all_in(dir, Kumade::Heroku::DEPLOY_BRANCH, 'Compiled assets', "Added and committed all assets", "couldn't commit assets")
62
- end
63
-
64
- def jammit_assets_path
65
- File.join(Jammit::PUBLIC_ROOT, Jammit.package_path)
66
- end
67
-
68
- def more_assets_path
69
- File.join('public', ::Less::More.destination_path)
70
- end
71
-
72
- def jammit_installed?
73
- @jammit_installed ||=
74
- (defined?(Jammit) ||
75
- begin
76
- require 'jammit'
77
- true
78
- rescue LoadError
79
- false
80
- end)
81
- end
82
-
83
- def more_installed?
84
- @more_installed ||=
85
- (defined?(Less::More) ||
86
- begin
87
- require 'less/more'
88
- true
89
- rescue LoadError
90
- false
91
- end)
37
+ def success_message
38
+ "Packaged with #{@packager.name}"
92
39
  end
93
40
  end
94
41
  end