heroku_san 2.1.3 → 2.1.4

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/CHANGELOG.md CHANGED
@@ -1,6 +1,21 @@
1
1
  # Change log (curated)
2
2
 
3
+ ## v2.1.4
4
+
5
+ * Use heroku-api for client calls instead heroku gem
6
+
7
+ ## v2.1.3
8
+
9
+ * Bug fixes
10
+
11
+ ## v2.1.2
12
+
13
+ * Bug fixes
14
+ * 1.8.7 backward compatibility
15
+ * Refactoring
16
+
3
17
  ## v2.1.1
18
+
4
19
  * Bug fixes
5
20
  * Changed most Stage methods to call Heroku::Client methods instead of shelling out
6
21
  * Finished integration tests
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
1
  source :rubygems
2
2
 
3
3
  # Specify dependencies in heroku_san.gemspec
4
- gemspec
4
+ gemspec
@@ -112,7 +112,7 @@ end
112
112
 
113
113
  When /^I deploy my project$/ do
114
114
  run_simple 'git init .'
115
- run_simple 'rails generate scaffold droids'
115
+ run_simple 'rails generate scaffold droid'
116
116
  append_to_file 'app/views/droids/index.html.erb', %Q{\n<div><code><%= ENV['DROIDS'] -%></code></div>\n}
117
117
  run_simple 'git add .'
118
118
  run_simple 'git commit -m "Initial commit"'
data/heroku_san.gemspec CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
24
24
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
25
25
  s.add_development_dependency(%q<rails>, ['>= 2'])
26
26
  s.add_runtime_dependency(%q<heroku>, ['>= 2'])
27
+ s.add_runtime_dependency(%q<heroku-api>, ['>= 0.1.2'])
27
28
  s.add_runtime_dependency(%q<rake>)
28
29
  s.add_development_dependency(%q<aruba>)
29
30
  s.add_development_dependency(%q<cucumber>)
@@ -32,12 +33,14 @@ Gem::Specification.new do |s|
32
33
  else
33
34
  s.add_dependency(%q<rails>, ['>= 2'])
34
35
  s.add_dependency(%q<heroku>, ['>= 2'])
36
+ s.add_dependency(%q<heroku-api>, ['>= 0.1.2'])
35
37
  s.add_dependency(%q<aruba>)
36
38
  s.add_dependency(%q<cucumber>)
37
39
  end
38
40
  else
39
41
  s.add_dependency(%q<rails>, ['>= 2'])
40
42
  s.add_dependency(%q<heroku>, ['>= 2'])
43
+ s.add_dependency(%q<heroku-api>, ['>= 0.1.2'])
41
44
  s.add_dependency(%q<aruba>)
42
45
  s.add_dependency(%q<cucumber>)
43
46
  end
@@ -1,6 +1,9 @@
1
1
  require 'heroku'
2
+ require 'heroku/api'
2
3
  require 'json'
3
4
 
5
+ MOCK = false unless defined?(MOCK)
6
+
4
7
  module HerokuSan
5
8
  class Stage
6
9
  attr_reader :name
@@ -12,7 +15,7 @@ module HerokuSan
12
15
  end
13
16
 
14
17
  def heroku
15
- Heroku::Auth.client
18
+ @heroku ||= Heroku::API.new(:api_key => ENV['HEROKU_API_KEY'] || Heroku::Auth.api_key, :mock => MOCK)
16
19
  end
17
20
 
18
21
  def app
@@ -24,7 +27,7 @@ module HerokuSan
24
27
  end
25
28
 
26
29
  def stack
27
- @options['stack'] ||= heroku.list_stacks(app).detect{|stack| stack['current']}['name']
30
+ @options['stack'] ||= heroku.get_stack(app).body.detect{|stack| stack['current']}['name']
28
31
  end
29
32
 
30
33
  def tag
@@ -60,24 +63,23 @@ module HerokuSan
60
63
 
61
64
  def maintenance(action = nil)
62
65
  if block_given?
63
- heroku.maintenance(app, :on)
66
+ heroku.post_app_maintenance(app, '1')
64
67
  begin
65
68
  yield
66
69
  ensure
67
- heroku.maintenance(app, :off)
70
+ heroku.post_app_maintenance(app, '0')
68
71
  end
69
72
  else
70
73
  raise ArgumentError, "Action #{action.inspect} must be one of (:on, :off)", caller if ![:on, :off].include?(action)
71
- heroku.maintenance(app, action)
74
+ heroku.post_app_maintenance(app, {:on => '1', :off => '0'}[action])
72
75
  end
