heroku_san 4.3.0 → 4.3.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/.travis.yml +16 -1
- data/Gemfile +16 -10
- data/Rakefile +17 -0
- data/features/remote.feature +1 -1
- data/features/shell_execution.feature +47 -0
- data/features/step_definitions/remote_steps.rb +13 -4
- data/heroku_san.gemspec +3 -18
- data/lib/heroku_san/api.rb +30 -2
- data/lib/heroku_san/configuration.rb +4 -2
- data/lib/heroku_san/stage.rb +5 -30
- data/lib/heroku_san/version.rb +1 -1
- data/spec/heroku_san/api_spec.rb +2 -2
- data/spec/heroku_san/application_spec.rb +2 -2
- data/spec/heroku_san/configuration_spec.rb +3 -3
- data/spec/heroku_san/deploy/base_spec.rb +1 -1
- data/spec/heroku_san/deploy/rails_spec.rb +1 -1
- data/spec/heroku_san/parser_spec.rb +4 -4
- data/spec/heroku_san/project_spec.rb +1 -1
- data/spec/heroku_san/stage_spec.rb +22 -21
- data/spec/spec_helper.rb +0 -2
- data/spec/support/factory.rb +14 -0
- data/spec/support/travis-key-cleanup.sh +3 -0
- data/spec/support/travis-ssh-keygen.sh +3 -0
- metadata +27 -3
data/.travis.yml
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
language: ruby
|
2
|
+
bundler_args: --without development
|
3
|
+
script: "bundle exec rake travis"
|
2
4
|
rvm:
|
3
|
-
- 1.8.7
|
4
5
|
- 1.9.2
|
5
6
|
- 1.9.3
|
7
|
+
- 2.0.0
|
8
|
+
env:
|
9
|
+
global:
|
10
|
+
- secure: dAxfEdg/7Cb/G9vkrn/ifdvycbXWtK2ey60JMepOxx9v3QyaqoSY3w5G0QB+4+uyOYmHwtif8tnK3Sa8jbBgqhAlXaxqxOT8WmQKYlhSgwWX4lQe4lUM5jkOkfNHRMRaQvCAn27gNAjdIRU7sb2cU/pm64eAFbU01TejJOM7Aow=
|
11
|
+
before_install:
|
12
|
+
- wget -qO- https://toolbelt.heroku.com/install-ubuntu.sh | sh
|
13
|
+
before_script:
|
14
|
+
- git config --global user.name "Travis CI"
|
15
|
+
- git config --global user.email "travis@example.com"
|
16
|
+
- echo -e "Host heroku.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
|
17
|
+
- ./spec/support/travis-ssh-keygen.sh < /dev/null
|
18
|
+
- heroku keys:add ~/.ssh/id_rsa.pub < /dev/null
|
19
|
+
after_script:
|
20
|
+
- ./spec/support/travis-key-cleanup.sh
|
data/Gemfile
CHANGED
@@ -3,21 +3,27 @@ source 'https://rubygems.org'
|
|
3
3
|
# Specify dependencies in heroku_san.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
-
group :
|
7
|
-
gem 'rails', '>= 2'
|
8
|
-
gem 'rspec'
|
6
|
+
group :test do
|
9
7
|
gem 'aruba'
|
8
|
+
gem 'bundler', '~> 1.1'
|
10
9
|
gem 'cucumber'
|
10
|
+
gem 'godot'
|
11
|
+
gem 'rails', '3.2.7'
|
11
12
|
gem 'rake'
|
12
|
-
gem '
|
13
|
+
gem 'rspec', '~> 2.14'
|
14
|
+
gem 'sqlite3'
|
15
|
+
gem 'pg'
|
16
|
+
end
|
17
|
+
|
18
|
+
group :development do
|
13
19
|
gem 'git-smart'
|
14
|
-
gem 'godot'
|
15
20
|
gem 'guard'
|
16
|
-
gem 'rb-inotify', :require => false
|
17
|
-
gem 'rb-fsevent', :require => false
|
18
|
-
gem 'rb-fchange', :require => false
|
19
|
-
gem 'terminal-notifier-guard'
|
20
|
-
gem 'guard-rspec'
|
21
21
|
gem 'guard-bundler'
|
22
22
|
gem 'guard-cucumber'
|
23
|
+
gem 'guard-rspec'
|
24
|
+
gem 'rb-fchange', :require => false
|
25
|
+
gem 'rb-fsevent', :require => false
|
26
|
+
gem 'rb-inotify', :require => false
|
27
|
+
gem 'terminal-notifier-guard'
|
28
|
+
gem 'travis', '~> 1.5.6'
|
23
29
|
end
|
data/Rakefile
CHANGED
@@ -3,6 +3,8 @@ require 'rubygems'
|
|
3
3
|
require 'bundler/setup'
|
4
4
|
require 'bundler/gem_tasks'
|
5
5
|
require 'rspec/core/rake_task'
|
6
|
+
require 'cucumber'
|
7
|
+
require 'cucumber/rake/task'
|
6
8
|
|
7
9
|
desc 'Default: run unit tests.'
|
8
10
|
task :default => :spec
|
@@ -11,3 +13,18 @@ desc "Run all specs"
|
|
11
13
|
RSpec::Core::RakeTask.new do |t|
|
12
14
|
t.pattern = 'spec/**/*_spec.rb'
|
13
15
|
end
|
16
|
+
|
17
|
+
namespace 'cucumber' do
|
18
|
+
Cucumber::Rake::Task.new(:remote) do |t|
|
19
|
+
t.profile = "remote"
|
20
|
+
end
|
21
|
+
|
22
|
+
Cucumber::Rake::Task.new(:default) do |t|
|
23
|
+
t.profile = "default"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "Run travis test suite"
|
28
|
+
task :travis => [:spec, 'cucumber:default', 'cucumber:remote']
|
29
|
+
|
30
|
+
# for app in `heroku apps | tail +2`; do heroku apps:destroy --app $app --confirm $app; done
|
data/features/remote.feature
CHANGED
@@ -8,7 +8,7 @@ Feature: heroku_san can control a project on Heroku
|
|
8
8
|
Scenario: Installs a project
|
9
9
|
Given I have a new Rails project
|
10
10
|
When I am in the project directory
|
11
|
-
And I add heroku_san to the Gemfile
|
11
|
+
And I add heroku_san to the rails Gemfile
|
12
12
|
Then rake reports that the heroku: tasks are available
|
13
13
|
|
14
14
|
Scenario: Manipulates a Rails app on Heroku
|
@@ -0,0 +1,47 @@
|
|
1
|
+
@slow_process @announce-cmd
|
2
|
+
Feature: heroku_san can shell out to heroku without errors
|
3
|
+
|
4
|
+
Scenario: Bundling a ruby 2.0 project
|
5
|
+
Given I run `mkdir -p ruby2test`
|
6
|
+
And I cd to "ruby2test"
|
7
|
+
And I write to "Gemfile" with:
|
8
|
+
"""
|
9
|
+
source "https://rubygems.org"
|
10
|
+
ruby '2.0.0'
|
11
|
+
gem 'heroku_san', :path => '../../../.'
|
12
|
+
"""
|
13
|
+
|
14
|
+
And I write to "get_heroku_version.rb" with:
|
15
|
+
"""
|
16
|
+
#!/usr/bin/env ruby
|
17
|
+
|
18
|
+
puts ENV['RUBY_VERSION']
|
19
|
+
|
20
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __FILE__)
|
21
|
+
|
22
|
+
require 'bundler/setup'
|
23
|
+
|
24
|
+
require 'heroku_san'
|
25
|
+
|
26
|
+
api = HerokuSan::API.new
|
27
|
+
|
28
|
+
api.sh('cool_app', 'version')
|
29
|
+
"""
|
30
|
+
And I write to "run_in_ruby_2.sh" with:
|
31
|
+
"""
|
32
|
+
#!/usr/bin/env bash
|
33
|
+
|
34
|
+
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"
|
35
|
+
|
36
|
+
rvm use 2.0.0
|
37
|
+
bundle install
|
38
|
+
|
39
|
+
ruby get_heroku_version.rb
|
40
|
+
"""
|
41
|
+
And I run `chmod +x run_in_ruby_2.sh`
|
42
|
+
And I cleanly run `./run_in_ruby_2.sh`
|
43
|
+
Then the output should contain "heroku-toolbelt"
|
44
|
+
# Fail if we see "Your Ruby version is 1.9.3, but your Gemfile specified 2.0.0"
|
45
|
+
Then the output should not contain "Your Ruby version"
|
46
|
+
Then the output should not contain "your Gemfile specified"
|
47
|
+
|
@@ -54,7 +54,7 @@ end
|
|
54
54
|
When /^I add heroku_san to the rails Gemfile$/ do
|
55
55
|
overwrite_file 'Gemfile', <<EOT.strip_heredoc
|
56
56
|
source 'https://rubygems.org'
|
57
|
-
ruby '
|
57
|
+
ruby '#{ruby_version}'
|
58
58
|
gem 'rails', '3.2.7'
|
59
59
|
gem 'pg'
|
60
60
|
group :development, :test do
|
@@ -67,7 +67,7 @@ end
|
|
67
67
|
When /^I add heroku_san to the sinatra Gemfile$/ do
|
68
68
|
overwrite_file 'Gemfile', <<EOT.strip_heredoc
|
69
69
|
source 'https://rubygems.org'
|
70
|
-
ruby '
|
70
|
+
ruby '#{ruby_version}'
|
71
71
|
gem 'sinatra'
|
72
72
|
group :development, :test do
|
73
73
|
gem 'heroku_san', :path => '../../../.'
|
@@ -87,6 +87,10 @@ When /^I run bundle install$/ do
|
|
87
87
|
run_clean "bundle install"
|
88
88
|
end
|
89
89
|
|
90
|
+
When /^I cleanly run `([^`]*)`$/ do |cmd|
|
91
|
+
run_clean(cmd)
|
92
|
+
end
|
93
|
+
|
90
94
|
Then /^rake reports that the heroku: tasks are available$/ do
|
91
95
|
output = run_clean 'rake -T heroku:'
|
92
96
|
assert_partial_output 'rake heroku:apps', output
|
@@ -197,13 +201,14 @@ When /^I install an addon$/ do
|
|
197
201
|
test_app:
|
198
202
|
app: #{@app}
|
199
203
|
addons:
|
200
|
-
-
|
204
|
+
- heroku-postgresql:dev
|
205
|
+
- pgbackups:plus
|
201
206
|
|
202
207
|
END_CONFIG
|
203
208
|
|
204
209
|
output = run_clean 'rake test_app heroku:addons'
|
205
210
|
# The output should show the new one ...
|
206
|
-
assert_partial_output "
|
211
|
+
assert_partial_output "heroku-postgresql:dev", output
|
207
212
|
end
|
208
213
|
|
209
214
|
Then /^(?:heroku_san|issue \d+) (?:is green|has been fixed)$/ do
|
@@ -230,3 +235,7 @@ def overwrite_simple_config_file
|
|
230
235
|
|
231
236
|
EOT
|
232
237
|
end
|
238
|
+
|
239
|
+
def ruby_version
|
240
|
+
ENV['TRAVIS_RUBY_VERSION'] || '1.9.3'
|
241
|
+
end
|
data/heroku_san.gemspec
CHANGED
@@ -23,23 +23,8 @@ Gem::Specification.new do |s|
|
|
23
23
|
https://toolbelt.heroku.com/
|
24
24
|
}
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
30
|
-
s.add_runtime_dependency(%q<heroku-api>, ['>= 0.1.2'])
|
31
|
-
s.add_runtime_dependency(%q<rake>)
|
32
|
-
else
|
33
|
-
s.add_dependency(%q<rails>, ['>= 2'])
|
34
|
-
s.add_dependency(%q<heroku-api>, ['>= 0.1.2'])
|
35
|
-
s.add_dependency(%q<aruba>)
|
36
|
-
s.add_dependency(%q<cucumber>)
|
37
|
-
end
|
38
|
-
else
|
39
|
-
s.add_dependency(%q<rails>, ['>= 2'])
|
40
|
-
s.add_dependency(%q<heroku-api>, ['>= 0.1.2'])
|
41
|
-
s.add_dependency(%q<aruba>)
|
42
|
-
s.add_dependency(%q<cucumber>)
|
43
|
-
end
|
26
|
+
s.add_runtime_dependency("heroku-api", [">= 0.1.2"])
|
27
|
+
s.add_runtime_dependency("json")
|
28
|
+
s.add_runtime_dependency("rake")
|
44
29
|
end
|
45
30
|
|
data/lib/heroku_san/api.rb
CHANGED
@@ -3,7 +3,23 @@ require 'time'
|
|
3
3
|
module HerokuSan
|
4
4
|
class API
|
5
5
|
def initialize(options = {})
|
6
|
-
@
|
6
|
+
@options = options
|
7
|
+
@options[:api_key] ||= auth_token
|
8
|
+
@heroku_api = Heroku::API.new(@options)
|
9
|
+
end
|
10
|
+
|
11
|
+
def sh(app, *command)
|
12
|
+
preflight_check_for_cli
|
13
|
+
|
14
|
+
cmd = (command + ['--app', app]).compact
|
15
|
+
|
16
|
+
show_command = cmd.join(' ')
|
17
|
+
$stderr.puts show_command if @debug
|
18
|
+
|
19
|
+
ok = Bundler.with_clean_env { system "heroku", *cmd }
|
20
|
+
|
21
|
+
status = $?
|
22
|
+
ok or fail "Command failed with status (#{status.exitstatus}): [heroku #{show_command}]"
|
7
23
|
end
|
8
24
|
|
9
25
|
def method_missing(name, *args)
|
@@ -15,5 +31,17 @@ module HerokuSan
|
|
15
31
|
$stderr.puts "\nHeroku API ERROR: #{status} (#{msg})\n\n"
|
16
32
|
raise error
|
17
33
|
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def auth_token
|
38
|
+
ENV['HEROKU_API_KEY'] || Bundler.with_clean_env { `heroku auth:token`.chomp }
|
39
|
+
rescue Errno::ENOENT
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def preflight_check_for_cli
|
44
|
+
raise "The Heroku Toolbelt is required for this action. http://toolbelt.heroku.com" if Bundler.with_clean_env { system('heroku version') == nil }
|
45
|
+
end
|
18
46
|
end
|
19
|
-
end
|
47
|
+
end
|
@@ -4,13 +4,15 @@ module HerokuSan
|
|
4
4
|
attr_accessor :configuration
|
5
5
|
attr_accessor :external_configuration
|
6
6
|
attr_reader :options
|
7
|
+
attr_reader :stage_factory
|
7
8
|
|
8
|
-
def initialize(configurable)
|
9
|
+
def initialize(configurable, stage_factory = HerokuSan::Stage)
|
9
10
|
@config_file = configurable.config_file
|
10
11
|
default_options = {
|
11
12
|
'deploy' => HerokuSan::Deploy::Rails
|
12
13
|
}
|
13
14
|
@options = default_options.merge(configurable.options || {})
|
15
|
+
@stage_factory = stage_factory
|
14
16
|
end
|
15
17
|
|
16
18
|
def parse
|
@@ -20,7 +22,7 @@ module HerokuSan
|
|
20
22
|
def stages
|
21
23
|
configured? or parse
|
22
24
|
configuration.inject({}) do |stages, (stage, settings)|
|
23
|
-
stages[stage] =
|
25
|
+
stages[stage] = stage_factory.new(stage, settings.merge('deploy' => (options[:deploy]||options['deploy'])))
|
24
26
|
stages
|
25
27
|
end
|
26
28
|
end
|
data/lib/heroku_san/stage.rb
CHANGED
@@ -2,28 +2,23 @@ require 'heroku-api'
|
|
2
2
|
require 'json'
|
3
3
|
require_relative 'application'
|
4
4
|
|
5
|
-
MOCK = false unless defined?(MOCK)
|
6
|
-
|
7
5
|
module HerokuSan
|
8
6
|
class Stage
|
9
7
|
include HerokuSan::Git
|
10
|
-
attr_reader :name
|
11
|
-
attr_reader :options
|
12
8
|
include HerokuSan::Application
|
13
9
|
|
10
|
+
attr_reader :name, :options, :heroku
|
11
|
+
|
14
12
|
def initialize(stage, options = {})
|
15
13
|
@name = stage
|
16
14
|
@options = options
|
15
|
+
@heroku = options.delete(:api) || HerokuSan::API.new
|
17
16
|
end
|
18
17
|
|
19
18
|
def ==(other)
|
20
19
|
other.name == name && other.options == options
|
21
20
|
end
|
22
21
|
|
23
|
-
def heroku
|
24
|
-
@heroku ||= HerokuSan::API.new(:api_key => auth_token, :mock => MOCK)
|
25
|
-
end
|
26
|
-
|
27
22
|
def app
|
28
23
|
@options['app'] or raise MissingApp, "#{name}: is missing the app: configuration value. I don't know what to access on Heroku."
|
29
24
|
end
|
@@ -49,7 +44,7 @@ module HerokuSan
|
|
49
44
|
end
|
50
45
|
|
51
46
|
def run(command, args = nil)
|
52
|
-
|
47
|
+
heroku.sh app, "run", command, *args
|
53
48
|
end
|
54
49
|
|
55
50
|
def push(sha = nil, force = false)
|
@@ -128,31 +123,11 @@ module HerokuSan
|
|
128
123
|
end
|
129
124
|
|
130
125
|
def logs(tail = false)
|
131
|
-
|
126
|
+
heroku.sh app, 'logs', (tail ? '--tail' : nil)
|
132
127
|
end
|
133
128
|
|
134
129
|
def revision
|
135
130
|
git_named_rev(git_revision(repo))
|
136
131
|
end
|
137
|
-
|
138
|
-
private
|
139
|
-
|
140
|
-
def auth_token
|
141
|
-
@auth_token ||= (ENV['HEROKU_API_KEY'] || `heroku auth:token`.chomp unless MOCK)
|
142
|
-
end
|
143
|
-
|
144
|
-
def sh_heroku(*command)
|
145
|
-
preflight_check_for_cli
|
146
|
-
cmd = (command + ['--app', app]).compact
|
147
|
-
show_command = cmd.join(' ')
|
148
|
-
$stderr.puts show_command if @debug
|
149
|
-
ok = system "heroku", *cmd
|
150
|
-
status = $?
|
151
|
-
ok or fail "Command failed with status (#{status.exitstatus}): [heroku #{show_command}]"
|
152
|
-
end
|
153
|
-
|
154
|
-
def preflight_check_for_cli
|
155
|
-
raise "The Heroku Toolbelt is required for this action. http://toolbelt.heroku.com" if system('heroku version') == nil
|
156
|
-
end
|
157
132
|
end
|
158
133
|
end
|
data/lib/heroku_san/version.rb
CHANGED
data/spec/heroku_san/api_spec.rb
CHANGED
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
# https://github.com/fastestforward/heroku_san/issues/105
|
4
4
|
module HerokuSan
|
5
5
|
describe HerokuSan::API do
|
6
|
-
subject(:api) { HerokuSan::API.new(:api_key => 'key', :
|
6
|
+
subject(:api) { HerokuSan::API.new(:api_key => 'key', :double => true)}
|
7
7
|
it "is a proxy to the Heroku::API" do
|
8
8
|
Heroku::API.any_instance.should_receive(:api_method).with(1, 2, {:arg => 3}) {true}
|
9
9
|
api.api_method(1, 2, {:arg => 3}).should be_true
|
@@ -12,7 +12,7 @@ describe HerokuSan::API do
|
|
12
12
|
it "reports Excon errors in a more human readable format" do
|
13
13
|
error_message = 'Name is already taken'
|
14
14
|
status_message = '000 Status'
|
15
|
-
response =
|
15
|
+
response = double("Response", :body => %Q[{"error":"#{error_message}"}], :headers => {'Status' => status_message})
|
16
16
|
Heroku::API.any_instance.should_receive(:api_method).and_raise(Heroku::API::Errors::ErrorWithResponse.new("excon message", response))
|
17
17
|
|
18
18
|
$stderr.should_receive(:puts).with("\nHeroku API ERROR: #{status_message} (#{error_message})\n\n")
|
@@ -2,8 +2,8 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module HerokuSan
|
4
4
|
describe HerokuSan::Application do
|
5
|
-
let(:stage) {
|
6
|
-
let(:response) {
|
5
|
+
let(:stage) { Factory::Stage.build('production', {"deploy" => HerokuSan::Deploy::Rails, "app" => "awesomeapp", "stack" => "cedar"}) }
|
6
|
+
let(:response) { double }
|
7
7
|
|
8
8
|
before do
|
9
9
|
stage.heroku.stub(:get_ps).with(stage.app) { response }
|
@@ -3,13 +3,13 @@ require 'spec_helper'
|
|
3
3
|
module HerokuSan
|
4
4
|
describe HerokuSan::Configuration do
|
5
5
|
let(:configurable) { Configurable.new }
|
6
|
-
let(:configuration) { HerokuSan::Configuration.new(configurable) }
|
6
|
+
let(:configuration) { HerokuSan::Configuration.new(configurable, Factory::Stage) }
|
7
7
|
|
8
8
|
describe "#stages" do
|
9
9
|
it "creates a configuration hash" do
|
10
10
|
configuration.configuration = {'production' => {}}
|
11
11
|
configuration.stages.should == {
|
12
|
-
'production' =>
|
12
|
+
'production' => Factory::Stage.build('production', 'deploy' => HerokuSan::Deploy::Rails)
|
13
13
|
}
|
14
14
|
end
|
15
15
|
|
@@ -17,7 +17,7 @@ describe HerokuSan::Configuration do
|
|
17
17
|
configurable.options = {'deploy' => HerokuSan::Deploy::Base}
|
18
18
|
configuration.configuration = {'production' => {}}
|
19
19
|
configuration.stages.should == {
|
20
|
-
'production' =>
|
20
|
+
'production' => Factory::Stage.build('production', 'deploy' => HerokuSan::Deploy::Base)
|
21
21
|
}
|
22
22
|
end
|
23
23
|
end
|
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
module HerokuSan
|
4
4
|
module Deploy
|
5
5
|
describe Base do
|
6
|
-
let(:stage) {
|
6
|
+
let(:stage) { Factory::Stage.build('test', {"app" => "awesomeapp", "deploy" => 'HerokuSan::Deploy::Base'}) }
|
7
7
|
|
8
8
|
it "calls push" do
|
9
9
|
subject = described_class.new(stage)
|
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
module HerokuSan
|
4
4
|
module Deploy
|
5
5
|
describe Rails do
|
6
|
-
let(:stage) {
|
6
|
+
let(:stage) { Factory::Stage.build('test', {"app" => "awesomeapp", "deploy" => 'HerokuSan::Deploy::Rails'}) }
|
7
7
|
|
8
8
|
it "calls push, rake db:migrate & restart" do
|
9
9
|
subject = described_class.new(stage, {})
|
@@ -54,13 +54,13 @@ describe HerokuSan::Parser do
|
|
54
54
|
end
|
55
55
|
|
56
56
|
describe "#merge_external_config" do
|
57
|
-
let(:stages) { [
|
58
|
-
let(:prod_config) {
|
57
|
+
let(:stages) { [double(:name => 'production', :config => prod_config), double(:name => 'staging', :config => staging_config)] }
|
58
|
+
let(:prod_config) { double('Production Config') }
|
59
59
|
let(:staging_config) { {'EXTRA' => 'bar'} }
|
60
60
|
let(:extras) { {'production' => {'EXTRA' => 'bar'}, 'staging' => {'EXTRA' => 'foo'}} }
|
61
61
|
|
62
62
|
context "with no extras" do
|
63
|
-
let(:parseable) {
|
63
|
+
let(:parseable) { double :external_configuration => nil }
|
64
64
|
|
65
65
|
it "doesn't change prod_config" do
|
66
66
|
prod_config.should_not_receive :merge!
|
@@ -69,7 +69,7 @@ describe HerokuSan::Parser do
|
|
69
69
|
end
|
70
70
|
|
71
71
|
context "with extra" do
|
72
|
-
let(:parseable) {
|
72
|
+
let(:parseable) { double :external_configuration => 'config_repos' }
|
73
73
|
before(:each) do
|
74
74
|
parser.should_receive(:git_clone).with('config_repos', anything)
|
75
75
|
parser.should_receive(:parse_yaml).and_return(extras)
|
@@ -6,7 +6,7 @@ describe HerokuSan::Project do
|
|
6
6
|
let(:heroku_san) { HerokuSan::Project.new }
|
7
7
|
subject { heroku_san }
|
8
8
|
before do
|
9
|
-
HerokuSan::Configuration.new(Configurable.new).tap do |config|
|
9
|
+
HerokuSan::Configuration.new(Configurable.new, Factory::Stage).tap do |config|
|
10
10
|
config.configuration = {'production' => {}, 'staging' => {}, 'demo' => {}}
|
11
11
|
heroku_san.configuration = config
|
12
12
|
end
|
@@ -1,21 +1,22 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
module HerokuSan
|
4
|
+
STOCK_CONFIG = {"BUNDLE_WITHOUT"=>"development:test", "LANG"=>"en_US.UTF-8", "RACK_ENV"=>"production"}
|
5
|
+
|
4
6
|
describe HerokuSan::Stage do
|
5
7
|
include HerokuSan::Git
|
6
|
-
subject {
|
7
|
-
STOCK_CONFIG = {"BUNDLE_WITHOUT"=>"development:test", "LANG"=>"en_US.UTF-8", "RACK_ENV"=>"production"}
|
8
|
+
subject { Factory::Stage.build('production', {"deploy" => HerokuSan::Deploy::Rails, "app" => "awesomeapp", "stack" => "cedar"})}
|
8
9
|
before do
|
9
|
-
HerokuSan::
|
10
|
+
HerokuSan::API.any_instance.stub(:preflight_check_for_cli)
|
10
11
|
end
|
11
12
|
|
12
13
|
context "initializes" do
|
13
|
-
subject {
|
14
|
+
subject { Factory::Stage.build('production',
|
14
15
|
{"stack" => "cedar",
|
15
16
|
"app" => "awesomeapp-demo",
|
16
17
|
"tag" => "demo/*",
|
17
18
|
"config"=> {"BUNDLE_WITHOUT"=>"development:test"},
|
18
|
-
"addons"=> ['one:addon', 'two:addons']
|
19
|
+
"addons"=> ['one:addon', 'two:addons']
|
19
20
|
})}
|
20
21
|
|
21
22
|
its(:name) { should == 'production' }
|
@@ -30,7 +31,7 @@ describe HerokuSan::Stage do
|
|
30
31
|
describe "#app" do
|
31
32
|
its(:app) { should == 'awesomeapp'}
|
32
33
|
context "blank app" do
|
33
|
-
subject {
|
34
|
+
subject { Factory::Stage.build('production') }
|
34
35
|
it "should raise an error" do
|
35
36
|
expect { subject.app }.to raise_error(HerokuSan::MissingApp, /production: is missing the app: configuration value\./)
|
36
37
|
end
|
@@ -39,20 +40,20 @@ describe HerokuSan::Stage do
|
|
39
40
|
|
40
41
|
describe "#stack" do
|
41
42
|
it "returns the name of the stack from Heroku" do
|
42
|
-
subject =
|
43
|
+
subject = Factory::Stage.build('production', {"app" => "awesomeapp"})
|
43
44
|
with_app(subject, 'name' => subject.app) do |app_data|
|
44
45
|
subject.stack.should == 'bamboo-mri-1.9.2'
|
45
46
|
end
|
46
47
|
end
|
47
48
|
|
48
49
|
it "returns the stack name from the config when it is set there" do
|
49
|
-
subject =
|
50
|
+
subject = Factory::Stage.build('production', {"app" => "awesomeapp", "stack" => "cedar"})
|
50
51
|
subject.stack.should == 'cedar'
|
51
52
|
end
|
52
53
|
end
|
53
54
|
|
54
55
|
describe '#addons' do
|
55
|
-
subject {
|
56
|
+
subject { Factory::Stage.build('production', {'addons' => addons}) }
|
56
57
|
context 'default' do
|
57
58
|
let(:addons) { nil }
|
58
59
|
its(:addons) { should == [] }
|
@@ -73,7 +74,7 @@ describe HerokuSan::Stage do
|
|
73
74
|
|
74
75
|
describe "#run" do
|
75
76
|
it "runs commands using the new cedar format" do
|
76
|
-
subject.should_receive(:system).with("heroku", "run", "worker foo bar bleh", "--app", "awesomeapp") { true }
|
77
|
+
subject.heroku.should_receive(:system).with("heroku", "run", "worker foo bar bleh", "--app", "awesomeapp") { true }
|
77
78
|
subject.run 'worker foo bar bleh'
|
78
79
|
end
|
79
80
|
end
|
@@ -123,7 +124,7 @@ describe HerokuSan::Stage do
|
|
123
124
|
class TestDeployStrategy < HerokuSan::Deploy::Base
|
124
125
|
def deploy; end
|
125
126
|
end
|
126
|
-
subject =
|
127
|
+
subject = Factory::Stage.build('test', {"app" => "awesomeapp", "deploy" => TestDeployStrategy})
|
127
128
|
it "(custom) calls deploy" do
|
128
129
|
TestDeployStrategy.any_instance.should_receive(:deploy)
|
129
130
|
subject.deploy
|
@@ -154,7 +155,7 @@ describe HerokuSan::Stage do
|
|
154
155
|
it "wraps it in a maintenance mode" do
|
155
156
|
with_app(subject, 'name' => subject.app) do |app_data|
|
156
157
|
subject.heroku.should_receive(:post_app_maintenance).with(subject.app, '1').ordered
|
157
|
-
reactor =
|
158
|
+
reactor = double("Reactor"); reactor.should_receive(:scram).with(:now).ordered
|
158
159
|
subject.heroku.should_receive(:post_app_maintenance).with(subject.app, '0').ordered
|
159
160
|
|
160
161
|
subject.maintenance {reactor.scram(:now)}
|
@@ -164,7 +165,7 @@ describe HerokuSan::Stage do
|
|
164
165
|
it "ensures that maintenance mode is turned off" do
|
165
166
|
with_app(subject, 'name' => subject.app) do |app_data|
|
166
167
|
subject.heroku.should_receive(:post_app_maintenance).with(subject.app, '1').ordered
|
167
|
-
reactor =
|
168
|
+
reactor = double("Reactor"); reactor.should_receive(:scram).and_raise(RuntimeError)
|
168
169
|
subject.heroku.should_receive(:post_app_maintenance).with(subject.app, '0').ordered
|
169
170
|
|
170
171
|
expect do subject.maintenance {reactor.scram(:now)} end.to raise_error
|
@@ -183,12 +184,12 @@ describe HerokuSan::Stage do
|
|
183
184
|
end
|
184
185
|
|
185
186
|
it "creates an app on heroku" do
|
186
|
-
subject =
|
187
|
+
subject = Factory::Stage.build('production')
|
187
188
|
(@app = subject.create).should =~ /generated-name-\d+/
|
188
189
|
end
|
189
190
|
|
190
191
|
it "uses the default stack if none is given" do
|
191
|
-
subject =
|
192
|
+
subject = Factory::Stage.build('production')
|
192
193
|
(@app = subject.create).should =~ /generated-name-\d+/
|
193
194
|
subject.heroku.get_stack(@app).body.detect{|stack| stack['current']}['name'].should == 'bamboo-mri-1.9.2'
|
194
195
|
end
|
@@ -209,14 +210,14 @@ describe HerokuSan::Stage do
|
|
209
210
|
|
210
211
|
describe "#push_config" do
|
211
212
|
it "updates the configuration settings on Heroku" do
|
212
|
-
subject =
|
213
|
+
subject = Factory::Stage.build('test', {"app" => "awesomeapp", "config" => {'FOO' => 'bar', 'DOG' => 'emu'}})
|
213
214
|
with_app(subject, 'name' => subject.app) do |app_data|
|
214
215
|
subject.push_config.should == STOCK_CONFIG.merge('FOO' => 'bar', 'DOG' => 'emu')
|
215
216
|
end
|
216
217
|
end
|
217
218
|
|
218
219
|
it "pushes the options hash" do
|
219
|
-
subject =
|
220
|
+
subject = Factory::Stage.build('test', {"app" => "awesomeapp", "config" => {'FOO' => 'bar', 'DOG' => 'emu'}})
|
220
221
|
with_app(subject, 'name' => subject.app) do |app_data|
|
221
222
|
subject.push_config('RACK_ENV' => 'magic').should == STOCK_CONFIG.merge('RACK_ENV' => 'magic')
|
222
223
|
end
|
@@ -233,12 +234,12 @@ describe HerokuSan::Stage do
|
|
233
234
|
|
234
235
|
describe "#logs" do
|
235
236
|
it "returns log files" do
|
236
|
-
subject.should_receive(:system).with("heroku", "logs", "--app", "awesomeapp") { true }
|
237
|
+
subject.heroku.should_receive(:system).with("heroku", "logs", "--app", "awesomeapp") { true }
|
237
238
|
subject.logs
|
238
239
|
end
|
239
240
|
|
240
241
|
it "tails log files" do
|
241
|
-
subject.should_receive(:system).with("heroku", "logs", "--tail", "--app", "awesomeapp") { true }
|
242
|
+
subject.heroku.should_receive(:system).with("heroku", "logs", "--tail", "--app", "awesomeapp") { true }
|
242
243
|
subject.logs(:tail)
|
243
244
|
end
|
244
245
|
end
|
@@ -266,7 +267,7 @@ describe HerokuSan::Stage do
|
|
266
267
|
end
|
267
268
|
|
268
269
|
describe '#install_addons' do
|
269
|
-
subject {
|
270
|
+
subject { Factory::Stage.build('production', {"app" => "awesomeapp", "stack" => "bamboo-ree-1.8.7", "addons" => %w[custom_domains:basic ssl:piggyback]})}
|
270
271
|
|
271
272
|
it "installs the addons" do
|
272
273
|
with_app(subject, 'name' => subject.app) do |app_data|
|
@@ -276,7 +277,7 @@ describe HerokuSan::Stage do
|
|
276
277
|
end
|
277
278
|
|
278
279
|
it "only installs missing addons" do
|
279
|
-
subject =
|
280
|
+
subject = Factory::Stage.build('production', {"app" => "awesomeapp", "stack" => "bamboo-ree-1.8.7", "addons" => %w[shared-database:5mb custom_domains:basic ssl:piggyback]})
|
280
281
|
with_app(subject, 'name' => subject.app) do |app_data|
|
281
282
|
subject.install_addons.map{|a| a['name']}.should include *%w[shared-database:5mb custom_domains:basic ssl:piggyback]
|
282
283
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -3,8 +3,6 @@ Bundler.setup
|
|
3
3
|
|
4
4
|
SPEC_ROOT = File.dirname(__FILE__)
|
5
5
|
|
6
|
-
MOCK = ENV['MOCK'] != 'false'
|
7
|
-
|
8
6
|
# Requires supporting ruby files with custom matchers and macros, etc,
|
9
7
|
# in spec/support/ and its subdirectories.
|
10
8
|
Dir[File.join(SPEC_ROOT, "support/**/*.rb")].each {|f| require f}
|
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: 4.3.
|
4
|
+
version: 4.3.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2013-
|
15
|
+
date: 2013-10-23 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: heroku-api
|
@@ -30,6 +30,22 @@ dependencies:
|
|
30
30
|
- - ! '>='
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: 0.1.2
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: json
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
type: :runtime
|
42
|
+
prerelease: false
|
43
|
+
version_requirements: !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
45
|
+
requirements:
|
46
|
+
- - ! '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
33
49
|
- !ruby/object:Gem::Dependency
|
34
50
|
name: rake
|
35
51
|
requirement: !ruby/object:Gem::Requirement
|
@@ -71,6 +87,7 @@ files:
|
|
71
87
|
- features/extended-config.feature
|
72
88
|
- features/issue_113.feature
|
73
89
|
- features/remote.feature
|
90
|
+
- features/shell_execution.feature
|
74
91
|
- features/step_definitions/remote_steps.rb
|
75
92
|
- features/support/env.rb
|
76
93
|
- heroku_san.gemspec
|
@@ -105,8 +122,11 @@ files:
|
|
105
122
|
- spec/heroku_san/project_spec.rb
|
106
123
|
- spec/heroku_san/stage_spec.rb
|
107
124
|
- spec/spec_helper.rb
|
125
|
+
- spec/support/factory.rb
|
108
126
|
- spec/support/heroku.rb
|
109
127
|
- spec/support/mocks.rb
|
128
|
+
- spec/support/travis-key-cleanup.sh
|
129
|
+
- spec/support/travis-ssh-keygen.sh
|
110
130
|
homepage: http://github.com/fastestforward/heroku_san
|
111
131
|
licenses:
|
112
132
|
- MIT
|
@@ -122,7 +142,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
122
142
|
version: '0'
|
123
143
|
segments:
|
124
144
|
- 0
|
125
|
-
hash:
|
145
|
+
hash: 364838446742760909
|
126
146
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
147
|
none: false
|
128
148
|
requirements:
|
@@ -141,6 +161,7 @@ test_files:
|
|
141
161
|
- features/extended-config.feature
|
142
162
|
- features/issue_113.feature
|
143
163
|
- features/remote.feature
|
164
|
+
- features/shell_execution.feature
|
144
165
|
- features/step_definitions/remote_steps.rb
|
145
166
|
- features/support/env.rb
|
146
167
|
- spec/fixtures/example.yml
|
@@ -156,5 +177,8 @@ test_files:
|
|
156
177
|
- spec/heroku_san/project_spec.rb
|
157
178
|
- spec/heroku_san/stage_spec.rb
|
158
179
|
- spec/spec_helper.rb
|
180
|
+
- spec/support/factory.rb
|
159
181
|
- spec/support/heroku.rb
|
160
182
|
- spec/support/mocks.rb
|
183
|
+
- spec/support/travis-key-cleanup.sh
|
184
|
+
- spec/support/travis-ssh-keygen.sh
|