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 +5 -0
- data/features/config.feature +2 -1
- data/features/extended-config.feature +29 -17
- data/features/remote.feature +29 -56
- data/features/step_definitions/remote_steps.rb +123 -0
- data/features/support/env.rb +1 -1
- data/heroku_san.gemspec +2 -2
- data/lib/heroku_san/project.rb +1 -0
- data/lib/heroku_san/stage.rb +30 -15
- data/lib/heroku_san/version.rb +1 -1
- data/lib/tasks.rb +12 -9
- data/spec/heroku_san/project_spec.rb +4 -5
- data/spec/heroku_san/stage_spec.rb +57 -71
- metadata +20 -19
- data/.gitmodules +0 -3
data/CHANGELOG.md
CHANGED
data/features/config.feature
CHANGED
@@ -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__)), '..', '
|
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 "
|
26
|
-
And the output should contain "
|
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: '
|
48
|
+
TEST_LOCAL: 'hello_production'
|
35
49
|
staging:
|
36
50
|
app: awesomeapp-staging
|
37
51
|
config:
|
38
|
-
TEST_LOCAL: '
|
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 "
|
46
|
-
And the output should contain "
|
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__)), '..', '
|
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: '
|
68
|
+
TEST_LOCAL: 'hello_production'
|
56
69
|
staging:
|
57
70
|
app: awesomeapp-staging
|
58
71
|
config:
|
59
|
-
TEST_LOCAL: '
|
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 "
|
66
|
-
And the output should contain "
|
67
|
-
And the output should contain "
|
68
|
-
And the output should contain "
|
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"
|
data/features/remote.feature
CHANGED
@@ -1,57 +1,30 @@
|
|
1
|
-
@announce @slow_process
|
2
|
-
Feature:
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
When I
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
And I run
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
And
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
data/features/support/env.rb
CHANGED
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.
|
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.
|
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'])
|
data/lib/heroku_san/project.rb
CHANGED
@@ -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
|
data/lib/heroku_san/stage.rb
CHANGED
@@ -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'] ||=
|
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
|
-
|
46
|
-
|
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
|
-
|
63
|
+
heroku.maintenance(app, :on)
|
52
64
|
begin
|
53
65
|
yield
|
54
66
|
ensure
|
55
|
-
|
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
|
-
|
71
|
+
heroku.maintenance(app, action)
|
60
72
|
end
|
61
73
|
end
|
62
74
|
|
63
|
-
def create
|
64
|
-
|
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
|
-
|
92
|
+
heroku.config_vars(app)
|
77
93
|
end
|
78
94
|
|
79
|
-
def push_config(options =
|
80
|
-
|
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
|
-
|
100
|
+
heroku.ps_restart(app)
|
86
101
|
end
|
87
102
|
|
88
103
|
def logs(tail = false)
|
data/lib/heroku_san/version.rb
CHANGED
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']
|
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
|
-
|
130
|
-
|
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.
|
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
|
-
|
19
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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(:
|
93
|
-
|
94
|
-
|
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
|
-
|
101
|
-
subject.maintenance
|
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
|
-
|
106
|
-
subject.maintenance
|
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
|
-
|
118
|
-
|
119
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 "
|
165
|
-
|
166
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
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-
|
15
|
+
date: 2012-03-21 00:00:00.000000000Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: rails
|
19
|
-
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: :
|
25
|
+
type: :development
|
26
26
|
prerelease: false
|
27
|
-
version_requirements: *
|
27
|
+
version_requirements: *2156274700
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: heroku
|
30
|
-
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: *
|
38
|
+
version_requirements: *2156273500
|
39
39
|
- !ruby/object:Gem::Dependency
|
40
40
|
name: rake
|
41
|
-
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: *
|
49
|
+
version_requirements: *2156272240
|
50
50
|
- !ruby/object:Gem::Dependency
|
51
51
|
name: aruba
|
52
|
-
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: *
|
60
|
+
version_requirements: *2156270800
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: cucumber
|
63
|
-
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: *
|
71
|
+
version_requirements: *2156269420
|
72
72
|
- !ruby/object:Gem::Dependency
|
73
73
|
name: rake
|
74
|
-
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: *
|
82
|
+
version_requirements: *2156268140
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: bundler
|
85
|
-
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.
|
90
|
+
version: '1.1'
|
91
91
|
type: :development
|
92
92
|
prerelease: false
|
93
|
-
version_requirements: *
|
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