73
76
  end
74
77
 
75
78
  def create # DEPREC?
76
- if @options['stack']
77
- heroku.create(@options['app'], {:stack => @options['stack']})
78
- else
79
- heroku.create(@options['app'])
80
- end
79
+ params = Hash[@options.select{|k,v| %w[app stack].include? k}].stringify_keys
80
+ params['name'] = params.delete('app')
81
+ response = heroku.post_app(params)
82
+ response.body['name']
81
83
  end
82
84
 
83
85
  def sharing_add(email) # DEPREC?
@@ -89,15 +91,16 @@ module HerokuSan
89
91
  end
90
92
 
91
93
  def long_config
92
- heroku.config_vars(app)
94
+ heroku.get_config_vars(app).body
93
95
  end
94
96
 
95
97
  def push_config(options = nil)
96
- JSON.parse(heroku.add_config_vars(app, options || config))
98
+ params = (options || config).stringify_keys
99
+ heroku.put_config_vars(app, params).body
97
100
  end
98
101
 
99
102
  def restart
100
- heroku.ps_restart(app)
103
+ "restarted" if heroku.post_ps_restart(app).body == 'ok'
101
104
  end
102
105
 
103
106
  def logs(tail = false)
@@ -114,4 +117,20 @@ module HerokuSan
114
117
  sh "heroku #{command} --app #{app}"
115
118
  end
116
119
  end
120
+ end
121
+
122
+ # from ActiveSupport
123
+ class Hash
124
+ # Return a new hash with all keys converted to strings.
125
+ def stringify_keys
126
+ dup.stringify_keys!
127
+ end
128
+
129
+ # Destructively convert all keys to strings.
130
+ def stringify_keys!
131
+ keys.each do |key|
132
+ self[key.to_s] = delete(key)
133
+ end
134
+ self
135
+ end
117
136
  end
@@ -1,3 +1,3 @@
1
1
  module HerokuSan
2
- VERSION = "2.1.3"
2
+ VERSION = "2.1.4"
3
3
  end
@@ -4,10 +4,9 @@ require 'heroku/client'
4
4
  describe HerokuSan::Stage do
5
5
  include Git
6
6
  subject { HerokuSan::Stage.new('production', {"app" => "awesomeapp", "stack" => "bamboo-ree-1.8.7"})}
7
-
7
+ STOCK_CONFIG = {"BUNDLE_WITHOUT"=>"development:test", "LANG"=>"en_US.UTF-8", "RACK_ENV"=>"production"}
8
8
  before do
9
- @heroku_client = mock(Heroku::Client)
10
- Heroku::Auth.stub(:client).and_return(@heroku_client)
9
+ Heroku::Auth.stub(:api_key) { 'API_KEY' }
11
10
  end
12
11
 
13
12
  context "initializes" do
@@ -39,9 +38,9 @@ describe HerokuSan::Stage do
39
38
  describe "#stack" do
40
39
  it "returns the name of the stack from Heroku" do
41
40
  subject = HerokuSan::Stage.new('production', {"app" => "awesomeapp"})
42
- @heroku_client.should_receive(:list_stacks).with('awesomeapp').
43
- and_return { [{'name' => 'other'}, {'name' => 'the-one', 'current' => true}] }
44
- subject.stack.should == 'the-one'
41
+ with_app(subject, 'name' => 'awesomeapp') do |app_data|
42
+ subject.stack.should == 'bamboo-mri-1.9.2'
43
+ end
45
44
  end
46
45
 
47
46
  it "returns the stack name from the config if it is set there" do
@@ -86,22 +85,24 @@ describe HerokuSan::Stage do
86
85
 
87
86
  describe "#migrate" do
88
87
  it "runs rake db:migrate" do
89
- subject.should_receive(:rake).with('db:migrate').and_return 'output:'
90
- # @heroku_client.should_receive(:rake).with('awesomeapp', 'db:migrate').and_return "output:"
91
- @heroku_client.should_receive(:ps_restart).with('awesomeapp').and_return "restarted"
92
- subject.migrate.should == "restarted"
88
+ with_app(subject, 'name' => subject.app) do |app_data|
89
+ subject.should_receive(:rake).with('db:migrate').and_return 'output:'
90
+ subject.migrate.should == "restarted"
91
+ end
93
92
  end
94
93
  end
95
94
 
96
95
  describe "#maintenance" do
97
96
  it ":on" do
