heroku_san 2.1.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Change log (curated)
2
2
 
3
+ ## v2.1.1
4
+ * Bug fixes
5
+ * Changed most Stage methods to call Heroku::Client methods instead of shelling out
6
+ * Finished integration tests
7
+
3
8
  ## v2.1.0
4
9
 
5
10
  * Documentation update
@@ -6,6 +6,7 @@ Feature: Command Line
6
6
  And I overwrite "Gemfile" with:
7
7
  """
8
8
  source :rubygems
9
+ gem 'rails'
9
10
  gem 'heroku_san', :path => '../../../.'
10
11
  """
11
12
 
@@ -28,7 +29,7 @@ Feature: Command Line
28
29
  And the output should contain "staging is shorthand for the Heroku app awesomeapp-staging"
29
30
  And the output should contain "demo is shorthand for the Heroku app awesomeapp-demo"
30
31
 
31
- Scenario: Config file still accepts the heroku_san format
32
+ Scenario: Config file still accepts the old heroku_san format
32
33
  Given a file named "config/heroku.yml" with:
33
34
  """
34
35
  apps:
@@ -1,17 +1,32 @@
1
1
  Feature: Extended config
2
2
 
3
3
  Background:
4
+ Given a directory named "test-config"
5
+ And I cd to "test-config"
6
+ And I run `git init .`
7
+ And a file named "config.yml" with:
8
+ """
9
+ production:
10
+ TEST_REMOTE: 'hello_production'
11
+ staging:
12
+ TEST_REMOTE: 'goodbye_staging'
13
+ """
14
+ And I run `git add .`
15
+ And I run `git commit -m 'Initial commit'`
16
+ And I cd to ".."
4
17
  Given I run `rails new heroku_san_test -O`
5
18
  And I cd to "heroku_san_test"
6
19
  And I overwrite "Gemfile" with:
7
20
  """
8
21
  source :rubygems
22
+ gem 'rails'
9
23
  gem 'heroku_san', :path => '../../../.'
10
24
  """
25
+
11
26
  Scenario: Config information can be pulled from a separate git repository
12
27
  Given a file named "config/heroku.yml" with:
13
28
  """
14
- config_repo: 'file:///<%= File.join(File.expand_path(File.dirname(__FILE__)), '..', '..', '..', 'features', 'data', 'test-config') %>'
29
+ config_repo: 'file:///<%= File.join(File.expand_path(File.dirname(__FILE__)), '..', 'test-config') %>'
15
30
  production:
16
31
  app: awesomeapp
17
32
  staging:
@@ -19,11 +34,10 @@ Feature: Extended config
19
34
  demo:
20
35
  app: awesomeapp-demo
21
36
  """
22
-
23
37
  When I run `rake --trace all heroku:config:list:local`
24
38
 
25
- Then the output should contain "production TEST_REMOTE: 'hello_world'"
26
- And the output should contain "staging TEST_REMOTE: 'goodbye_world'"
39
+ Then the output should contain "TEST_REMOTE: hello_production"
40
+ And the output should contain "TEST_REMOTE: goodbye_staging"
27
41
 
28
42
  Scenario: Config information can be listed
29
43
  Given a file named "config/heroku.yml" with:
@@ -31,38 +45,36 @@ Feature: Extended config
31
45
  production:
32
46
  app: awesomeapp
33
47
  config:
34
- TEST_LOCAL: 'hello_world'
48
+ TEST_LOCAL: 'hello_production'
35
49
  staging:
36
50
  app: awesomeapp-staging
37
51
  config:
38
- TEST_LOCAL: 'goodbye_world'
52
+ TEST_LOCAL: 'goodbye_staging'
39
53
  demo:
40
54
  app: awesomeapp-demo
41
55
  """
42
-
43
56
  When I run `rake --trace all heroku:config:list:local`
44
57
 
45
- Then the output should contain "production TEST_LOCAL: 'hello_world'"
46
- And the output should contain "staging TEST_LOCAL: 'goodbye_world'"
58
+ Then the output should contain "TEST_LOCAL: hello_production"
59
+ And the output should contain "TEST_LOCAL: goodbye_staging"
47
60
 
48
61
  Scenario: Config information can be merged between local and remote
49
62
  Given a file named "config/heroku.yml" with:
50
63
  """
51
- config_repo: 'file:///<%= File.join(File.expand_path(File.dirname(__FILE__)), '..', '..', '..', 'features', 'data', 'test-config') %>'
64
+ config_repo: 'file:///<%= File.join(File.expand_path(File.dirname(__FILE__)), '..', 'test-config') %>'
52
65
  production:
53
66
  app: awesomeapp
54
67
  config:
55
- TEST_LOCAL: 'hello_world'
68
+ TEST_LOCAL: 'hello_production'
56
69
  staging:
57
70
  app: awesomeapp-staging
58
71
  config:
59
- TEST_LOCAL: 'goodbye_world'
72
+ TEST_LOCAL: 'goodbye_staging'
60
73
  TEST_REMOTE: 'overridden_by_remote'
61
74
  """
