heroku_san 2.1.3 → 2.1.4

Sign up to get free protection for your applications and to get access to all the features.
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