98
- @heroku_client.should_receive(:maintenance).with('awesomeapp', :on) {'on'}
99
- subject.maintenance(:on).should == 'on'
97
+ with_app(subject, 'name' => subject.app )do |app_data|
98
+ subject.maintenance(:on).status.should == 200
99
+ end
100
100
  end
101
101
 
102
102
  it ":off" do
103
- @heroku_client.should_receive(:maintenance).with('awesomeapp', :off) {'off'}
104
- subject.maintenance(:off).should == 'off'
103
+ with_app(subject, 'name' => subject.app) do |app_data|
104
+ subject.maintenance(:off).status.should.should == 200
105
+ end
105
106
  end
106
107
 
107
108
  it "otherwise raises an ArgumentError" do
@@ -112,36 +113,45 @@ describe HerokuSan::Stage do
112
113
 
113
114
  context "with a block" do
114
115
  it "wraps it in a maitenance mode" do
115
- @heroku_client.should_receive(:maintenance).with('awesomeapp', :on).ordered
116
- reactor = mock("Reactor"); reactor.should_receive(:scram).with(:now).ordered
117
- @heroku_client.should_receive(:maintenance).with('awesomeapp', :off).ordered
118
- subject.maintenance do reactor.scram(:now) end
116
+ with_app(subject, 'name' => subject.app) do |app_data|
117
+ subject.heroku.should_receive(:post_app_maintenance).with(subject.app, '1').ordered
118
+ reactor = mock("Reactor"); reactor.should_receive(:scram).with(:now).ordered
119
+ subject.heroku.should_receive(:post_app_maintenance).with(subject.app, '0').ordered
120
+
121
+ subject.maintenance {reactor.scram(:now)}
122
+ end
119
123
  end
120
124
  it "ensures that maintenance mode is turned off" do
121
- @heroku_client.should_receive(:maintenance).with('awesomeapp', :on).ordered
122
- reactor = mock("Reactor"); reactor.should_receive(:scram).with(:now).and_raise(RuntimeError)
123
- @heroku_client.should_receive(:maintenance).with('awesomeapp', :off).ordered
124
- expect {
125
- subject.maintenance do reactor.scram(:now) end
126
- }.to raise_error
125
+ with_app(subject, 'name' => subject.app) do |app_data|
126
+ subject.heroku.should_receive(:post_app_maintenance).with(subject.app, '1').ordered
127
+ reactor = mock("Reactor"); reactor.should_receive(:scram).and_raise(RuntimeError)
128
+ subject.heroku.should_receive(:post_app_maintenance).with(subject.app, '0').ordered
129
+
130
+ expect do subject.maintenance {reactor.scram(:now)} end.to raise_error
131
+ end
127
132
  end
128
133
  end
129
134
  end
130
135
 
131
136
  describe "#create" do
137
+ after do
138
+ subject.heroku.delete_app(@app)
139
+ end
140
+ it "uses the provided name" do
141
+ (@app = subject.create).should == 'awesomeapp'
142
+ end
132
143
  it "creates an app on heroku" do
133
- @heroku_client.should_receive(:create).with('awesomeapp', {:stack => 'bamboo-ree-1.8.7'})
134
- subject.create
144
+ subject = HerokuSan::Stage.new('production')
145
+ (@app = subject.create).should =~ /generated-name-\d+/
135
146
  end
136
147
  it "uses the default stack if none is given" do
137
- subject = HerokuSan::Stage.new('production', {"app" => "awesomeapp"})
138
- @heroku_client.should_receive(:create).with('awesomeapp')
139
- subject.create
140
- end
141
- it "sends a nil app name if none is given (Heroku will generate one)" do
142
- subject = HerokuSan::Stage.new('production', {"app" => nil})
143
- @heroku_client.should_receive(:create).with(nil).and_return('warm-ocean-9218')
144
- subject.create.should == 'warm-ocean-9218'
148
+ subject = HerokuSan::Stage.new('production')
149
+ (@app = subject.create).should =~ /generated-name-\d+/
150
+ subject.heroku.get_stack(@app).body.detect{|stack| stack['current']}['name'].should == 'bamboo-mri-1.9.2'
151
+ end
152
+ it "uses the stack from the config" do
153
+ (@app = subject.create).should == 'awesomeapp'
154
+ subject.heroku.get_stack(@app).body.detect{|stack| stack['current']}['name'].should == 'bamboo-ree-1.8.7'
145
155
  end
146
156
  end
147
157
 
