Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Use heroku-api for client calls

  • Loading branch information...
commit 54718936f11dbd43d17ed13ff49b62675c608ea6 1 parent 2a303c6
@kmayer kmayer authored
View
2  Gemfile
@@ -1,4 +1,4 @@
source :rubygems
# Specify dependencies in heroku_san.gemspec
-gemspec
+gemspec
View
2  features/step_definitions/remote_steps.rb
@@ -112,7 +112,7 @@
When /^I deploy my project$/ do
run_simple 'git init .'
- run_simple 'rails generate scaffold droids'
+ run_simple 'rails generate scaffold droid'
append_to_file 'app/views/droids/index.html.erb', %Q{\n<div><code><%= ENV['DROIDS'] -%></code></div>\n}
run_simple 'git add .'
run_simple 'git commit -m "Initial commit"'
View
3  heroku_san.gemspec
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
s.add_development_dependency(%q<rails>, ['>= 2'])
s.add_runtime_dependency(%q<heroku>, ['>= 2'])
+ s.add_runtime_dependency(%q<heroku-api>, ['>= 0.1.2'])
s.add_runtime_dependency(%q<rake>)
s.add_development_dependency(%q<aruba>)
s.add_development_dependency(%q<cucumber>)
@@ -32,12 +33,14 @@ Gem::Specification.new do |s|
else
s.add_dependency(%q<rails>, ['>= 2'])
s.add_dependency(%q<heroku>, ['>= 2'])
+ s.add_dependency(%q<heroku-api>, ['>= 0.1.2'])
s.add_dependency(%q<aruba>)
s.add_dependency(%q<cucumber>)
end
else
s.add_dependency(%q<rails>, ['>= 2'])
s.add_dependency(%q<heroku>, ['>= 2'])
+ s.add_dependency(%q<heroku-api>, ['>= 0.1.2'])
s.add_dependency(%q<aruba>)
s.add_dependency(%q<cucumber>)
end
View
45 lib/heroku_san/stage.rb
@@ -1,6 +1,9 @@
require 'heroku'
+require 'heroku/api'
require 'json'
+MOCK = false unless defined?(MOCK)
+
module HerokuSan
class Stage
attr_reader :name
@@ -12,7 +15,7 @@ def initialize(stage, options = {})
end
def heroku
- Heroku::Auth.client
+ @heroku ||= Heroku::API.new(:api_key => ENV['HEROKU_API_KEY'] || Heroku::Auth.api_key, :mock => MOCK)
end
def app
@@ -24,7 +27,7 @@ def repo
end
def stack
- @options['stack'] ||= heroku.list_stacks(app).detect{|stack| stack['current']}['name']
+ @options['stack'] ||= heroku.get_stack(app).body.detect{|stack| stack['current']}['name']
end
def tag
@@ -60,24 +63,23 @@ def rake(*args)
def maintenance(action = nil)
if block_given?
- heroku.maintenance(app, :on)
+ heroku.post_app_maintenance(app, '1')
begin
yield
ensure
- heroku.maintenance(app, :off)
+ heroku.post_app_maintenance(app, '0')
end
else
raise ArgumentError, "Action #{action.inspect} must be one of (:on, :off)", caller if ![:on, :off].include?(action)
- heroku.maintenance(app, action)
+ heroku.post_app_maintenance(app, {:on => '1', :off => '0'}[action])
end
end
def create # DEPREC?
- if @options['stack']
- heroku.create(@options['app'], {:stack => @options['stack']})
- else
- heroku.create(@options['app'])
- end
+ params = @options.select{|k,v| %w[app stack].include? k}.stringify_keys
+ params['name'] = params.delete('app')
+ response = heroku.post_app(params)
+ response.body['name']
end
def sharing_add(email) # DEPREC?
@@ -89,15 +91,16 @@ def sharing_remove(email) # DEPREC?
end
def long_config
- heroku.config_vars(app)
+ heroku.get_config_vars(app).body
end
def push_config(options = nil)
- JSON.parse(heroku.add_config_vars(app, options || config))
+ params = (options || config).stringify_keys
+ heroku.put_config_vars(app, params).body
end
def restart
- heroku.ps_restart(app)
+ "restarted" if heroku.post_ps_restart(app).body == 'ok'
end
def logs(tail = false)
@@ -114,4 +117,20 @@ def sh_heroku(command)
sh "heroku #{command} --app #{app}"
end
end
+end
+
+# from ActiveSupport
+class Hash
+ # Return a new hash with all keys converted to strings.
+ def stringify_keys
+ dup.stringify_keys!
+ end
+
+ # Destructively convert all keys to strings.
+ def stringify_keys!
+ keys.each do |key|
+ self[key.to_s] = delete(key)
+ end
+ self
+ end
end
View
101 spec/heroku_san/stage_spec.rb
@@ -4,10 +4,9 @@
describe HerokuSan::Stage do
include Git
subject { HerokuSan::Stage.new('production', {"app" => "awesomeapp", "stack" => "bamboo-ree-1.8.7"})}
-
+ STOCK_CONFIG = {"BUNDLE_WITHOUT"=>"development:test", "LANG"=>"en_US.UTF-8", "RACK_ENV"=>"production"}
before do
- @heroku_client = mock(Heroku::Client)
- Heroku::Auth.stub(:client).and_return(@heroku_client)
+ Heroku::Auth.stub(:api_key) { 'API_KEY' }
end
context "initializes" do
@@ -39,9 +38,9 @@
describe "#stack" do
it "returns the name of the stack from Heroku" do
subject = HerokuSan::Stage.new('production', {"app" => "awesomeapp"})
- @heroku_client.should_receive(:list_stacks).with('awesomeapp').
- and_return { [{'name' => 'other'}, {'name' => 'the-one', 'current' => true}] }
- subject.stack.should == 'the-one'
+ with_app(subject, 'name' => 'awesomeapp') do |app_data|
+ subject.stack.should == 'bamboo-mri-1.9.2'
+ end
end
it "returns the stack name from the config if it is set there" do
@@ -86,22 +85,24 @@
describe "#migrate" do
it "runs rake db:migrate" do
- subject.should_receive(:rake).with('db:migrate').and_return 'output:'
- # @heroku_client.should_receive(:rake).with('awesomeapp', 'db:migrate').and_return "output:"
- @heroku_client.should_receive(:ps_restart).with('awesomeapp').and_return "restarted"
- subject.migrate.should == "restarted"
+ with_app(subject, 'name' => subject.app) do |app_data|
+ subject.should_receive(:rake).with('db:migrate').and_return 'output:'
+ subject.migrate.should == "restarted"
+ end
end
end
describe "#maintenance" do
it ":on" do
- @heroku_client.should_receive(:maintenance).with('awesomeapp', :on) {'on'}
- subject.maintenance(:on).should == 'on'
+ with_app(subject, 'name' => subject.app )do |app_data|
+ subject.maintenance(:on).status.should == 200
+ end
end
it ":off" do
- @heroku_client.should_receive(:maintenance).with('awesomeapp', :off) {'off'}
- subject.maintenance(:off).should == 'off'
+ with_app(subject, 'name' => subject.app) do |app_data|
+ subject.maintenance(:off).status.should.should == 200
+ end
end
it "otherwise raises an ArgumentError" do
@@ -112,36 +113,45 @@
context "with a block" do
it "wraps it in a maitenance mode" do
- @heroku_client.should_receive(:maintenance).with('awesomeapp', :on).ordered
- reactor = mock("Reactor"); reactor.should_receive(:scram).with(:now).ordered
- @heroku_client.should_receive(:maintenance).with('awesomeapp', :off).ordered
- subject.maintenance do reactor.scram(:now) end
+ with_app(subject, 'name' => subject.app) do |app_data|
+ subject.heroku.should_receive(:post_app_maintenance).with(subject.app, '1').ordered
+ reactor = mock("Reactor"); reactor.should_receive(:scram).with(:now).ordered
+ subject.heroku.should_receive(:post_app_maintenance).with(subject.app, '0').ordered
+
+ subject.maintenance {reactor.scram(:now)}
+ end
end
it "ensures that maintenance mode is turned off" do
- @heroku_client.should_receive(:maintenance).with('awesomeapp', :on).ordered
- reactor = mock("Reactor"); reactor.should_receive(:scram).with(:now).and_raise(RuntimeError)
- @heroku_client.should_receive(:maintenance).with('awesomeapp', :off).ordered
- expect {
- subject.maintenance do reactor.scram(:now) end
- }.to raise_error
+ with_app(subject, 'name' => subject.app) do |app_data|
+ subject.heroku.should_receive(:post_app_maintenance).with(subject.app, '1').ordered
+ reactor = mock("Reactor"); reactor.should_receive(:scram).and_raise(RuntimeError)
+ subject.heroku.should_receive(:post_app_maintenance).with(subject.app, '0').ordered
+
+ expect do subject.maintenance {reactor.scram(:now)} end.to raise_error
+ end
end
end
end
describe "#create" do
+ after do
+ subject.heroku.delete_app(@app)
+ end
+ it "uses the provided name" do
+ (@app = subject.create).should == 'awesomeapp'
+ end
it "creates an app on heroku" do
- @heroku_client.should_receive(:create).with('awesomeapp', {:stack => 'bamboo-ree-1.8.7'})
- subject.create
+ subject = HerokuSan::Stage.new('production')
+ (@app = subject.create).should =~ /generated-name-\d+/
end
it "uses the default stack if none is given" do
- subject = HerokuSan::Stage.new('production', {"app" => "awesomeapp"})
- @heroku_client.should_receive(:create).with('awesomeapp')
- subject.create
- end
- it "sends a nil app name if none is given (Heroku will generate one)" do
- subject = HerokuSan::Stage.new('production', {"app" => nil})
- @heroku_client.should_receive(:create).with(nil).and_return('warm-ocean-9218')
- subject.create.should == 'warm-ocean-9218'
+ subject = HerokuSan::Stage.new('production')
+ (@app = subject.create).should =~ /generated-name-\d+/
+ subject.heroku.get_stack(@app).body.detect{|stack| stack['current']}['name'].should == 'bamboo-mri-1.9.2'
+ end
+ it "uses the stack from the config" do
+ (@app = subject.create).should == 'awesomeapp'
+ subject.heroku.get_stack(@app).body.detect{|stack| stack['current']}['name'].should == 'bamboo-ree-1.8.7'
end
end
@@ -161,15 +171,17 @@
describe "#long_config" do
it "returns the remote config" do
- @heroku_client.should_receive(:config_vars).with('awesomeapp') { {'A' => 'one', 'B' => 'two'} }
- subject.long_config.should == { 'A' => 'one', 'B' => 'two' }
+ with_app(subject, 'name' => subject.app) do |app_data|
+ subject.long_config.should == STOCK_CONFIG
+ end
end
end
describe "#restart" do
it "restarts an app" do
- @heroku_client.should_receive(:ps_restart).with('awesomeapp').and_return "restarted"
- subject.restart.should == 'restarted'
+ with_app(subject, 'name' => subject.app) do |app_data|
+ subject.restart.should == 'restarted'
+ end
end
end
@@ -186,13 +198,16 @@
describe "#push_config" do
it "updates the configuration settings on Heroku" do
- subject = HerokuSan::Stage.new('test', {"app" => "awesomeapp", "config" => {:FOO => 'bar', :DOG => 'emu'}})
- @heroku_client.should_receive(:add_config_vars).with('awesomeapp', {:FOO => 'bar', :DOG => 'emu'}).and_return("{}")
- subject.push_config
+ subject = HerokuSan::Stage.new('test', {"app" => "awesomeapp", "config" => {:FOO => 'bar', :DOG => 'emu'}})
+ with_app(subject, 'name' => subject.app) do |app_data|
+ subject.push_config.should == STOCK_CONFIG.merge('FOO' => 'bar', 'DOG' => 'emu')
+ end
end
it "pushes the options hash" do
- @heroku_client.should_receive(:add_config_vars).with('awesomeapp', {:RACK_ENV => 'magic'}).and_return("{}")
- subject.push_config(:RACK_ENV => 'magic')
+ subject = HerokuSan::Stage.new('test', {"app" => "awesomeapp", "config" => {:FOO => 'bar', :DOG => 'emu'}})
+ with_app(subject, 'name' => subject.app) do |app_data|
+ subject.push_config(:RACK_ENV => 'magic').should == STOCK_CONFIG.merge('RACK_ENV' => 'magic')
+ end
end
end
View
2  spec/spec_helper.rb
@@ -3,6 +3,8 @@
SPEC_ROOT = File.dirname(__FILE__)
+MOCK = ENV['MOCK'] != 'false'
+
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[File.join(SPEC_ROOT, "support/**/*.rb")].each {|f| require f}
View
21 spec/support/heroku.rb
@@ -0,0 +1,21 @@
+def random_name
+ "heroku-rb-#{SecureRandom.hex(10)}"
+end
+
+def random_email_address
+ "email@#{random_name}.com"
+end
+
+def with_app(subject, params={}, &block)
+ begin
+ data = subject.heroku.post_app(params).body
+ @name = data['name']
+ ready = false
+ until ready
+ ready = subject.heroku.request(:method => :put, :path => "/apps/#{@name}/status").status == 201
+ end
+ yield(data)
+ ensure
+ subject.heroku.delete_app(@name) rescue nil
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.