kumade 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,7 +2,6 @@ rvm:
2
2
  - 1.9.2
3
3
  - 1.8.7
4
4
  - ree-1.8.7
5
- - 1.8.7-p249
6
5
  # branches:
7
6
  # only:
8
7
  # - master
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # Kumade 熊手 [![Build Status](https://secure.travis-ci.org/thoughtbot/kumade.png)](http://travis-ci.org/thoughtbot/kumade)
2
- Kumade is a set of basic Rake tasks for deploying to Heroku. It aims to
2
+ Kumade is a command-line program for deploying to Heroku. It aims to
3
3
  provide most of what you want. Unlike other Heroku deploy gems, it is
4
4
  well-tested.
5
5
 
@@ -9,11 +9,11 @@ public API is constant (e.g. `kumade production` will work), but you may have to
9
9
  rebase against master a couple times before your pull request can be merged.
10
10
 
11
11
  ## What does Kumade do?
12
- Before deploying, Kumade ensures the git repo is clean and that all tests pass.
12
+ Before deploying, Kumade ensures the git repo is clean.
13
13
  After that, it packages assets using
14
14
  [Jammit](http://documentcloud.github.com/jammit/) and/or
15
15
  [More](https://github.com/cloudhead/more), commits them, and pushes to origin.
16
- Then it force pushes to the correct remote and runs `rake db:migrate` on the
16
+ Then it force pushes to the correct Heroku remote and runs `rake db:migrate` on the
17
17
  Heroku app.
18
18
 
19
19
  If any step fails, it immediately prints an error and stops the deploy
@@ -29,36 +29,34 @@ gem 'kumade'
29
29
  ## Usage
30
30
 
31
31
  kumade will deploy to any Heroku remote in the repo.
32
- For example, if you have a remote named "bamboo":
32
+ For example, if you have a remote named "staging":
33
33
 
34
- $ bundle exec kumade bamboo
34
+ $ bundle exec kumade staging
35
35
 
36
- or
36
+ To run in pretend mode, which prints what would be done without actually doing
37
+ any of it:
37
38
 
38
- # in your Rakefile:
39
- require 'kumade'
39
+ $ bundle exec kumade staging -p
40
40
 
41
- # kumade auto-generates a deploy:ENV task for every Heroku environment
42
- $ rake deploy:bamboo
41
+ The default is to deploy to staging:
43
42
 
44
- which will autodetect the name of the Heroku app that the bamboo remote points
45
- to and deploy to it.
43
+ # equivalent to "bundle exec kumade staging"
44
+ $ bundle exec kumade
46
45
 
47
- To run in pretend mode, which prints what would be done without actually doing
48
- any of it:
46
+ ## Rake
49
47
 
50
- $ bundle exec kumade bamboo -p
48
+ Kumade auto-generates a deploy:ENV task for every Heroku environment.
51
49
 
52
- The default is to deploy to staging:
50
+ # in your Rakefile:
51
+ require 'kumade'
53
52
 
54
- $ bundle exec kumade # equivalent to "bundle exec kumade staging"
53
+ $ rake deploy:staging
55
54
 
55
+ If you use rake tasks, you can't pass in options (like -p/--pretend).
56
56
 
57
57
  ## Does it support the Cedar stack?
58
58
 
59
- Yes. To indicate that a particular app is using Cedar, run with the -c flag:
60
-
61
- bundle exec kumade bamboo -c
59
+ Yes. Kumade will automatically detect if your app is running on Cedar.
62
60
 
63
61
  ## Compatibility
64
62
 
@@ -68,7 +66,7 @@ Tested against:
68
66
  * MRI 1.9.2
69
67
  * REE 1.8.7
70
68
 
71
- ## Misc Features
69
+ ## Miscellaneous Features
72
70
 
73
71
  Want to run a task before bundling your assets on deploy? In your Rails app's rake tasks, drop in:
74
72
 
data/bin/kumade CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  require 'kumade'
4
4
 
5
- Kumade::Runner.run
5
+ Kumade::CLI.new
@@ -19,10 +19,12 @@ Gem::Specification.new do |s|
19
19
  s.add_dependency('heroku', '~> 2.0')
20
20
  s.add_dependency('thor', '~> 0.14')
21
21
  s.add_dependency('rake', '>= 0.8.7')
22
+ s.add_dependency('cocaine', '>= 0.2.0')
22
23
 
23
24
  s.add_development_dependency('rake', '>= 0.8.7')
24
25
  s.add_development_dependency('rspec', '~> 2.6.0')
25
26
  s.add_development_dependency('cucumber', '~> 1.0.2')
26
27
  s.add_development_dependency('aruba', '~> 0.4.3')
27
28
  s.add_development_dependency('jammit', '~> 0.6.3')
29
+ s.add_development_dependency('bourne')
28
30
  end
@@ -1,13 +1,19 @@
1
- require 'rake'
2
- require 'thor'
3
- require 'stringio'
1
+ module Kumade
2
+ autoload :Base, "kumade/base"
3
+ autoload :Git, "kumade/git"
4
+ autoload :Deployer, "kumade/deployer"
5
+ autoload :CLI, "kumade/cli"
6
+ autoload :Railtie, "kumade/railtie"
7
+ autoload :DeploymentError, "kumade/deployment_error"
8
+ autoload :Configuration, "kumade/configuration"
9
+ autoload :Heroku, "kumade/heroku"
10
+ autoload :Packager, "kumade/packager"
4
11
 
5
- require 'kumade/base'
6
- require 'kumade/git'
7
- require 'kumade/deployer'
8
- require 'kumade/runner'
9
- require 'kumade/railtie'
10
- require 'kumade/deployment_error'
12
+ def self.configuration
13
+ @@configuration ||= Configuration.new
14
+ end
11
15
 
12
- module Kumade
16
+ def self.configuration=(new_configuration)
17
+ @@configuration = new_configuration
18
+ end
13
19
  end
@@ -1,21 +1,26 @@
1
+ require "thor"
2
+
1
3
  module Kumade
2
4
  class Base < Thor::Shell::Color
3
5
  def initialize
4
6
  super()
5
7
  end
6
8
 
7
- def run_or_error(commands, error_message)
8
- all_commands = [commands].flatten.join(' && ')
9
- if @pretending
10
- say_status(:run, all_commands)
11
- else
12
- error(error_message) unless run(all_commands)
9
+ def run_or_error(command, error_message)
10
+ say_status(:run, command)
11
+ if ! Kumade.configuration.pretending?
12
+ error(error_message) unless run(command)
13
13
  end
14
14
  end
15
15
 
16
- def run(command, config = {})
17
- say_status :run, command
18
- config[:capture] ? `#{command}` : system("#{command}")
16
+ def run(command)
17
+ line = Cocaine::CommandLine.new(command)
18
+ begin
19
+ line.run
20
+ true
21
+ rescue Cocaine::ExitStatusError => e
22
+ false
23
+ end
19
24
  end
20
25
 
21
26
  def error(message)
@@ -0,0 +1,86 @@
1
+ require 'optparse'
2
+ require 'stringio'
3
+
4
+ module Kumade
5
+ class CLI
6
+ class << self
7
+ attr_writer :deployer
8
+
9
+ def deployer
10
+ @deployer || Kumade::Deployer
11
+ end
12
+ end
13
+
14
+ def initialize(args = ARGV, out = StringIO.new)
15
+ @options = {}
16
+ parse_arguments!(args)
17
+
18
+ Kumade.configuration.pretending = !!@options[:pretend]
19
+ Kumade.configuration.environment = args.shift || 'staging'
20
+
21
+ self.class.swapping_stdout_for(out, print_output?) do
22
+ deploy
23
+ end
24
+ end
25
+
26
+ def self.swapping_stdout_for(io, print_output = false)
27
+ if print_output
28
+ yield
29
+ else
30
+ begin
31
+ real_stdout = $stdout
32
+ $stdout = io
33
+ yield
34
+ rescue Kumade::DeploymentError
35
+ io.rewind
36
+ real_stdout.print(io.read)
37
+ ensure
38
+ $stdout = real_stdout
39
+ end
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def deploy
46
+ if Kumade.configuration.pretending?
47
+ puts "==> In Pretend Mode"
48
+ end
49
+ puts "==> Deploying to: #{Kumade.configuration.environment}"
50
+ self.class.deployer.new.deploy
51
+ puts "==> Deployed to: #{Kumade.configuration.environment}"
52
+ end
53
+
54
+ def parse_arguments!(args)
55
+ OptionParser.new do |opts|
56
+ opts.banner = "Usage: kumade <environment> [options]"
57
+
58
+ opts.on("-p", "--pretend", "Pretend mode: print what kumade would do") do |p|
59
+ @options[:pretend] = true
60
+ end
61
+
62
+ opts.on_tail("-v", "--verbose", "Print what kumade is doing") do
63
+ @options[:verbose] = true
64
+ end
65
+
66
+ opts.on_tail('--version', 'Show version') do
67
+ puts "kumade #{Kumade::VERSION}"
68
+ exit
69
+ end
70
+
71
+ opts.on_tail('-h', '--help', 'Show this message') do
72
+ puts opts
73
+ exit
74
+ end
75
+ end.parse!(args)
76
+ end
77
+
78
+ def verbose?
79
+ @options[:verbose]
80
+ end
81
+
82
+ def print_output?
83
+ Kumade.configuration.pretending? || verbose?
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,14 @@
1
+ module Kumade
2
+ class Configuration
3
+ def initialize(environment = 'staging', pretending = false )
4
+ @environment = environment
5
+ @pretending = pretending
6
+ end
7
+
8
+ def pretending?
9
+ @pretending
10
+ end
11
+
12
+ attr_accessor :pretending, :environment
13
+ end
14
+ end
@@ -1,22 +1,28 @@
1
+ require "rake"
2
+ require 'cocaine'
3
+
1
4
  module Kumade
2
5
  class Deployer < Base
3
- DEPLOY_BRANCH = "deploy"
4
- attr_reader :environment, :pretending, :git
6
+ attr_reader :git, :heroku, :packager
5
7
 
6
- def initialize(environment = 'staging', pretending = false)
8
+ def initialize
7
9
  super()
8
- @environment = environment
9
- @pretending = pretending
10
- @git = Git.new(pretending, environment)
11
- @branch = @git.current_branch
10
+ @git = Git.new
11
+ @heroku = Heroku.new
12
+ @branch = @git.current_branch
13
+ @packager = Packager.new(@git)
12
14
  end
13
15
 
14
16
  def deploy
15
- ensure_heroku_remote_exists
16
- pre_deploy
17
- sync_heroku
18
- heroku_migrate
19
- post_deploy
17
+ begin
18
+ ensure_heroku_remote_exists
19
+ pre_deploy
20
+ heroku.sync
21
+ heroku.migrate_database
22
+ rescue
23
+ ensure
24
+ post_deploy
25
+ end
20
26
  end
21
27
 
22
28
  def pre_deploy
@@ -25,138 +31,31 @@ module Kumade
25
31
  sync_github
26
32
  end
27
33
 
28
- def sync_github
29
- git.push(@branch)
30
- end
31
-
32
- def sync_heroku
33
- git.create(DEPLOY_BRANCH)
34
- git.push("#{DEPLOY_BRANCH}:master", environment, true)
34
+ def package_assets
35
+ packager.run
35
36
  end
36
37
 
37
- def heroku_migrate
38
- heroku("rake db:migrate") unless pretending
39
- success("Migrated #{environment}")
38
+ def sync_github
39
+ git.push(@branch)
40
40
  end
41
41
 
42
42
  def post_deploy
43
- git.delete(DEPLOY_BRANCH, @branch)
44
- end
45
-
46
- def heroku(command)
47
- heroku_command = if cedar?
48
- "bundle exec heroku run"
49
- else
50
- "bundle exec heroku"
51
- end
52
- run_or_error("#{heroku_command} #{command} --remote #{environment}",
53
- "Failed to run #{command} on Heroku")
54
- end
55
-
56
- def cedar?
57
- return @cedar unless @cedar.nil?
58
- @cedar = heroku("stack").split("\n").grep(/\*/).any? do |line|
59
- line.include?("cedar")
60
- end
43
+ heroku.delete_deploy_branch
61
44
  end
62
45
 
63
46
  def ensure_clean_git
64
47
  git.ensure_clean_git
65
48
  end
66
49
 
67
- def package_assets
68
- invoke_custom_task if custom_task?
69
- package_with_jammit if jammit_installed?
70
- package_with_more if more_installed?
71
- end
72
-
73
- def package_with_jammit
74
- begin
75
- success_message = "Packaged assets with Jammit"
76
-
77
- if pretending
78
- success(success_message)
79
- else
80
- Jammit.package!
81
-
82
- success(success_message)
83
- git_add_and_commit_all_assets_in(jammit_assets_path)
84
- end
85
- rescue => jammit_error
86
- error("Error: #{jammit_error.class}: #{jammit_error.message}")
87
- end
88
- end
89
-
90
- def package_with_more
91
- success_message = "Packaged assets with More"
92
- if pretending
93
- success(success_message)
94
- else
95
- begin
96
- run "bundle exec rake more:generate"
97
- if git.dirty?
98
- success(success_message)
99
- git_add_and_commit_all_assets_in(more_assets_path)
100
- end
101
- rescue => more_error
102
- error("Error: #{more_error.class}: #{more_error.message}")
103
- end
104
- end
105
- end
106
-
107
- def invoke_custom_task
108
- success "Running kumade:before_asset_compilation task"
109
- Rake::Task["kumade:before_asset_compilation"].invoke unless pretending
110
- end
111
-
112
- def git_add_and_commit_all_assets_in(dir)
113
- git.add_and_commit_all_in(dir, DEPLOY_BRANCH, 'Compiled assets', "Added and committed all assets", "couldn't commit assets")
114
- end
115
-
116
- def jammit_assets_path
117
- File.join(Jammit::PUBLIC_ROOT, Jammit.package_path)
118
- end
119
-
120
- def more_assets_path
121
- File.join('public', ::Less::More.destination_path)
122
- end
123
-
124
- def jammit_installed?
125
- @jammit_installed ||=
126
- (defined?(Jammit) ||
127
- begin
128
- require 'jammit'
129
- true
130
- rescue LoadError
131
- false
132
- end)
133
- end
134
-
135
- def more_installed?
136
- @more_installed ||=
137
- (defined?(Less::More) ||
138
- begin
139
- require 'less/more'
140
- true
141
- rescue LoadError
142
- false
143
- end)
144
- end
145
-
146
- def custom_task?
147
- load("Rakefile") if File.exist?("Rakefile")
148
- Rake::Task.task_defined?("kumade:before_asset_compilation")
149
- end
150
-
151
50
  def ensure_heroku_remote_exists
152
- if git.remote_exists?(environment)
51
+ if git.remote_exists?(Kumade.configuration.environment)
153
52
  if git.heroku_remote?
154
- success("#{environment} is a Heroku remote")
53
+ success("#{Kumade.configuration.environment} is a Heroku remote")
155
54
  else
156
- error(%{Cannot deploy: "#{environment}" remote does not point to Heroku})
55
+ error(%{Cannot deploy: "#{Kumade.configuration.environment}" remote does not point to Heroku})
157
56
  end
158
57
  else
159
- error(%{Cannot deploy: "#{environment}" remote does not exist})
58
+ error(%{Cannot deploy: "#{Kumade.configuration.environment}" remote does not exist})
160
59
  end
161
60
  end
162
61
  end