@@ -161,15 +171,17 @@ describe HerokuSan::Stage do
161
171
 
162
172
  describe "#long_config" do
163
173
  it "returns the remote config" do
164
- @heroku_client.should_receive(:config_vars).with('awesomeapp') { {'A' => 'one', 'B' => 'two'} }
165
- subject.long_config.should == { 'A' => 'one', 'B' => 'two' }
174
+ with_app(subject, 'name' => subject.app) do |app_data|
175
+ subject.long_config.should == STOCK_CONFIG
176
+ end
166
177
  end
167
178
  end
168
179
 
169
180
  describe "#restart" do
170
181
  it "restarts an app" do
171
- @heroku_client.should_receive(:ps_restart).with('awesomeapp').and_return "restarted"
172
- subject.restart.should == 'restarted'
182
+ with_app(subject, 'name' => subject.app) do |app_data|
183
+ subject.restart.should == 'restarted'
184
+ end
173
185
  end
174
186
  end
175
187
 
@@ -186,13 +198,16 @@ describe HerokuSan::Stage do
186
198
 
187
199
  describe "#push_config" do
188
200
  it "updates the configuration settings on Heroku" do
189
- subject = HerokuSan::Stage.new('test', {"app" => "awesomeapp", "config" => {:FOO => 'bar', :DOG => 'emu'}})
190
- @heroku_client.should_receive(:add_config_vars).with('awesomeapp', {:FOO => 'bar', :DOG => 'emu'}).and_return("{}")
191
- subject.push_config
201
+ subject = HerokuSan::Stage.new('test', {"app" => "awesomeapp", "config" => {:FOO => 'bar', :DOG => 'emu'}})
202
+ with_app(subject, 'name' => subject.app) do |app_data|
203
+ subject.push_config.should == STOCK_CONFIG.merge('FOO' => 'bar', 'DOG' => 'emu')
204
+ end
192
205
  end
193
206
  it "pushes the options hash" do
194
- @heroku_client.should_receive(:add_config_vars).with('awesomeapp', {:RACK_ENV => 'magic'}).and_return("{}")
195
- subject.push_config(:RACK_ENV => 'magic')
207
+ subject = HerokuSan::Stage.new('test', {"app" => "awesomeapp", "config" => {:FOO => 'bar', :DOG => 'emu'}})
208
+ with_app(subject, 'name' => subject.app) do |app_data|
209
+ subject.push_config(:RACK_ENV => 'magic').should == STOCK_CONFIG.merge('RACK_ENV' => 'magic')
210
+ end
196
211
  end
197
212
  end
198
213
 
data/spec/spec_helper.rb CHANGED
@@ -3,6 +3,8 @@ Bundler.setup
3
3
 
4
4
  SPEC_ROOT = File.dirname(__FILE__)
5
5
 
6
+ MOCK = ENV['MOCK'] != 'false'
7
+
6
8
  # Requires supporting ruby files with custom matchers and macros, etc,
7
9
  # in spec/support/ and its subdirectories.
8
10
  Dir[File.join(SPEC_ROOT, "support/**/*.rb")].each {|f| require f}
@@ -0,0 +1,21 @@
1
+ def random_name
2
+ "heroku-rb-#{SecureRandom.hex(10)}"
3
+ end
4
+
5
+ def random_email_address
6
+ "email@#{random_name}.com"
7
+ end
8
+
9
+ def with_app(subject, params={}, &block)
10
+ begin
11
+ data = subject.heroku.post_app(params).body
12
+ @name = data['name']
13
+ ready = false
14
+ until ready
15
+ ready = subject.heroku.request(:method => :put, :path => "/apps/#{@name}/status").status == 201
16
+ end
17
+ yield(data)
18
+ ensure
19
+ subject.heroku.delete_app(@name) rescue nil
20
+ end
21
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: heroku_san
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.3
4
+ version: 2.1.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -12,11 +12,11 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2012-03-31 00:00:00.000000000Z
15
+ date: 2012-04-11 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rails
19
- requirement: &2152371380 !ruby/object:Gem::Requirement
19
+ requirement: !ruby/object:Gem::Requirement
20
20
  none: false
21
21
  requirements:
22
22
  - - ! '>='
@@ -24,10 +24,15 @@ dependencies:
24
24
  version: '2'
25
25
  type: :development
26
26
  prerelease: false
27
- version_requirements: *2152371380
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '2'
28
33
  - !ruby/object:Gem::Dependency
29
34
  name: heroku
