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.
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - ruby-head
4
+ - 2.0.0
5
+ - 1.9.3
6
+ - jruby-head
7
+ - jruby-19mode
8
+
data/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ [![Build Status](https://secure.travis-ci.org/moredip/heroku-headless.png?branch=master)](http://travis-ci.org/moredip/heroku-headless)
2
+ [![Dependency Status](https://gemnasium.com/moredip/heroku-headless.png?travis)](https://gemnasium.com/moredip/heroku-headless)
3
+ [![Code Climate](https://codeclimate.com/github/moredip/heroku-headless.png)](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
@@ -17,6 +17,7 @@ Gem::Specification.new do |gem|
17
17
 
18
18
  gem.add_runtime_dependency "heroku-api"
19
19
  gem.add_runtime_dependency "rendezvous"
20
+ gem.add_development_dependency "rake"
20
21
  gem.add_development_dependency "rspec"
21
22
  gem.add_development_dependency "pry"
22
23
  end
@@ -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
@@ -1,30 +1,38 @@
1
1
  require "heroku-headless/version"
2
2
 
3
3
  require "heroku-headless/documents_actions"
4
- require "heroku-headless/creates_uuids"
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
- attr_accessor :configuration
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
@@ -0,0 +1,10 @@
1
+ require 'securerandom'
2
+
3
+ module HerokuHeadless
4
+ module CreatesUIDs
5
+ def generate_uid
6
+ SecureRandom.hex(16).downcase
7
+ end
8
+ module_function :generate_uid
9
+ end
10
+ end
@@ -8,7 +8,7 @@ module HerokuHeadless
8
8
  include TalksToHeroku
9
9
 
10
10
  def self.deploy(app_name)
11
- new(app_name,CreatesUUIDs.generate_lowercase_uuid).deploy
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}, "git push git@heroku.com:#{@app_name}.git HEAD:master" )
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-#{deploy_uuid}"[0,30]
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,deploy_uuid).deploy
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 deploy_uuid
51
- @deploy_uuid ||= CreatesUUIDs.generate_lowercase_uuid
50
+ def deploy_uid
51
+ @deploy_uid ||= CreatesUIDs.generate_uid
52
52
  end
53
53
  end
54
54
  end
@@ -2,8 +2,9 @@ module HerokuHeadless
2
2
  module DocumentsActions
3
3
  def do_action(description)
4
4
  print " " + description + " ..."
5
- yield
5
+ result = yield
6
6
  puts " DONE"
7
+ result
7
8
  end
8
9
  end
9
10
  end
@@ -1,3 +1,3 @@
1
1
  module HerokuHeadless
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -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
- $?.exitstatus.should_not eq 0
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
- $?.exitstatus.should eq 0
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
- $?.exitstatus.should eq 0
33
+ result = HerokuHeadless::Deployer.deploy('app_with_db')
34
+ result.should be_true
35
35
  end
36
- end
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.0
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-04-10 00:00:00.000000000 Z
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/creates_uuids.rb
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.24
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.
@@ -1,8 +0,0 @@
1
- module HerokuHeadless
2
- module CreatesUUIDs
3
- def generate_lowercase_uuid
4
- `uuidgen`.chomp.downcase
5
- end
6
- module_function :generate_lowercase_uuid
7
- end
8
- end