heroku-headless 0.2.0 → 0.2.1
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 +8 -0
- data/README.md +66 -0
- data/Rakefile +4 -2
- data/heroku-headless.gemspec +1 -0
- data/integration/configuration_spec.rb +10 -0
- data/lib/heroku-headless.rb +13 -5
- data/lib/heroku-headless/creates_uids.rb +10 -0
- data/lib/heroku-headless/deployer.rb +32 -7
- data/lib/heroku-headless/disposable_deployer.rb +4 -4
- data/lib/heroku-headless/documents_actions.rb +2 -1
- data/lib/heroku-headless/version.rb +1 -1
- data/spec/deploy_spec.rb +67 -9
- metadata +28 -4
- data/lib/heroku-headless/creates_uuids.rb +0 -8
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
[](http://travis-ci.org/moredip/heroku-headless)
|
2
|
+
[](https://gemnasium.com/moredip/heroku-headless)
|
3
|
+
[](https://codeclimate.com/github/moredip/heroku-headless)
|
4
|
+
|
1
5
|
# HerokuHeadless
|
2
6
|
|
3
7
|
## What?
|
@@ -19,3 +23,65 @@ And then execute:
|
|
19
23
|
Or install it yourself as:
|
20
24
|
|
21
25
|
$ gem install heroku-headless
|
26
|
+
|
27
|
+
## How do I use this?
|
28
|
+
It's as simple as
|
29
|
+
```ruby
|
30
|
+
require 'heroku-headless'
|
31
|
+
HerokuHeadless::Deployer.deploy( 'your-app-name' )
|
32
|
+
```
|
33
|
+
|
34
|
+
### Use it with pre- and post-commands:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
require 'heroku-headless'
|
38
|
+
|
39
|
+
app_name = 'my-heroku-app-name'
|
40
|
+
remote_name = 'herokuheadless'
|
41
|
+
|
42
|
+
puts "deploying to heroku app #{app_name}"
|
43
|
+
remote_name = "headlessheroku"
|
44
|
+
HerokuHeadless.configure do | config |
|
45
|
+
config.post_deploy_commands = ['rake db:migrate']
|
46
|
+
config.pre_deploy_git_commands = [
|
47
|
+
"git remote -v",
|
48
|
+
"git checkout master",
|
49
|
+
"git commit -am \"changes from headless deploy\" ",
|
50
|
+
"git remote add #{remote_name} git@heroku.com:#{app_name}.git",
|
51
|
+
"git fetch #{remote_name}",
|
52
|
+
"git merge -m \"merged by automatic deploy\" #{remote_name}/master"]
|
53
|
+
end
|
54
|
+
|
55
|
+
result = HerokuHeadless::Deployer.deploy( app_name )
|
56
|
+
puts "successfully deployed to #{app_name}" if result
|
57
|
+
exit result ? 0 : 1
|
58
|
+
|
59
|
+
```
|
60
|
+
|
61
|
+
### Restart processes after deployment and post-commands:
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
require 'heroku-headless'
|
65
|
+
|
66
|
+
app_name = 'my-heroku-app-name'
|
67
|
+
remote_name = 'herokuheadless'
|
68
|
+
|
69
|
+
puts "deploying to heroku app #{app_name}"
|
70
|
+
remote_name = "headlessheroku"
|
71
|
+
HerokuHeadless.configure do | config |
|
72
|
+
config.post_deploy_commands = ['rake db:migrate']
|
73
|
+
config.restart_processes = true
|
74
|
+
end
|
75
|
+
|
76
|
+
result = HerokuHeadless::Deployer.deploy( app_name )
|
77
|
+
puts "successfully deployed to #{app_name}" if result
|
78
|
+
exit result ? 0 : 1
|
79
|
+
|
80
|
+
```
|
81
|
+
|
82
|
+
|
83
|
+
## Tell me more!
|
84
|
+
|
85
|
+
[Deploying To Heroku From CI](http://blog.thepete.net/blog/2013/01/21/deploying-to-heroku-from-ci)
|
86
|
+
|
87
|
+
[Deploying to Heroku From CI - the Gory Details](http://blog.thepete.net/blog/2013/01/22/deploying-to-heroku-from-ci-the-gory-details/)
|
data/Rakefile
CHANGED
@@ -3,7 +3,9 @@ require "bundler/gem_tasks"
|
|
3
3
|
require 'rspec/core/rake_task'
|
4
4
|
|
5
5
|
RSpec::Core::RakeTask.new(:spec)
|
6
|
+
RSpec::Core::RakeTask.new(:integration) do | spec |
|
7
|
+
spec.pattern = 'integration/**/*_spec.rb'
|
8
|
+
end
|
6
9
|
|
10
|
+
task :default => [:spec, :integration]
|
7
11
|
task :build => :spec
|
8
|
-
|
9
|
-
task :default => :spec
|
data/heroku-headless.gemspec
CHANGED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'heroku-headless'
|
3
|
+
# Do not include spec_helper, because it has a HerokuHeadless.configure block
|
4
|
+
|
5
|
+
describe 'HerokuHeadless' do
|
6
|
+
it "should have a default configuration" do
|
7
|
+
HerokuHeadless.configuration = nil
|
8
|
+
HerokuHeadless.configuration.mock_mode.should == false
|
9
|
+
end
|
10
|
+
end
|
data/lib/heroku-headless.rb
CHANGED
@@ -1,30 +1,38 @@
|
|
1
1
|
require "heroku-headless/version"
|
2
2
|
|
3
3
|
require "heroku-headless/documents_actions"
|
4
|
-
require "heroku-headless/
|
4
|
+
require "heroku-headless/creates_uids"
|
5
5
|
require "heroku-headless/talks_to_heroku"
|
6
6
|
|
7
7
|
require "heroku-headless/deployer"
|
8
8
|
|
9
9
|
module HerokuHeadless
|
10
10
|
class << self
|
11
|
-
|
11
|
+
attr_writer :configuration
|
12
12
|
end
|
13
13
|
|
14
14
|
def self.configure
|
15
|
-
self.configuration ||= Configuration.new
|
16
15
|
yield(configuration)
|
17
16
|
end
|
18
17
|
|
18
|
+
def self.configuration
|
19
|
+
@configuration ||= Configuration.new
|
20
|
+
end
|
21
|
+
|
19
22
|
def self.heroku
|
20
23
|
@@heroku ||= Heroku::API.new(:mock => HerokuHeadless.configuration.mock_mode)
|
21
24
|
end
|
22
25
|
|
23
26
|
class Configuration
|
24
|
-
attr_accessor :mock_mode, :post_deploy_commands
|
27
|
+
attr_accessor :mock_mode, :pre_deploy_git_commands, :post_deploy_commands,
|
28
|
+
:force_push, :restart_processes
|
25
29
|
|
26
30
|
def initialize
|
31
|
+
@pre_deploy_git_commands = []
|
27
32
|
@post_deploy_commands = []
|
33
|
+
@force_push ||= false
|
34
|
+
@mock_mode ||= false
|
35
|
+
@restart_processes ||= false
|
28
36
|
end
|
29
37
|
end
|
30
|
-
end
|
38
|
+
end
|
@@ -8,7 +8,7 @@ module HerokuHeadless
|
|
8
8
|
include TalksToHeroku
|
9
9
|
|
10
10
|
def self.deploy(app_name)
|
11
|
-
new(app_name,
|
11
|
+
new(app_name,CreatesUIDs.generate_uid).deploy
|
12
12
|
end
|
13
13
|
|
14
14
|
def initialize( app_name, uid )
|
@@ -19,14 +19,17 @@ module HerokuHeadless
|
|
19
19
|
def deploy
|
20
20
|
prep_temp_dir
|
21
21
|
setup_ssh_key
|
22
|
-
do_action('push git to heroku'){ push_head_to_app }
|
23
|
-
do_action('post_deploy_hooks'){ run_post_deploy_hooks }
|
24
|
-
|
22
|
+
result = do_action('push git to heroku'){ push_head_to_app }
|
23
|
+
result = result && do_action('post_deploy_hooks'){ run_post_deploy_hooks }
|
24
|
+
if HerokuHeadless.configuration.restart_processes
|
25
|
+
result = result && do_action('restart_processes'){ restart_processes }
|
26
|
+
end
|
27
|
+
result
|
25
28
|
ensure
|
26
29
|
cleanup
|
27
30
|
end
|
28
31
|
|
29
|
-
private
|
32
|
+
private
|
30
33
|
|
31
34
|
def prep_temp_dir
|
32
35
|
@tmpdir = Pathname.new( Dir.tmpdir ).join('heroku-deployer').join(@uid)
|
@@ -66,13 +69,14 @@ module HerokuHeadless
|
|
66
69
|
def add_ssh_key
|
67
70
|
heroku.post_key(public_ssh_key)
|
68
71
|
end
|
69
|
-
|
72
|
+
|
70
73
|
def remove_ssh_key
|
71
74
|
heroku.delete_key(ssh_key_name)
|
72
75
|
end
|
73
76
|
|
74
77
|
def push_head_to_app
|
75
78
|
setup_custom_git_ssh
|
79
|
+
run_pre_deploy_git_commands
|
76
80
|
push_git
|
77
81
|
end
|
78
82
|
|
@@ -87,7 +91,23 @@ module HerokuHeadless
|
|
87
91
|
end
|
88
92
|
|
89
93
|
def push_git
|
90
|
-
system( {'GIT_SSH'=>custom_git_ssh_path.to_s},
|
94
|
+
system( {'GIT_SSH'=>custom_git_ssh_path.to_s}, git_push_command )
|
95
|
+
end
|
96
|
+
|
97
|
+
def git_push_command
|
98
|
+
cmd = "git push "
|
99
|
+
cmd << "-f " if HerokuHeadless.configuration.force_push
|
100
|
+
cmd << "git@heroku.com:#{@app_name}.git HEAD:master"
|
101
|
+
end
|
102
|
+
|
103
|
+
def run_pre_deploy_git_commands
|
104
|
+
HerokuHeadless.configuration.pre_deploy_git_commands.each do | command |
|
105
|
+
do_action( command ) { run_git_command(command) }
|
106
|
+
end
|
107
|
+
end
|
108
|
+
def run_git_command(command)
|
109
|
+
result = system( {'GIT_SSH'=>custom_git_ssh_path.to_s}, command )
|
110
|
+
result
|
91
111
|
end
|
92
112
|
|
93
113
|
def run_post_deploy_hooks
|
@@ -96,6 +116,11 @@ module HerokuHeadless
|
|
96
116
|
end
|
97
117
|
end
|
98
118
|
|
119
|
+
def restart_processes
|
120
|
+
response = heroku.post_ps_restart(@app_name)
|
121
|
+
response.body == "ok"
|
122
|
+
end
|
123
|
+
|
99
124
|
def run_command(cmd)
|
100
125
|
data = heroku.post_ps(@app_name, cmd, :attach => true).body
|
101
126
|
rendezvous_url = data['rendezvous_url']
|
@@ -26,13 +26,13 @@ module HerokuHeadless
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def create_app
|
29
|
-
app_name = "disposable-#{
|
29
|
+
app_name = "disposable-#{deploy_uid}"[0,30]
|
30
30
|
heroku.post_app( name: app_name )
|
31
31
|
@app_name = app_name
|
32
32
|
end
|
33
33
|
|
34
34
|
def deploy_app
|
35
|
-
Deployer.new(@app_name,
|
35
|
+
Deployer.new(@app_name,deploy_uid).deploy
|
36
36
|
end
|
37
37
|
|
38
38
|
def cleanup
|
@@ -47,8 +47,8 @@ module HerokuHeadless
|
|
47
47
|
heroku.delete_app( @app_name ) if @app_name
|
48
48
|
end
|
49
49
|
|
50
|
-
def
|
51
|
-
@
|
50
|
+
def deploy_uid
|
51
|
+
@deploy_uid ||= CreatesUIDs.generate_uid
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
data/spec/deploy_spec.rb
CHANGED
@@ -4,16 +4,16 @@ describe 'HerokuHeadless' do
|
|
4
4
|
let(:heroku) { HerokuHeadless.heroku }
|
5
5
|
|
6
6
|
it "should fail to deploy a missing app" do
|
7
|
-
HerokuHeadless::Deployer.deploy('missing_app')
|
8
|
-
|
7
|
+
result = HerokuHeadless::Deployer.deploy('missing_app')
|
8
|
+
result.should be_false
|
9
9
|
end
|
10
10
|
|
11
11
|
it "should successfully deploy an existing app" do
|
12
12
|
heroku.post_app(:name => 'existing_app')
|
13
13
|
# Creating an app on heroku actually isn't enough to make the git push pass!
|
14
|
-
HerokuHeadless::Deployer.any_instance.should_receive(:push_git)
|
15
|
-
HerokuHeadless::Deployer.deploy('existing_app')
|
16
|
-
|
14
|
+
HerokuHeadless::Deployer.any_instance.should_receive(:push_git).and_return(true)
|
15
|
+
result = HerokuHeadless::Deployer.deploy('existing_app')
|
16
|
+
result.should be_true
|
17
17
|
end
|
18
18
|
|
19
19
|
it "should call post-deploy actions" do
|
@@ -26,11 +26,69 @@ describe 'HerokuHeadless' do
|
|
26
26
|
]
|
27
27
|
end
|
28
28
|
|
29
|
-
HerokuHeadless::Deployer.any_instance.should_receive(:push_git)
|
29
|
+
HerokuHeadless::Deployer.any_instance.should_receive(:push_git).and_return(true)
|
30
30
|
HerokuHeadless::Deployer.any_instance.should_receive(:run_command).with('echo hello')
|
31
31
|
HerokuHeadless::Deployer.any_instance.should_receive(:run_command).with('echo success')
|
32
32
|
|
33
|
-
HerokuHeadless::Deployer.deploy('app_with_db')
|
34
|
-
|
33
|
+
result = HerokuHeadless::Deployer.deploy('app_with_db')
|
34
|
+
result.should be_true
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
|
+
it "should restart the app if configured" do
|
38
|
+
heroku.post_app(:name => 'app_with_restart')
|
39
|
+
|
40
|
+
HerokuHeadless.configure do | config |
|
41
|
+
config.restart_processes = true
|
42
|
+
end
|
43
|
+
|
44
|
+
HerokuHeadless::Deployer.any_instance.should_receive(:push_git).and_return(true)
|
45
|
+
HerokuHeadless::Deployer.any_instance.should_receive(:restart_processes).and_call_original
|
46
|
+
|
47
|
+
result = HerokuHeadless::Deployer.deploy('app_with_restart')
|
48
|
+
result.should be_true
|
49
|
+
end
|
50
|
+
|
51
|
+
context "forced pushs" do
|
52
|
+
let(:headless) { HerokuHeadless::Deployer.new("forced_app", HerokuHeadless::CreatesUIDs.generate_uid) }
|
53
|
+
subject { headless.send(:git_push_command) }
|
54
|
+
|
55
|
+
context "enabled forced push" do
|
56
|
+
before do
|
57
|
+
HerokuHeadless.configure do | config |
|
58
|
+
config.force_push = true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
it {should eq "git push -f git@heroku.com:forced_app.git HEAD:master"}
|
62
|
+
end
|
63
|
+
|
64
|
+
context "disabled forced push" do
|
65
|
+
before do
|
66
|
+
HerokuHeadless.configure do | config |
|
67
|
+
config.force_push = false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
it {should eq "git push git@heroku.com:forced_app.git HEAD:master"}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should run the git pre-deploy commands" do
|
75
|
+
@app_name = 'app_with_configuration_changes'
|
76
|
+
heroku.post_app(:name => @app_name)
|
77
|
+
HerokuHeadless.configure do | config |
|
78
|
+
config.pre_deploy_git_commands = [
|
79
|
+
"git checkout master",
|
80
|
+
"git remote add heroku git@heroku.com:#{@app_name}.git"
|
81
|
+
]
|
82
|
+
end
|
83
|
+
|
84
|
+
HerokuHeadless::Deployer.any_instance.should_receive(:push_git).and_return(true)
|
85
|
+
HerokuHeadless::Deployer.any_instance.should_receive(:run_git_command).with("git checkout master")
|
86
|
+
HerokuHeadless::Deployer.any_instance.should_receive(:run_git_command).with("git remote add heroku git@heroku.com:#{@app_name}.git")
|
87
|
+
|
88
|
+
result = HerokuHeadless::Deployer.deploy(@app_name)
|
89
|
+
result.should be_true
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: heroku-headless
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-06-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: heroku-api
|
@@ -43,6 +43,22 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
46
62
|
- !ruby/object:Gem::Dependency
|
47
63
|
name: rspec
|
48
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -83,13 +99,15 @@ extensions: []
|
|
83
99
|
extra_rdoc_files: []
|
84
100
|
files:
|
85
101
|
- .gitignore
|
102
|
+
- .travis.yml
|
86
103
|
- Gemfile
|
87
104
|
- LICENSE
|
88
105
|
- README.md
|
89
106
|
- Rakefile
|
90
107
|
- heroku-headless.gemspec
|
108
|
+
- integration/configuration_spec.rb
|
91
109
|
- lib/heroku-headless.rb
|
92
|
-
- lib/heroku-headless/
|
110
|
+
- lib/heroku-headless/creates_uids.rb
|
93
111
|
- lib/heroku-headless/deployer.rb
|
94
112
|
- lib/heroku-headless/disposable_app_deleter.rb
|
95
113
|
- lib/heroku-headless/disposable_deployer.rb
|
@@ -110,15 +128,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
110
128
|
- - ! '>='
|
111
129
|
- !ruby/object:Gem::Version
|
112
130
|
version: '0'
|
131
|
+
segments:
|
132
|
+
- 0
|
133
|
+
hash: 3232932552037509403
|
113
134
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
135
|
none: false
|
115
136
|
requirements:
|
116
137
|
- - ! '>='
|
117
138
|
- !ruby/object:Gem::Version
|
118
139
|
version: '0'
|
140
|
+
segments:
|
141
|
+
- 0
|
142
|
+
hash: 3232932552037509403
|
119
143
|
requirements: []
|
120
144
|
rubyforge_project:
|
121
|
-
rubygems_version: 1.8.
|
145
|
+
rubygems_version: 1.8.25
|
122
146
|
signing_key:
|
123
147
|
specification_version: 3
|
124
148
|
summary: Heroku's workflow is geared towards pushing to a heroku app from a dev workstation.
|