heroku_san 2.1.0 → 2.1.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.
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