30
- requirement: &2152370780 !ruby/object:Gem::Requirement
35
+ requirement: !ruby/object:Gem::Requirement
31
36
  none: false
32
37
  requirements:
33
38
  - - ! '>='
@@ -35,10 +40,31 @@ dependencies:
35
40
  version: '2'
36
41
  type: :runtime
37
42
  prerelease: false
38
- version_requirements: *2152370780
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '2'
49
+ - !ruby/object:Gem::Dependency
50
+ name: heroku-api
51
+ requirement: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: 0.1.2
57
+ type: :runtime
58
+ prerelease: false
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: 0.1.2
39
65
  - !ruby/object:Gem::Dependency
40
66
  name: rake
41
- requirement: &2152370200 !ruby/object:Gem::Requirement
67
+ requirement: !ruby/object:Gem::Requirement
42
68
  none: false
43
69
  requirements:
44
70
  - - ! '>='
@@ -46,10 +72,15 @@ dependencies:
46
72
  version: '0'
47
73
  type: :runtime
48
74
  prerelease: false
49
- version_requirements: *2152370200
75
+ version_requirements: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
50
81
  - !ruby/object:Gem::Dependency
51
82
  name: aruba
52
- requirement: &2152369560 !ruby/object:Gem::Requirement
83
+ requirement: !ruby/object:Gem::Requirement
53
84
  none: false
54
85
  requirements:
55
86
  - - ! '>='
@@ -57,10 +88,15 @@ dependencies:
57
88
  version: '0'
58
89
  type: :development
59
90
  prerelease: false
60
- version_requirements: *2152369560
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
61
97
  - !ruby/object:Gem::Dependency
62
98
  name: cucumber
63
- requirement: &2152369120 !ruby/object:Gem::Requirement
99
+ requirement: !ruby/object:Gem::Requirement
64
100
  none: false
65
101
  requirements:
66
102
  - - ! '>='
@@ -68,10 +104,15 @@ dependencies:
68
104
  version: '0'
69
105
  type: :development
70
106
  prerelease: false
71
- version_requirements: *2152369120
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ! '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
72
113
  - !ruby/object:Gem::Dependency
73
114
  name: rake
74
- requirement: &2152368700 !ruby/object:Gem::Requirement
115
+ requirement: !ruby/object:Gem::Requirement
75
116
  none: false
76
117
  requirements:
77
118
  - - ! '>='
@@ -79,10 +120,15 @@ dependencies:
79
120
  version: '0'
80
121
  type: :development
81
122
  prerelease: false
82
- version_requirements: *2152368700
123
+ version_requirements: !ruby/object:Gem::Requirement
124
+ none: false
125
+ requirements:
126
+ - - ! '>='
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
83
129
  - !ruby/object:Gem::Dependency
84
130
  name: bundler
85
- requirement: &2152368160 !ruby/object:Gem::Requirement
131
+ requirement: !ruby/object:Gem::Requirement
86
132
  none: false
87
133
  requirements:
88
134
  - - ~>
@@ -90,7 +136,12 @@ dependencies:
90
136
  version: '1.1'
91
137
  type: :development
92
138
  prerelease: false
93
- version_requirements: *2152368160
139
+ version_requirements: !ruby/object:Gem::Requirement
140
+ none: false
141
+ requirements:
142
+ - - ~>
143
+ - !ruby/object:Gem::Version
144
+ version: '1.1'
94
145
  description: Manage multiple Heroku instances/apps for a single Rails app using Rake
95
146
  email: elijah.miller@gmail.com
96
147
  executables: []
@@ -133,6 +184,7 @@ files:
133
184
  - spec/heroku_san/project_spec.rb
134
185
  - spec/heroku_san/stage_spec.rb
135
186
  - spec/spec_helper.rb
187
+ - spec/support/heroku.rb
136
188
  homepage: http://github.com/fastestforward/heroku_san
137
189
  licenses: []
138
190
  post_install_message:
@@ -153,7 +205,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
205
  version: '0'
154
206
  requirements: []
155
207
  rubyforge_project:
156
- rubygems_version: 1.8.10
208
+ rubygems_version: 1.8.21
157
209
  signing_key:
158
210
  specification_version: 3
159
211
  summary: A bunch of useful Rake tasks for managing your Heroku apps
@@ -171,3 +223,4 @@ test_files:
171
223
  - spec/heroku_san/project_spec.rb
172
224
  - spec/heroku_san/stage_spec.rb
173
225
  - spec/spec_helper.rb
226
+ - spec/support/heroku.rb