62
-
63
75
  When I run `rake --trace all heroku:config:list:local`
64
76
 
65
- Then the output should contain "production TEST_LOCAL: 'hello_world'"
66
- And the output should contain "production TEST_REMOTE: 'hello_world'"
67
- And the output should contain "staging TEST_LOCAL: 'goodbye_world'"
68
- And the output should contain "staging TEST_REMOTE: 'goodbye_world'"
77
+ Then the output should contain "TEST_LOCAL: hello_production"
78
+ And the output should contain "TEST_REMOTE: hello_production"
79
+ And the output should contain "TEST_LOCAL: goodbye_staging"
80
+ And the output should contain "TEST_REMOTE: goodbye_staging"
@@ -1,57 +1,30 @@
1
- @announce @slow_process
2
- Feature: Works with Heroku
3
-
4
- Background:
5
- Given I run `git clone git://github.com/kmayer/heroku_san_demo.git`
6
- And I cd to "heroku_san_demo"
7
- And I run `bundle install`
8
-
9
- Scenario: Remote commands
10
- When I run `rake demo deploy`
11
- Then the output should match /(http:.*-demo.heroku.com deployed to Heroku)|(Everything up-to-date)/
12
-
13
- When I run `rake demo heroku:maintenance_on`
14
- Then the output should contain "Maintenance mode enabled."
15
-
16
- When I run `rake demo restart`
17
- Then the output should contain "Restarting processes... done"
18
-
19
- When I run `rake demo heroku:maintenance_off`
20
- Then the output should contain "Maintenance mode disabled."
21
-
22
- When I run `rake demo heroku:rake[db:seed]`
23
- Then I run `curl -s http://heroku-san-demo-demo.heroku.com/droids.text`
24
- And the output should contain "C3PO, Marvin, R2D2, Robby"
1
+ @announce-cmd @slow_process
2
+ Feature: heroku_san can control a project on Heroku
3
+ WARNING: This WILL create apps on Heroku!
4
+ You must login with the heroku cli before starting
5
+ this test; otherwise it will probably hang the first
6
+ time it tries to do anything with Heroku itself.
7
+
8
+ Scenario: Installing on a project
9
+ Given I have a new Rails project
10
+ When I am in the project directory
11
+ And I add heroku_san to the Gemfile
12
+ And I run bundle install
13
+ Then rake reports that the heroku: tasks are available
25
14
 
