kumade 0.3.0 → 0.4.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.
- data/.travis.yml +0 -1
- data/README.md +19 -21
- data/bin/kumade +1 -1
- data/kumade.gemspec +2 -0
- data/lib/kumade.rb +16 -10
- data/lib/kumade/base.rb +14 -9
- data/lib/kumade/cli.rb +86 -0
- data/lib/kumade/configuration.rb +14 -0
- data/lib/kumade/deployer.rb +27 -128
- data/lib/kumade/git.rb +11 -12
- data/lib/kumade/heroku.rb +46 -0
- data/lib/kumade/packager.rb +94 -0
- data/lib/kumade/version.rb +1 -1
- data/lib/tasks/deploy.rake +1 -1
- data/spec/kumade/base_spec.rb +89 -8
- data/spec/kumade/cli_spec.rb +109 -0
- data/spec/kumade/configuration_spec.rb +36 -0
- data/spec/kumade/deployer_spec.rb +45 -415
- data/spec/kumade/git_spec.rb +88 -21
- data/spec/kumade/heroku_spec.rb +121 -0
- data/spec/kumade/packager_spec.rb +318 -0
- data/spec/kumade_spec.rb +18 -0
- data/spec/spec_helper.rb +19 -3
- data/spec/support/heroku.rb +33 -0
- metadata +63 -22
- data/lib/kumade/runner.rb +0 -70
- data/spec/kumade/runner_spec.rb +0 -66
data/lib/kumade/git.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
|
+
require 'cocaine'
|
1
2
|
module Kumade
|
2
3
|
class Git < Base
|
3
|
-
|
4
|
-
def initialize(pretending, environment)
|
4
|
+
def initialize
|
5
5
|
super()
|
6
|
-
@pretending = pretending
|
7
|
-
@environment = environment
|
8
6
|
end
|
9
7
|
|
10
8
|
def heroku_remote?
|
11
|
-
`git config --get remote.#{environment}.url`.strip
|
9
|
+
remote_url = `git config --get remote.#{Kumade.configuration.environment}.url`.strip
|
10
|
+
!! remote_url.strip.match(/^git@heroku\..+:(.+)\.git$/)
|
12
11
|
end
|
13
12
|
|
14
13
|
def self.environments
|
@@ -21,7 +20,7 @@ module Kumade
|
|
21
20
|
command << remote
|
22
21
|
command << branch
|
23
22
|
command = command.join(" ")
|
24
|
-
run_or_error(
|
23
|
+
run_or_error(command, "Failed to push #{branch} -> #{remote}")
|
25
24
|
success("Pushed #{branch} -> #{remote}")
|
26
25
|
end
|
27
26
|
|
@@ -32,12 +31,12 @@ module Kumade
|
|
32
31
|
end
|
33
32
|
|
34
33
|
def delete(branch_to_delete, branch_to_checkout)
|
35
|
-
run_or_error(
|
34
|
+
run_or_error("git checkout #{branch_to_checkout} && git branch -D #{branch_to_delete}",
|
36
35
|
"Failed to clean up #{branch_to_delete} branch")
|
37
36
|
end
|
38
37
|
|
39
38
|
def add_and_commit_all_in(dir, branch, commit_message, success_output, error_output)
|
40
|
-
run_or_error
|
39
|
+
run_or_error "git checkout -b #{branch} && git add -f #{dir} && git commit -m '#{commit_message}'",
|
41
40
|
"Cannot deploy: #{error_output}"
|
42
41
|
success success_output
|
43
42
|
end
|
@@ -47,7 +46,7 @@ module Kumade
|
|
47
46
|
end
|
48
47
|
|
49
48
|
def remote_exists?(remote_name)
|
50
|
-
if
|
49
|
+
if Kumade.configuration.pretending?
|
51
50
|
true
|
52
51
|
else
|
53
52
|
`git remote` =~ /^#{remote_name}$/
|
@@ -55,11 +54,11 @@ module Kumade
|
|
55
54
|
end
|
56
55
|
|
57
56
|
def dirty?
|
58
|
-
!
|
57
|
+
!run("git diff --exit-code")
|
59
58
|
end
|
60
59
|
|
61
60
|
def ensure_clean_git
|
62
|
-
if !
|
61
|
+
if ! Kumade.configuration.pretending? && dirty?
|
63
62
|
error("Cannot deploy: repo is not clean.")
|
64
63
|
else
|
65
64
|
success("Git repo is clean")
|
@@ -67,7 +66,7 @@ module Kumade
|
|
67
66
|
end
|
68
67
|
|
69
68
|
def branch_exist?(branch)
|
70
|
-
|
69
|
+
run("git show-ref #{branch}")
|
71
70
|
end
|
72
71
|
end
|
73
72
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'cocaine'
|
2
|
+
|
3
|
+
module Kumade
|
4
|
+
class Heroku < Base
|
5
|
+
DEPLOY_BRANCH = "deploy"
|
6
|
+
attr_reader :git
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
super()
|
10
|
+
@git = Git.new
|
11
|
+
@branch = @git.current_branch
|
12
|
+
end
|
13
|
+
|
14
|
+
def sync
|
15
|
+
git.create(DEPLOY_BRANCH)
|
16
|
+
git.push("#{DEPLOY_BRANCH}:master", Kumade.configuration.environment, true)
|
17
|
+
end
|
18
|
+
|
19
|
+
def migrate_database
|
20
|
+
heroku("rake db:migrate") unless Kumade.configuration.pretending?
|
21
|
+
success("Migrated #{Kumade.configuration.environment}")
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete_deploy_branch
|
25
|
+
git.delete(DEPLOY_BRANCH, @branch)
|
26
|
+
end
|
27
|
+
|
28
|
+
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")
|
36
|
+
end
|
37
|
+
|
38
|
+
def cedar?
|
39
|
+
return @cedar unless @cedar.nil?
|
40
|
+
|
41
|
+
@cedar = Cocaine::CommandLine.new("bundle exec heroku stack --remote #{Kumade.configuration.environment}").run.split("\n").grep(/\*/).any? do |line|
|
42
|
+
line.include?("cedar")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Kumade
|
2
|
+
class Packager < Base
|
3
|
+
attr_reader :git
|
4
|
+
|
5
|
+
def initialize(git)
|
6
|
+
super()
|
7
|
+
@git = git
|
8
|
+
end
|
9
|
+
|
10
|
+
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?
|
19
|
+
end
|
20
|
+
|
21
|
+
def custom_task?
|
22
|
+
load("Rakefile") if File.exist?("Rakefile")
|
23
|
+
Rake::Task.task_defined?("kumade:before_asset_compilation")
|
24
|
+
end
|
25
|
+
|
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!
|
34
|
+
|
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
|
41
|
+
end
|
42
|
+
|
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}")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
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)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/kumade/version.rb
CHANGED
data/lib/tasks/deploy.rake
CHANGED
data/spec/kumade/base_spec.rb
CHANGED
@@ -1,18 +1,99 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Kumade::Base, "#success" do
|
4
|
-
it
|
5
|
-
subject.should respond_to(:success)
|
6
|
-
end
|
4
|
+
it { should respond_to(:success) }
|
7
5
|
end
|
8
6
|
|
9
7
|
describe Kumade::Base, "#error" do
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
before { STDOUT.stubs(:puts) }
|
9
|
+
|
10
|
+
it { should respond_to(:error) }
|
13
11
|
|
14
12
|
it "prints its message and raises its message" do
|
15
|
-
subject.
|
16
|
-
|
13
|
+
lambda { subject.error("I'm an error!") }.should raise_error(Kumade::DeploymentError)
|
14
|
+
|
15
|
+
STDOUT.should have_received(:puts).with(regexp_matches(/I'm an error!/))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe Kumade::Base, "#run_or_error" do
|
20
|
+
let(:command) { "dummy command" }
|
21
|
+
let(:error_message) { "dummy error message" }
|
22
|
+
|
23
|
+
before do
|
24
|
+
STDOUT.stubs(:puts)
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when pretending" do
|
28
|
+
before do
|
29
|
+
Kumade.configuration.pretending = true
|
30
|
+
subject.stubs(:run)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "does not run the command" do
|
34
|
+
subject.run_or_error("dummy command", "dummy error message")
|
35
|
+
|
36
|
+
subject.should_not have_received(:run)
|
37
|
+
STDOUT.should have_received(:puts).with(regexp_matches(/#{command}/))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when not pretending" do
|
42
|
+
context "when it runs successfully" do
|
43
|
+
before do
|
44
|
+
Cocaine::CommandLine.stubs(:new).returns(stub(:run))
|
45
|
+
end
|
46
|
+
|
47
|
+
it "does not print an error" do
|
48
|
+
subject.run_or_error(command, error_message)
|
49
|
+
|
50
|
+
STDOUT.should_not have_received(:puts).with(regexp_matches(/#{error_message}/))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when it does not run successfully " do
|
55
|
+
let(:failing_command_line) { stub("Failing Cocaine::CommandLine") }
|
56
|
+
|
57
|
+
before do
|
58
|
+
subject.stubs(:error)
|
59
|
+
failing_command_line.stubs(:run).raises(Cocaine::ExitStatusError)
|
60
|
+
Cocaine::CommandLine.stubs(:new).returns(failing_command_line)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "prints an error message" do
|
64
|
+
subject.run_or_error(command, error_message)
|
65
|
+
|
66
|
+
subject.should have_received(:error).with(error_message)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe Kumade::Base, "#run" do
|
73
|
+
let(:command_line) { stub("Cocaine::CommandLine") }
|
74
|
+
let(:command) { "command" }
|
75
|
+
|
76
|
+
before do
|
77
|
+
Cocaine::CommandLine.stubs(:new).with(command).returns(command_line)
|
78
|
+
end
|
79
|
+
|
80
|
+
context "when not successful" do
|
81
|
+
before do
|
82
|
+
command_line.stubs(:run)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "returns true" do
|
86
|
+
subject.run(command).should == true
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "when successful" do
|
91
|
+
before do
|
92
|
+
command_line.stubs(:run).raises(Cocaine::ExitStatusError)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "returns false" do
|
96
|
+
subject.run(command).should == false
|
97
|
+
end
|
17
98
|
end
|
18
99
|
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Kumade::CLI do
|
4
|
+
let(:out) { StringIO.new }
|
5
|
+
let(:environment) { 'my-environment' }
|
6
|
+
let(:deployer) { stub("Deployer", :new => deployer_instance) }
|
7
|
+
let(:deployer_instance) { stub("DeployerInstance", :deploy => nil) }
|
8
|
+
|
9
|
+
before { Kumade::CLI.deployer = deployer }
|
10
|
+
after { Kumade::CLI.deployer = nil }
|
11
|
+
|
12
|
+
context "when pretending" do
|
13
|
+
%w(-p --pretend).each do |pretend_flag|
|
14
|
+
subject { Kumade::CLI.new([pretend_flag, environment], out) }
|
15
|
+
|
16
|
+
context pretend_flag do
|
17
|
+
it "sets pretending to true" do
|
18
|
+
subject
|
19
|
+
Kumade.configuration.pretending.should == true
|
20
|
+
end
|
21
|
+
|
22
|
+
it "deploys" do
|
23
|
+
subject
|
24
|
+
|
25
|
+
deployer_instance.should have_received(:deploy)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "with no command-line arguments" do
|
32
|
+
subject { Kumade::CLI.new([], out) }
|
33
|
+
|
34
|
+
it "sets the environment to staging" do
|
35
|
+
Kumade.configuration.environment.should == 'staging'
|
36
|
+
end
|
37
|
+
|
38
|
+
it "sets pretending to false" do
|
39
|
+
Kumade.configuration.pretending.should == false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "running normally" do
|
44
|
+
subject { Kumade::CLI.new([environment], out) }
|
45
|
+
|
46
|
+
it "sets pretending to false" do
|
47
|
+
subject
|
48
|
+
Kumade.configuration.pretending.should == false
|
49
|
+
end
|
50
|
+
|
51
|
+
it "deploys" do
|
52
|
+
subject
|
53
|
+
|
54
|
+
deployer_instance.should have_received(:deploy)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe Kumade::CLI, ".deployer" do
|
60
|
+
after { Kumade::CLI.deployer = nil }
|
61
|
+
|
62
|
+
it "sets the deployer to the Deployer class by default" do
|
63
|
+
Kumade::CLI.deployer.should == Kumade::Deployer
|
64
|
+
end
|
65
|
+
|
66
|
+
it "can override deployer" do
|
67
|
+
Kumade::CLI.deployer = "deployer!"
|
68
|
+
Kumade::CLI.deployer.should == "deployer!"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe Kumade::CLI, ".swapping_stdout_for" do
|
73
|
+
let(:stdout) { $stdout }
|
74
|
+
let(:output) { StringIO.new }
|
75
|
+
|
76
|
+
before do
|
77
|
+
stdout.stubs(:print => nil, :puts => nil)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'does not let anything get printed' do
|
81
|
+
Kumade::CLI.swapping_stdout_for(output) do
|
82
|
+
$stdout.puts "Hello, you can't see me."
|
83
|
+
end
|
84
|
+
|
85
|
+
stdout.should_not have_received(:print)
|
86
|
+
|
87
|
+
output.rewind
|
88
|
+
output.read.should == "Hello, you can't see me.\n"
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'dumps the output stash to real stdout when an error happens' do
|
92
|
+
Kumade::CLI.swapping_stdout_for(output) do
|
93
|
+
$stdout.puts "Hello, you can see me!"
|
94
|
+
raise Kumade::DeploymentError.new("error")
|
95
|
+
end
|
96
|
+
|
97
|
+
stdout.should have_received(:print)
|
98
|
+
end
|
99
|
+
|
100
|
+
context "in print output mode" do
|
101
|
+
it 'prints everything' do
|
102
|
+
Kumade::CLI.swapping_stdout_for(output, true) do
|
103
|
+
$stdout.puts "Hello, you can see me!"
|
104
|
+
end
|
105
|
+
|
106
|
+
stdout.should have_received(:puts)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Kumade::Configuration, "by default" do
|
4
|
+
its(:environment) { should == 'staging' }
|
5
|
+
it { should_not be_pretending }
|
6
|
+
end
|
7
|
+
|
8
|
+
describe Kumade::Configuration, "#pretending" do
|
9
|
+
it "has read/write access for the pretending attribute" do
|
10
|
+
subject.pretending = true
|
11
|
+
subject.pretending.should == true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe Kumade::Configuration, "#pretending?" do
|
16
|
+
it "returns false when not pretending" do
|
17
|
+
subject.pretending = false
|
18
|
+
subject.should_not be_pretending
|
19
|
+
end
|
20
|
+
|
21
|
+
it "returns true when pretending" do
|
22
|
+
subject.pretending = true
|
23
|
+
subject.should be_pretending
|
24
|
+
end
|
25
|
+
|
26
|
+
it "defaults to false" do
|
27
|
+
subject.pretending.should == false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe Kumade::Configuration, "#environment" do
|
32
|
+
it "has read/write access for the environment attribute" do
|
33
|
+
subject.environment = 'new-environment'
|
34
|
+
subject.environment.should == 'new-environment'
|
35
|
+
end
|
36
|
+
end
|