26
- When I run `rake demo logs`
27
- Then the output should contain "Starting process with command `rake db:seed`"
28
-
29
- When I run `git co staging`
30
- And I run `rake deploy`
31
- Then the output should contain "Defaulting to 'staging' as it matches the current branch"
32
- Then the output should match /(http:.*-staging.heroku.com deployed to Heroku)|(Everything up-to-date)/
33
- When I run `curl -s http://heroku-san-demo-staging.heroku.com`
34
- And the output should contain "Ruby on Rails: Welcome aboard"
35
-
36
- When I run `rake production deploy:force`
37
- Then the output should match /^git update-ref refs.heroku_san.deploy \w{40}$/
38
- # Runs a before_deploy
39
- # Runs an after_deploy
40
- # Adds a collaborator
41
-
42
- # Given I run `rake heroku:create_config`
43
-
44
- # When I run `rake demo heroku:create`
45
- # Then the output should contain "somthing about the created app"
46
- # $ rake all heroku:create
47
- # heroku create heroku-san-demo-demo
48
- # Creating heroku-san-demo-demo.... done, stack is bamboo-mri-1.9.2
49
- # http://heroku-san-demo-demo.heroku.com/ | git@heroku.com:heroku-san-demo-demo.git
50
- # Git remote heroku added
51
- # heroku create heroku-san-demo-production
52
- # Creating heroku-san-demo-production... done, stack is bamboo-mri-1.9.2
53
- # http://heroku-san-demo-production.heroku.com/ | git@heroku.com:heroku-san-demo-production.git
54
- # heroku create heroku-san-demo-staging
55
- # Creating heroku-san-demo-staging... done, stack is bamboo-mri-1.9.2
56
- # http://heroku-san-demo-staging.heroku.com/ | git@heroku.com:heroku-san-demo-staging.git
57
-
15
+ Scenario: Manipulates the project on Heroku
16
+ Given I have a new Rails project
17
+ When I am in the project directory
18
+ And I add heroku_san to the Gemfile
19
+ And I run bundle install
20
+ And I create a new config/heroku.yml file
21
+ And I create my project on Heroku
22
+ And I list the remote configuration
23
+ And I curl the app home page
24
+ And I configure my project
25
+ And I turn maintenance on
26
+ And I deploy my project
27
+ And I turn maintenance off
28
+ And I restart my project
29
+ And I list all apps on Heroku
30
+ Then heroku_san is green
@@ -0,0 +1,123 @@
1
+ World(Aruba::Api)
2
+
3
+ Given /^I have a new Rails project$/ do
4
+ # template = File.join(File.expand_path(File.dirname(__FILE__)), '..', '..', 'features', 'data', 'template.rb')
5
+ cmd = "rails new heroku_san_test --quiet --force --database=postgresql --skip-bundle --skip-javascript --skip-test-unit --skip-sprockets" #" --template #{template}"
6
+ run_simple unescape(cmd)
7
+ end
8
+
9
+ When /^I am in the project directory$/ do
10
+ cd '/heroku_san_test'
11
+ end
12
+
13
+ When /^I add heroku_san to the Gemfile$/ do
14
+ append_to_file 'Gemfile', <<EOT
15
+ group :development, :test do
16
+ gem 'heroku_san', :path => '../../../.'
17
+ end
18
+ EOT
19
+ end
20
+
21
+ When /^I run bundle install$/ do
22
+ use_clean_gemset 'heroku_san_test'
23
+ run_simple 'bundle install --quiet'
24
+ write_file '.rvmrc', "rvm use default@heroku_san_test\n"
25
+ end
26
+
27
+ Then /^rake reports that the heroku: tasks are available$/ do
28
+ run_simple 'rake -T heroku:'
29
+ assert_partial_output 'rake heroku:apps', all_output
30
+ end
31
+
32
+ When /^I create a new config\/heroku\.yml file$/ do
33
+ run_simple 'rake heroku:create_config'
34
+ assert_matching_output %q{Copied example config to ".*.config.heroku.yml"}, all_output
35
+ assert_matching_output %q{Please edit ".*.config.heroku.yml" with your application's settings.}, all_output
36
+ overwrite_file 'config/heroku.yml', <<EOT
37
+ ---
38
+ test_app:
39
+ EOT
40
+ end
41
+
42
+ When /^I create my project on Heroku$/ do
43
+ cmd = 'rake test_app heroku:create'
44
+ run_simple unescape(cmd)
45
+ assert_matching_output %q{test_app: Created ([\w-]+)}, all_output
46
+ output = stdout_from cmd
47
+ @app = output.match(/test_app: Created ([\w-]+)/)[1]
48
+ overwrite_file 'config/heroku.yml', <<EOT
49
+ ---
50
+ test_app:
51
+ app: #{@app}
52
+ EOT
53
+ end
54
+
55
+ When /^I list the remote configuration$/ do
56
+ cmd = 'rake test_app heroku:config:list'
57
+ run_simple unescape(cmd)
58
+ assert_partial_output "APP_NAME: #{@app}", all_output
59
+ assert_partial_output "URL: #{@app}.heroku.com", all_output
60
+ output = stdout_from cmd
61
+ @url = output.match(/\bURL:\s+(.*.heroku.com)\b/)[1]
62
+ @curl = unescape("curl --silent http://#{@url}")
63
+ end
64
+
65
+ When /^I curl the app home page$/ do
66
+ run_simple @curl
67
+ output = stdout_from @curl
68
+ assert_partial_output '<h1><strong>Heroku | Welcome to your new app!</strong></h1>', output
69
+ end
70
+
71
+ When /^I configure my project$/ do
72
+ overwrite_file 'config/heroku.yml', <<EOT
73
+ ---
74
+ test_app:
75
+ app: #{@app}
76
+ config:
77
+ DROIDS: marvin
78
+ EOT
79
+ cmd = 'rake test_app heroku:config'
80
+ run_simple unescape(cmd)
81
+ assert_partial_output 'DROIDS: marvin', all_output
82
+ end
83
+
84
+ When /^I turn maintenance on$/ do
85
+ run_simple 'rake test_app heroku:maintenance_on'
86
+ assert_partial_output 'test_app: Maintenance mode enabled.', all_output
87
+ run_simple @curl
88
+ output = stdout_from @curl
89
+ assert_partial_output '<title>Offline for Maintenance</title>', all_output
90
+ end
91
+
92
+ When /^I turn maintenance off$/ do
93
+ run_simple 'rake test_app heroku:maintenance_off'
94
+ assert_partial_output 'test_app: Maintenance mode disabled.', all_output
95
+ run_simple @curl + "/droids"
96
+ assert_partial_output %Q{<code>marvin</code>}, all_output
97
+ end
98
+
99
+ When /^I restart my project$/ do
100
+ run_simple 'rake test_app heroku:restart'
101
+ assert_partial_output 'test_app: Restarted.', all_output
102
+ end
103
+
104
+ When /^I deploy my project$/ do
105
+ run_simple 'git init .'
106
+ run_simple 'rails generate scaffold droids'
107
+ append_to_file 'app/views/droids/index.html.erb', %Q{\n<div><code><%= ENV['DROIDS'] -%></code></div>\n}
108
+ run_simple 'git add .'
109
+ run_simple 'git commit -m "Initial commit"'
110
+ run_simple 'rake test_app deploy'
111
+ assert_partial_output "http://#{@app}.heroku.com deployed to Heroku", all_output
112
+ end
113
+
114
+ When /^I list all apps on Heroku$/ do
115
+ run_simple 'rake heroku:apps'
116
+ assert_partial_output "test_app is shorthand for the Heroku app #{@app} located at:", all_output
117
+ assert_partial_output "git@heroku.com:#{@app}.git", all_output
118
+ assert_matching_output '@ \w{40} master', all_output
119
+ end
120
+
121
+ Then /^heroku_san is green$/ do
122
+ run_simple "heroku apps:destroy #{@app} --confirm #{@app}"
123
+ end
@@ -12,6 +12,6 @@ Before do
12
12
  end
13
13
 
14
14
  Before('@slow_process') do
15
- @aruba_timeout_seconds = 60
15
+ @aruba_timeout_seconds = 180
16
16
  # @aruba_io_wait_seconds = 15
17
17
  end
data/heroku_san.gemspec CHANGED
@@ -22,13 +22,13 @@ Gem::Specification.new do |s|
22
22
  s.specification_version = 3
23
23
 
24
24
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
25
- s.add_runtime_dependency(%q<rails>, ['>= 2'])
25
+ s.add_development_dependency(%q<rails>, ['>= 2'])
26
26
  s.add_runtime_dependency(%q<heroku>, ['>= 2'])
27
27
  s.add_runtime_dependency(%q<rake>)
28
28
  s.add_development_dependency(%q<aruba>)
29
29
  s.add_development_dependency(%q<cucumber>)
30
30
  s.add_development_dependency(%q<rake>)
31
- s.add_development_dependency(%q<bundler>, ['~> 1.0'])
31
+ s.add_development_dependency(%q<bundler>, ['~> 1.1 '])
32
32
  else
33
33
  s.add_dependency(%q<rails>, ['>= 2'])
34
34
  s.add_dependency(%q<heroku>, ['>= 2'])
@@ -101,6 +101,7 @@ module HerokuSan
101
101
 
102
102
  # make sure each app has a 'config' section & merge w/extra
103
103
  app_settings.keys.each do |name|
104
+ app_settings[name] ||= {}
104
105
  app_settings[name]['config'] ||= {}
105
106
  app_settings[name]['config'].merge!(extra_config[name]) if extra_config[name]
106
107
  end
@@ -1,3 +1,6 @@
1
+ require 'heroku'
2
+ require 'json'
3
+
1
4
  module HerokuSan
2
5
  class Stage
3
6
  attr_reader :name
@@ -8,6 +11,10 @@ module HerokuSan
8
11
  @options = options
9
12
  end
10
13
 
14
+ def heroku
15
+ Heroku::Auth.client
16
+ end
17
+
11
18
  def app
12
19
  @options['app'] or raise MissingApp, "#{name}: is missing the app: configuration value. I don't know what to access on Heroku."
13
20
  end
@@ -17,7 +24,7 @@ module HerokuSan
17
24
  end
18
25
 
19
26
  def stack
20
- @options['stack'] ||= %x"heroku stack --app #{app}".split("\n").select { |b| b =~ /^\* / }.first.gsub(/^\* /, '')
27
+ @options['stack'] ||= heroku.list_stacks(app).detect{|stack| stack['current']}['name']
21
28
  end
22
29
 
23
30
  def tag
@@ -42,47 +49,55 @@ module HerokuSan
42
49
  end
43
50
 
44
51
  def migrate
45
- run 'rake', 'db:migrate'
46
- sh_heroku "restart"
52
+ rake('db:migrate')
53
+ restart
54
+ end
55
+
56
+ def rake(*args)
57
+ run 'rake', args.join(' ')
58
+ # heroku.rake app, args.join(' ')
47
59
  end
48
60
 
49
61
  def maintenance(action = nil)
50
62
  if block_given?
51
- sh_heroku "maintenance:on"
63
+ heroku.maintenance(app, :on)
52
64
  begin
53
65
  yield
54
66
  ensure
55
- sh_heroku "maintenance:off"
67
+ heroku.maintenance(app, :off)
56
68
  end
57
69
  else
58
70
  raise ArgumentError, "Action #{action.inspect} must be one of (:on, :off)", caller if ![:on, :off].include?(action)
59
- sh_heroku "maintenance:#{action}"
71
+ heroku.maintenance(app, action)
60
72
  end
61
73
  end
62
74
 
63
- def create
64
- sh "heroku apps:create #{app}" + (@options['stack'] ? " --stack #{@options['stack']}" : '')
75
+ def create # DEPREC?
76
+ if @options['stack']
77
+ heroku.create(@options['app'], {:stack => @options['stack']})
78
+ else
79
+ heroku.create(@options['app'])
80
+ end
65
81
  end
66
82
 
67
- def sharing_add(email)
83
+ def sharing_add(email) # DEPREC?
68
84
  sh_heroku "sharing:add #{email.chomp}"
69
85
  end
70
86
 
71
- def sharing_remove(email)
87
+ def sharing_remove(email) # DEPREC?
72
88
  sh_heroku "sharing:remove #{email.chomp}"
73
89
  end
74
90
 
75
91
  def long_config
76
- sh_heroku 'config --long'
92
+ heroku.config_vars(app)
77
93
  end
78
94
 
79
- def push_config(options = {})
80
- vars = (options == {} ? config : options).map {|var,value| "#{var}=#{Shellwords.escape(value)}"}.join(' ')
81
- sh_heroku "config:add #{vars}"
95
+ def push_config(options = nil)
96
+ JSON.parse(heroku.add_config_vars(app, options || config))
82
97
  end
83
98
 
84
99
  def restart
85
- sh_heroku 'restart'
100
+ heroku.ps_restart(app)
86
101
  end
87
102
 
88
103
  def logs(tail = false)
@@ -1,3 +1,3 @@
1
1
  module HerokuSan
2
- VERSION = "2.1.0"
2
+ VERSION = "2.1.1"
3
3
  end
data/lib/tasks.rb CHANGED
@@ -20,7 +20,7 @@ namespace :heroku do
20
20
  desc "Creates the Heroku app"
21
21
  task :create do
22
22
  each_heroku_app do |stage|
23
- stage.create
23
+ puts "#{stage.name}: Created #{stage.create}"
24
24
  end
25
25
  end
26
26
 
@@ -82,7 +82,7 @@ namespace :heroku do
82
82
  desc 'Add config:vars to each application.'
83
83
  task :config do
84
84
  each_heroku_app do |stage|
85
- stage.push_config
85
+ puts y(stage.push_config)
86
86
  end
87
87
  end
88
88
 
@@ -91,7 +91,7 @@ namespace :heroku do
91
91
  filename = %Q{#{@heroku_san.config_file.to_s}}
92
92
  if @heroku_san.create_config
93
93
  puts "Copied example config to #{filename.inspect}"
94
- if ENV['EDITOR'].present?
94
+ if ENV['EDITOR'] && ENV['EDITOR'] != ''
95
95
  sh "#{ENV['EDITOR']} #{filename}"
96
96
  else
97
97
  puts "Please edit #{filename.inspect} with your application's settings."
@@ -109,7 +109,7 @@ namespace :heroku do
109
109
  puts command
110
110
  config = Hash[`#{command}`.scan(/^(.+?)\s*=>\s*(.+)$/)]
111
111
  if config['RACK_ENV'] != stage.name
112
- stage.push_config RACK_ENV: stage.name
112
+ puts stage.push_config RACK_ENV: stage.name
113
113
  end
114
114
  end
115
115
  end
@@ -118,7 +118,7 @@ namespace :heroku do
118
118
  task :list do
119
119
  each_heroku_app do |stage|
120
120
  puts "#{stage.name}:"
121
- stage.long_config
121
+ puts y(stage.long_config)
122
122
  end
123
123
  end
124
124
 
@@ -126,9 +126,8 @@ namespace :heroku do
126
126
  desc "Lists local config variables without setting them"
127
127
  task :local do
128
128
  each_heroku_app do |stage|
129
- (stage.config).each do |var, value|
130
- puts "#{stage.name} #{var}: '#{value}'"
131
- end
129
+ puts "#{stage.name}:"
130
+ puts y(stage.config)
132
131
  end
133
132
  end
134
133
  end
@@ -137,7 +136,7 @@ namespace :heroku do
137
136
  desc 'Runs a rake task remotely'
138
137
  task :rake, [:task] do |t, args|
139
138
  each_heroku_app do |stage|
140
- stage.run 'rake', args.task
139
+ puts stage.rake args.task
141
140
  end
142
141
  end
143
142
 
@@ -161,6 +160,7 @@ namespace :heroku do
161
160
  task :maintenance do
162
161
  each_heroku_app do |stage|
163
162
  stage.maintenance :on
163
+ puts "#{stage.name}: Maintenance mode enabled."
164
164
  end
165
165
  end
166
166
 
@@ -168,6 +168,7 @@ namespace :heroku do
168
168
  task :maintenance_on do
169
169
  each_heroku_app do |stage|
170
170
  stage.maintenance :on
171
+ puts "#{stage.name}: Maintenance mode enabled."
171
172
  end
172
173
  end
173
174
 
@@ -175,6 +176,7 @@ namespace :heroku do
175
176
  task :maintenance_off do
176
177
  each_heroku_app do |stage|
177
178
  stage.maintenance :off
179
+ puts "#{stage.name}: Maintenance mode disabled."
178
180
  end
179
181
  end
180
182
 
@@ -227,6 +229,7 @@ namespace :heroku do
227
229
  task :restart do
228
230
  each_heroku_app do |stage|
229
231
  stage.restart
232
+ puts "#{stage.name}: Restarted."
230
233
  end
231
234
  end
232
235
 
@@ -6,7 +6,7 @@ describe HerokuSan::Project do
6
6
  heroku_san = HerokuSan::Project.new("/u/should/never/get/here")
7
7
  heroku_san.all.should == []
8
8
  end
9
-
9
+
10
10
  context "using the example config file" do
11
11
  let(:heroku_config_file) { File.join(SPEC_ROOT, "fixtures", "example.yml") }
12
12
  let(:template_config_file) {
@@ -14,10 +14,9 @@ describe HerokuSan::Project do
14
14
  (File.respond_to? :realpath) ? File.realpath(path) : path
15
15
  }
16
16
  let(:heroku_san) { HerokuSan::Project.new(heroku_config_file) }
17
-
18
- it "#all" do
19
- heroku_san.all.should =~ %w[production staging demo]
20
- end
17
+ subject { heroku_san }
18
+
19
+ its(:all) { should =~ %w[production staging demo] }
21
20
 
22
21
  context "using the heroku_san format" do
23
22
  let(:heroku_san) { HerokuSan::Project.new(File.join(SPEC_ROOT, "fixtures", "old_format.yml")) }
@@ -1,9 +1,15 @@
1
1
  require 'spec_helper'
2
+ require 'heroku/client'
2
3
 
3
4
  describe HerokuSan::Stage do
4
5
  include Git
5
6
  subject { HerokuSan::Stage.new('production', {"app" => "awesomeapp", "stack" => "bamboo-ree-1.8.7"})}
6
7
 
8
+ before do
9
+ @heroku_client = mock(Heroku::Client)
10
+ Heroku::Auth.stub(:client).and_return(@heroku_client)
11
+ end
12
+
7
13
  context "initializes" do
8
14
  subject { HerokuSan::Stage.new('production',
9
15
  {"stack" => "cedar",
@@ -30,38 +36,29 @@ describe HerokuSan::Stage do
30
36
  end
31
37
  end
32
38
 
33
- context "celadon cedar stack has a different API" do
34
- describe "#stack" do
35
- it "returns the name of the stack from Heroku" do
36
- subject = HerokuSan::Stage.new('production', {"app" => "awesomeapp"})
37
- subject.should_receive("`").with("heroku stack --app awesomeapp") {
38
- <<EOT
39
- aspen-mri-1.8.6
40
- * bamboo-mri-1.9.2
41
- bamboo-ree-1.8.7
42
- cedar (beta)
43
- EOT
44
- }
45
- subject.stack.should == 'bamboo-mri-1.9.2'
46
- end
47
-
48
- it "returns the stack name from the config if it is set there" do
49
- subject = HerokuSan::Stage.new('production', {"app" => "awesomeapp", "stack" => "cedar"})
50
- subject.should_not_receive("`")
51
- subject.stack.should == 'cedar'
52
- end
39
+ describe "#stack" do
40
+ it "returns the name of the stack from Heroku" do
41
+ 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'
53
45
  end
54
-
55
- describe "#run" do
56
- it "runs commands using the pre-cedar format" do
57
- subject.should_receive(:sh).with("heroku run:rake foo bar bleh --app awesomeapp")
58
- subject.run 'rake', 'foo bar bleh'
59
- end
60
- it "runs commands using the new cedar format" do
61
- subject = HerokuSan::Stage.new('production', {"app" => "awesomeapp", "stack" => "cedar"})
62
- subject.should_receive(:sh).with("heroku run worker foo bar bleh --app awesomeapp")
63
- subject.run 'worker', 'foo bar bleh'
64
- end
46
+
47
+ it "returns the stack name from the config if it is set there" do
48
+ subject = HerokuSan::Stage.new('production', {"app" => "awesomeapp", "stack" => "cedar"})
49
+ subject.stack.should == 'cedar'
50
+ end
51
+ end
52
+
53
+ describe "#run" do
54
+ it "runs commands using the pre-cedar format" do
55
+ subject.should_receive(:sh).with("heroku run:rake foo bar bleh --app awesomeapp")
56
+ subject.run 'rake', 'foo bar bleh'
57
+ end
58
+ it "runs commands using the new cedar format" do
59
+ subject = HerokuSan::Stage.new('production', {"app" => "awesomeapp", "stack" => "cedar"})
60
+ subject.should_receive(:sh).with("heroku run worker foo bar bleh --app awesomeapp")
61
+ subject.run 'worker', 'foo bar bleh'
65
62
  end
66
63
  end
67
64
 
@@ -89,21 +86,22 @@ EOT
89
86
 
90
87
  describe "#migrate" do
91
88
  it "runs rake db:migrate" do
92
- subject.should_receive(:sh).with("heroku run:rake db:migrate --app awesomeapp")
93
- subject.should_receive(:sh).with("heroku restart --app awesomeapp")
94
- subject.migrate
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"
95
93
  end
96
94
  end
97
95
 
98
96
  describe "#maintenance" do
99
97
  it ":on" do
100
- subject.should_receive(:sh).with("heroku maintenance:on --app awesomeapp")
101
- subject.maintenance :on
98
+ @heroku_client.should_receive(:maintenance).with('awesomeapp', :on) {'on'}
99
+ subject.maintenance(:on).should == 'on'
102
100
  end
103
101
 
104
102
  it ":off" do
105
- subject.should_receive(:sh).with("heroku maintenance:off --app awesomeapp")
106
- subject.maintenance :off
103
+ @heroku_client.should_receive(:maintenance).with('awesomeapp', :off) {'off'}
104
+ subject.maintenance(:off).should == 'off'
107
105
  end
108
106
 
109
107
  it "otherwise raises an ArgumentError" do
@@ -114,21 +112,17 @@ EOT
114
112
 
115
113
  context "with a block" do
116
114
  it "wraps it in a maitenance mode" do
117
- subject.should_receive(:sh).with("heroku maintenance:on --app awesomeapp")
118
- reactor = mock("Reactor"); reactor.should_receive(:scram).with(:now)
119
- subject.should_receive(:sh).with("heroku maintenance:off --app awesomeapp")
120
- subject.maintenance do
121
- reactor.scram(:now)
122
- end
115
+ reactor = mock("Reactor"); reactor.should_receive(:scram).with(:now).ordered
116
+ @heroku_client.should_receive(:maintenance).with('awesomeapp', :on).ordered
117
+ @heroku_client.should_receive(:maintenance).with('awesomeapp', :off).ordered
118
+ subject.maintenance do reactor.scram(:now) end
123
119
  end
124
120
  it "ensures that maintenance mode is turned off" do
125
- subject.should_receive(:sh).with("heroku maintenance:on --app awesomeapp")
121
+ @heroku_client.should_receive(:maintenance).with('awesomeapp', :on).ordered
126
122
  reactor = mock("Reactor"); reactor.should_receive(:scram).with(:now).and_raise(RuntimeError)
127
- subject.should_receive(:sh).with("heroku maintenance:off --app awesomeapp")
123
+ @heroku_client.should_receive(:maintenance).with('awesomeapp', :off).ordered
128
124
  expect {
129
- subject.maintenance do
130
- reactor.scram(:now)
131
- end
125
+ subject.maintenance do reactor.scram(:now) end
132
126
  }.to raise_error
133
127
  end
134
128
  end
@@ -136,14 +130,19 @@ EOT
136
130
 
137
131
  describe "#create" do
138
132
  it "creates an app on heroku" do
139
- subject.should_receive(:sh).with("heroku apps:create awesomeapp --stack bamboo-ree-1.8.7")
133
+ @heroku_client.should_receive(:create).with('awesomeapp', {:stack => 'bamboo-ree-1.8.7'})
140
134
  subject.create
141
135
  end
142
136
  it "uses the default stack if none is given" do
143
137
  subject = HerokuSan::Stage.new('production', {"app" => "awesomeapp"})
144
- subject.should_receive(:sh).with("heroku apps:create awesomeapp")
138
+ @heroku_client.should_receive(:create).with('awesomeapp')
145
139
  subject.create
146
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'
145
+ end
147
146
  end
148
147
 
149
148
  describe "#sharing_add" do
@@ -161,24 +160,16 @@ EOT
161
160
  end
162
161
 
163
162
  describe "#long_config" do
164
- it "prints out the remote config" do
165
- subject.should_receive(:sh).with("heroku config --long --app awesomeapp") {
166
- <<EOT
167
- BUNDLE_WITHOUT => development:test
168
- DATABASE_URL => postgres://thnodhxrzn:T0-UwxLyFgXcnBSHmyhv@ec2-50-19-216-194.compute-1.amazonaws.com/thnodhxrzn
169
- LANG => en_US.UTF-8
170
- RACK_ENV => production
171
- SHARED_DATABASE_URL => postgres://thnodhxrzn:T0-UwxLyFgXcnBSHmyhv@ec2-50-19-216-194.compute-1.amazonaws.com/thnodhxrzn
172
- EOT
173
- }
174
- subject.long_config
163
+ 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' }
175
166
  end
176
167
  end
177
168
 
178
169
  describe "#restart" do
179
170
  it "restarts an app" do
180
- subject.should_receive(:sh).with("heroku restart --app awesomeapp")
181
- subject.restart
171
+ @heroku_client.should_receive(:ps_restart).with('awesomeapp').and_return "restarted"
172
+ subject.restart.should == 'restarted'
182
173
  end
183
174
  end
184
175
 
@@ -196,16 +187,11 @@ EOT
196
187
  describe "#push_config" do
197
188
  it "updates the configuration settings on Heroku" do
198
189
  subject = HerokuSan::Stage.new('test', {"app" => "awesomeapp", "config" => {FOO: 'bar', DOG: 'emu'}})
199
- subject.should_receive(:sh).with("heroku config:add FOO=bar DOG=emu --app awesomeapp")
200
- subject.push_config
201
- end
202
- it "properly escapes variables" do
203
- subject = HerokuSan::Stage.new('test', {"app" => "awesomeapp", "config" => {FOO: ' bar\emu bat zebra '}})
204
- subject.should_receive(:sh).with("heroku config:add FOO=#{Shellwords.escape(' bar\emu bat zebra ')} --app awesomeapp")
190
+ @heroku_client.should_receive(:add_config_vars).with('awesomeapp', {:FOO => 'bar', :DOG => 'emu'}).and_return("{}")
205
191
  subject.push_config
206
192
  end
207
193
  it "pushes the options hash" do
208
- subject.should_receive(:sh).with("heroku config:add RACK_ENV=magic --app awesomeapp")
194
+ @heroku_client.should_receive(:add_config_vars).with('awesomeapp', {:RACK_ENV => 'magic'}).and_return("{}")
209
195
  subject.push_config(RACK_ENV: 'magic')
210
196
  end
211
197
  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.0
4
+ version: 2.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -12,22 +12,22 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2012-03-06 00:00:00.000000000Z
15
+ date: 2012-03-21 00:00:00.000000000Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rails
19
- requirement: &2153413220 !ruby/object:Gem::Requirement
19
+ requirement: &2156274700 !ruby/object:Gem::Requirement
20
20
  none: false
21
21
  requirements:
22
22
  - - ! '>='
23
23
  - !ruby/object:Gem::Version
24
24
  version: '2'
25
- type: :runtime
25
+ type: :development
26
26
  prerelease: false
27
- version_requirements: *2153413220
27
+ version_requirements: *2156274700
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: heroku
30
- requirement: &2153412680 !ruby/object:Gem::Requirement
30
+ requirement: &2156273500 !ruby/object:Gem::Requirement
31
31
  none: false
32
32
  requirements:
33
33
  - - ! '>='
@@ -35,10 +35,10 @@ dependencies:
35
35
  version: '2'
36
36
  type: :runtime
37
37
  prerelease: false
38
- version_requirements: *2153412680
38
+ version_requirements: *2156273500
39
39
  - !ruby/object:Gem::Dependency
40
40
  name: rake
41
- requirement: &2153412280 !ruby/object:Gem::Requirement
41
+ requirement: &2156272240 !ruby/object:Gem::Requirement
42
42
  none: false
43
43
  requirements:
44
44
  - - ! '>='
@@ -46,10 +46,10 @@ dependencies:
46
46
  version: '0'
47
47
  type: :runtime
48
48
  prerelease: false
49
- version_requirements: *2153412280
49
+ version_requirements: *2156272240
50
50
  - !ruby/object:Gem::Dependency
51
51
  name: aruba
52
- requirement: &2153411640 !ruby/object:Gem::Requirement
52
+ requirement: &2156270800 !ruby/object:Gem::Requirement
53
53
  none: false
54
54
  requirements:
55
55
  - - ! '>='
@@ -57,10 +57,10 @@ dependencies:
57
57
  version: '0'
58
58
  type: :development
59
59
  prerelease: false
60
- version_requirements: *2153411640
60
+ version_requirements: *2156270800
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: cucumber
63
- requirement: &2153411060 !ruby/object:Gem::Requirement
63
+ requirement: &2156269420 !ruby/object:Gem::Requirement
64
64
  none: false
65
65
  requirements:
66
66
  - - ! '>='
@@ -68,10 +68,10 @@ dependencies:
68
68
  version: '0'
69
69
  type: :development
70
70
  prerelease: false
71
- version_requirements: *2153411060
71
+ version_requirements: *2156269420
72
72
  - !ruby/object:Gem::Dependency
73
73
  name: rake
74
- requirement: &2153410400 !ruby/object:Gem::Requirement
74
+ requirement: &2156268140 !ruby/object:Gem::Requirement
75
75
  none: false
76
76
  requirements:
77
77
  - - ! '>='
@@ -79,18 +79,18 @@ dependencies:
79
79
  version: '0'
80
80
  type: :development
81
81
  prerelease: false
82
- version_requirements: *2153410400
82
+ version_requirements: *2156268140
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: bundler
85
- requirement: &2153409500 !ruby/object:Gem::Requirement
85
+ requirement: &2156263700 !ruby/object:Gem::Requirement
86
86
  none: false
87
87
  requirements:
88
88
  - - ~>
89
89
  - !ruby/object:Gem::Version
90
- version: '1.0'
90
+ version: '1.1'
91
91
  type: :development
92
92
  prerelease: false
93
- version_requirements: *2153409500
93
+ version_requirements: *2156263700
94
94
  description: Manage multiple Heroku instances/apps for a single Rails app using Rake
95
95
  email: elijah.miller@gmail.com
96
96
  executables: []
@@ -99,7 +99,6 @@ extra_rdoc_files:
99
99
  - README.rdoc
100
100
  files:
101
101
  - .gitignore
102
- - .gitmodules
103
102
  - .rvmrc
104
103
  - CHANGELOG.md
105
104
  - Gemfile
@@ -113,6 +112,7 @@ files:
113
112
  - features/config.feature
114
113
  - features/extended-config.feature
115
114
  - features/remote.feature
115
+ - features/step_definitions/remote_steps.rb
116
116
  - features/support/env.rb
117
117
  - heroku_san.gemspec
118
118
  - lib/git.rb
@@ -160,6 +160,7 @@ test_files:
160
160
  - features/config.feature
161
161
  - features/extended-config.feature
162
162
  - features/remote.feature
163
+ - features/step_definitions/remote_steps.rb
163
164
  - features/support/env.rb
164
165
  - spec/fixtures/example.yml
165
166
  - spec/fixtures/extended_config.yml
data/.gitmodules DELETED
@@ -1,3 +0,0 @@
1
- [submodule "features/data/test-config"]
2
- path = features/data/test-config
3
- url = git://github.com/rahearn/test-credentials.git