heroku-rails-saas 0.1.5 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,10 +1,14 @@
1
1
  source :rubygems
2
2
  gemspec
3
3
 
4
- # gem "ruby-debug", :platforms => :mri_18
5
- # gem "ruby-debug19", :platforms => :mri_19
4
+ gem "rake"
5
+ group :development, :test do
6
+ gem "rdoc", '~> 3.12'
7
+ end
6
8
 
7
- gem "autotest", ">= 0"
8
- gem "growl-glue", ">= 0"
9
-
10
- gem "rake", "0.8.7"
9
+ group :test do
10
+ gem "ruby-debug", :platforms => :mri_18
11
+ gem "ruby-debug19", :platforms => :mri_19
12
+
13
+ gem "rspec"
14
+ end
data/Gemfile.lock CHANGED
@@ -1,46 +1,78 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- heroku-rails-saas (0.1.5)
4
+ heroku-rails-saas (0.1.7)
5
5
  heroku (>= 2.24.1)
6
6
 
7
7
  GEM
8
8
  remote: http://rubygems.org/
9
9
  specs:
10
- ZenTest (4.7.0)
11
- addressable (2.2.8)
12
- autotest (4.4.6)
13
- ZenTest (>= 4.4.1)
10
+ activesupport (3.2.3)
11
+ i18n (~> 0.6)
12
+ multi_json (~> 1.0)
13
+ addressable (2.3.2)
14
+ archive-tar-minitar (0.5.2)
15
+ columnize (0.3.6)
14
16
  diff-lcs (1.1.3)
15
- growl-glue (1.0.7)
16
- heroku (2.25.0)
17
+ excon (0.15.5)
18
+ heroku (2.30.2)
19
+ heroku-api (~> 0.3.2)
17
20
  launchy (>= 0.3.2)
18
- netrc (~> 0.7.1)
21
+ netrc (~> 0.7.5)
19
22
  rest-client (~> 1.6.1)
20
23
  rubyzip
21
- launchy (2.1.0)
22
- addressable (~> 2.2.6)
23
- mime-types (1.18)
24
- netrc (0.7.1)
25
- rake (0.8.7)
24
+ heroku-api (0.3.2)
25
+ excon (~> 0.15.5)
26
+ i18n (0.6.0)
27
+ json (1.7.4)
28
+ launchy (2.1.2)
29
+ addressable (~> 2.3)
30
+ linecache (0.46)
31
+ rbx-require-relative (> 0.0.4)
32
+ linecache19 (0.5.12)
33
+ ruby_core_source (>= 0.1.4)
34
+ mime-types (1.19)
35
+ multi_json (1.3.4)
36
+ netrc (0.7.5)
37
+ rake (0.9.2.2)
38
+ rbx-require-relative (0.0.9)
39
+ rdoc (3.12)
40
+ json (~> 1.4)
26
41
  rest-client (1.6.7)
27
42
  mime-types (>= 1.16)
28
- rspec (2.9.0)
29
- rspec-core (~> 2.9.0)
30
- rspec-expectations (~> 2.9.0)
31
- rspec-mocks (~> 2.9.0)
32
- rspec-core (2.9.0)
33
- rspec-expectations (2.9.1)
43
+ rspec (2.11.0)
44
+ rspec-core (~> 2.11.0)
45
+ rspec-expectations (~> 2.11.0)
46
+ rspec-mocks (~> 2.11.0)
47
+ rspec-core (2.11.1)
48
+ rspec-expectations (2.11.2)
34
49
  diff-lcs (~> 1.1.3)
35
- rspec-mocks (2.9.0)
36
- rubyzip (0.9.8)
50
+ rspec-mocks (2.11.1)
51
+ ruby-debug (0.10.4)
52
+ columnize (>= 0.1)
53
+ ruby-debug-base (~> 0.10.4.0)
54
+ ruby-debug-base (0.10.4)
55
+ linecache (>= 0.3)
56
+ ruby-debug-base19 (0.11.25)
57
+ columnize (>= 0.3.1)
58
+ linecache19 (>= 0.5.11)
59
+ ruby_core_source (>= 0.1.4)
60
+ ruby-debug19 (0.11.6)
61
+ columnize (>= 0.3.1)
62
+ linecache19 (>= 0.5.11)
63
+ ruby-debug-base19 (>= 0.11.19)
64
+ ruby_core_source (0.1.5)
65
+ archive-tar-minitar (>= 0.5.2)
66
+ rubyzip (0.9.9)
37
67
 
38
68
  PLATFORMS
39
69
  ruby
40
70
 
41
71
  DEPENDENCIES
42
- autotest
43
- growl-glue
72
+ activesupport
44
73
  heroku-rails-saas!
45
- rake (= 0.8.7)
46
- rspec (~> 2.0)
74
+ rake
75
+ rdoc (~> 3.12)
76
+ rspec
77
+ ruby-debug
78
+ ruby-debug19
data/Rakefile CHANGED
@@ -1,11 +1,14 @@
1
1
  require "bundler"
2
2
  Bundler.setup
3
3
 
4
- require 'rake'
5
- require 'rake/gempackagetask'
4
+ # require 'rake'
5
+ # require 'rake/gempackagetask'
6
+
7
+ require 'rubygems'
8
+ require 'rubygems/package_task'
6
9
 
7
10
  gemspec = eval(File.read('heroku-rails.gemspec'))
8
- Rake::GemPackageTask.new(gemspec) do |pkg|
11
+ Gem::PackageTask.new(gemspec) do |pkg|
9
12
  pkg.gem_spec = gemspec
10
13
  end
11
14
 
@@ -19,19 +22,19 @@ task :release => :gem do
19
22
  system "gem push pkg/#{gemspec.name}-#{gemspec.version}.gem"
20
23
  end
21
24
 
22
- require "rspec"
25
+ # require "rspec"
23
26
  require "rspec/core/rake_task"
24
27
 
25
- Rspec::Core::RakeTask.new(:spec) do |spec|
28
+ RSpec::Core::RakeTask.new(:spec) do |spec|
26
29
  spec.pattern = "spec/**/*_spec.rb"
27
30
  end
28
31
 
29
- Rspec::Core::RakeTask.new('spec:progress') do |spec|
32
+ RSpec::Core::RakeTask.new('spec:progress') do |spec|
30
33
  spec.rspec_opts = %w(--format progress)
31
34
  spec.pattern = "spec/**/*_spec.rb"
32
35
  end
33
36
 
34
- require "rake/rdoctask"
37
+ require 'rdoc/task'
35
38
  Rake::RDocTask.new do |rdoc|
36
39
  rdoc.rdoc_dir = "rdoc"
37
40
  rdoc.title = "Heroku Rails SaaS #{gemspec.version}"
data/heroku-rails.gemspec CHANGED
@@ -1,8 +1,8 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "heroku-rails-saas"
3
- s.version = "0.1.5"
3
+ s.version = "0.1.7"
4
4
 
5
- s.authors = [ "Elijah Miller", "Glenn Roberts", "Jacques Crocker", "Lance Sanchez"]
5
+ s.authors = [ "Elijah Miller", "Glenn Roberts", "Jacques Crocker", "Lance Sanchez", "Chris Trinh"]
6
6
 
7
7
  s.summary = "Deployment and configuration tools for Heroku/Rails"
8
8
  s.description = "Manage multiple Heroku instances/apps for a single Rails app using Rake."
@@ -34,5 +34,6 @@ Gem::Specification.new do |s|
34
34
 
35
35
  s.add_runtime_dependency "heroku", ">= 2.24.1"
36
36
  s.add_development_dependency "rspec", "~> 2.0"
37
+ s.add_development_dependency "activesupport"
37
38
  end
38
39
 
@@ -1,3 +1,4 @@
1
+ require 'active_support/core_ext/object/try'
1
2
  require 'erb'
2
3
 
3
4
  module HerokuRailsSaas
@@ -44,6 +45,18 @@ module HerokuRailsSaas
44
45
  apps.keys
45
46
  end
46
47
 
48
+ def cmd(app_env)
49
+ if self.stack(app_env) =~ /cedar/i
50
+ 'heroku run '
51
+ else
52
+ 'heroku '
53
+ end
54
+ end
55
+
56
+ def rails_cli script
57
+ Rails::VERSION::MAJOR < 3 ? ".script/#{script}" : "rails #{script}"
58
+ end
59
+
47
60
  # Returns the app name on heroku froma string format like so: `app:env`
48
61
  # Allows for `rake <app:env> [<app:env>] <command>`
49
62
  def app_name_on_heroku(string)
@@ -70,73 +83,62 @@ module HerokuRailsSaas
70
83
  def stack(app_env)
71
84
  name, env = app_env.split(SEPERATOR)
72
85
  stacks = self.settings['stacks'] || {}
73
- (stacks[name] && stacks[name][env]) || stacks['all']
86
+ stacks[name].try("[]", env) || stacks['all']
74
87
  end
75
88
 
76
- def cmd(app_env)
77
- if self.stack(app_env) =~ /cedar/i
78
- 'heroku run '
79
- else
80
- 'heroku '
81
- end
89
+ # return a list of domains for a particular app environment
90
+ def domains(app_env)
91
+ name, env = app_env.split(SEPERATOR)
92
+ domains = self.settings['domains'] || {}
93
+ domains[name].try("[]", env) || []
82
94
  end
83
95
 
84
96
  # pull out the config setting hash for a particular app environment
85
97
  def config(app_env)
86
- name, env = app_env.split(SEPERATOR)
87
- config = self.settings['config'] || {}
88
- all = config['all'] || {}
89
-
90
- app_configs = (config[name] && config[name].reject { |k,v| v.class == Hash }) || {}
91
- # overwrite app configs with the environment specific ones
92
- merged_environment_configs = app_configs.merge((config[name] && config[name][env]) || {})
93
-
94
- # overwrite all configs with the environment specific ones
95
- all.merge(merged_environment_configs)
98
+ app_setting_hash("config", app_env)
96
99
  end
97
100
 
98
101
  # pull out the scaling setting hash for a particular app environment
99
102
  def scale(app_env)
100
- name, env = app_env.split(SEPERATOR)
101
- scaling = self.settings['scale'] || {}
102
- all = scaling['all'] || {}
103
-
104
- app_scaling = (scaling[name] && scaling[name].reject { |k,v| v.class == Hash }) || {}
105
- # overwrite app scaling with the environment specific ones
106
- merged_environment_scaling = app_scaling.merge((scaling[name] && scaling[name][env]) || {})
107
-
108
- # overwrite all scaling with the environment specific ones
109
- all.merge(merged_environment_scaling)
103
+ app_setting_hash("scale", app_env)
110
104
  end
111
105
 
112
- # return a list of domains for a particular app environment
113
- def domains(app_env)
114
- name, env = app_env.split(SEPERATOR)
115
- domains = self.settings['domains'] || {}
116
- (domains[name] && domains[name][env]) || []
117
- end
106
+
118
107
  # return a list of collaborators for a particular app environment
119
108
  def collaborators(app_env)
120
- app_setting_list('collaborators', app_env)
109
+ app_setting_array('collaborators', app_env)
121
110
  end
122
111
 
123
112
  # return a list of addons for a particular app environment
124
113
  def addons(app_env)
125
- app_setting_list('addons', app_env)
114
+ app_setting_array('addons', app_env)
126
115
  end
127
116
 
128
- protected
117
+ private
129
118
 
130
- def app_setting_list(setting_key, app_env)
119
+ # Add app specific settings to the default ones defined in all for an array listing
120
+ def app_setting_array(setting_key, app_env)
131
121
  name, env = app_env.split(SEPERATOR)
132
122
  setting = self.settings[setting_key] || {}
133
- all = setting['all'] || []
123
+ default = setting['all'] || []
134
124
 
135
- # add in collaborators from app environment to the ones defined in all
136
- (all + ((setting[name] && setting[name][env]) || [])).uniq
125
+ app_settings = setting[name].try("[]", env) || []
126
+ (default + app_settings).uniq
137
127
  end
138
128
 
139
- private
129
+ # Add app specific settings to the default ones defined in all for a hash listing
130
+ def app_setting_hash(setting_key, app_env)
131
+ name, env = app_env.split(SEPERATOR)
132
+ config = self.settings[setting_key] || {}
133
+ all = config['all'] || {}
134
+
135
+ app_configs = (config[name] && config[name].reject { |k,v| v.class == Hash }) || {}
136
+ # overwrite app settings with the environment specific ones
137
+ merged_environment_configs = app_configs.merge((config[name] && config[name][env]) || {})
138
+
139
+ # overwrite all settings with the environment specific ones
140
+ all.merge(merged_environment_configs)
141
+ end
140
142
 
141
143
  def parse_yml(config_filepath, options)
142
144
  if File.exists?(config_filepath)
@@ -157,8 +159,7 @@ module HerokuRailsSaas
157
159
  end
158
160
 
159
161
  def aggregate_heroku_configs(config_files)
160
- hsh = {}
161
- config_files[:apps].each_with_object(hsh) { |file, h| h.rmerge!(parse_yml(file, :apps)) }
162
+ hsh = config_files[:apps].each_with_object({}) { |file, h| h.rmerge!(parse_yml(file, :apps)) }
162
163
  # overwrite all configs with the environment specific ones
163
164
  hsh.rmerge!(parse_yml(config_files[:default], :default))
164
165
  end
@@ -1,3 +1,4 @@
1
+ require 'active_support/core_ext/object/blank'
1
2
  require 'heroku/client'
2
3
 
3
4
  module HerokuRailsSaas
@@ -130,7 +131,7 @@ module HerokuRailsSaas
130
131
  creation_command "heroku config:add #{set_config} --app #{app_name}"
131
132
 
132
133
  # This fails on a newly created app
133
- system_with_echo("#{@config.cmd(app_env)} \"#{rails_cli(:runner)} 'Rails.cache.clear'\" --app #{app_name}")
134
+ system_with_echo("#{@config.cmd(app_env)} \"#{@config.rails_cli(:runner)} 'Rails.cache.clear'\" --app #{app_name}")
134
135
  end
135
136
  end
136
137
  end
@@ -223,7 +224,6 @@ module HerokuRailsSaas
223
224
  # cycles through each configured heroku app
224
225
  # yields the environment name, the app name, and the repo url
225
226
  def each_heroku_app
226
-
227
227
  if @config.apps.size == 0
228
228
  puts "\nNo heroku apps are configured. Run:
229
229
  rails generate heroku:config\n\n"
@@ -295,9 +295,5 @@ module HerokuRailsSaas
295
295
  Regexp.new("#{@config.class::SEPERATOR}(#{match})")
296
296
  end
297
297
 
298
- def rails_cli script
299
- Rails::VERSION::MAJOR < 3 ? ".script/#{script}" : "rails #{script}"
300
- end
301
-
302
298
  end
303
299
  end
@@ -75,7 +75,7 @@ namespace :heroku do
75
75
  Rake::Task["heroku:before_each_deploy"].invoke(app_name)
76
76
 
77
77
  cmd = HEROKU_CONFIG.cmd(heroku_env)
78
-
78
+
79
79
  if heroku_env[HEROKU_RUNNER.regex_for(:production)]
80
80
  all_tags = `git tag`
81
81
  target_tag = `git describe --tags --abbrev=0`.chomp # Set latest tag as default
@@ -102,16 +102,19 @@ namespace :heroku do
102
102
  puts "Unable to determine the current git branch, please checkout the branch you'd like to deploy." and exit(1) if to_deploy.empty?
103
103
  end
104
104
 
105
- @git_push_arguments ||= []
106
- @git_push_arguments << '--force'
105
+ @git_push_arguments ||= ['--force']
107
106
 
108
107
  system_with_echo "git push #{repo} #{@git_push_arguments.join(' ')} #{to_deploy}:master"
109
108
 
110
109
  system_with_echo "heroku maintenance:on --app #{app_name}"
111
110
 
112
111
  Rake::Task["heroku:setup:config"].invoke
113
- system_with_echo "#{cmd} rake --app #{app_name} db:migrate && heroku restart --app #{app_name}"
112
+ system_with_echo "#{cmd} rake --app #{app_name} db:migrate"
114
113
 
114
+ system_with_echo "#{cmd} \"#{HEROKU_CONFIG.rails_cli(:runner)} 'Rails.cache.clear'\" --app #{app_name}"
115
+
116
+ system_with_echo "heroku restart --app #{app_name}"
117
+
115
118
  system_with_echo "heroku maintenance:off --app #{app_name}"
116
119
 
117
120
  Rake::Task["heroku:after_each_deploy"].reenable
@@ -233,7 +236,7 @@ namespace :heroku do
233
236
  system_with_echo "heroku pgbackups:capture --app #{app_name}"
234
237
  dump = `heroku pgbackups --app #{app_name}`.split("\n").last.split(" ").first
235
238
  system_with_echo "mkdir -p #{HerokuRailsSaas::Config.root}/db/dumps"
236
- file = "#{HerokuRailsSaas::Config.root}/db/dumps/#{dump}.sql.gz"
239
+ file = "#{HerokuRailsSaas::Config.root}/db/dumps/#{app_name}-#{dump}.sql.gz"
237
240
  url = `heroku pgbackups:url --app #{app_name} #{dump}`.chomp
238
241
  system_with_echo "wget", url, "-O", file
239
242
 
@@ -12,3 +12,8 @@ collaborators:
12
12
  domains:
13
13
  development:
14
14
  - "mediocreapp.com"
15
+
16
+ scale:
17
+ development:
18
+ web: 1
19
+ worker: 0
@@ -156,7 +156,7 @@ module HerokuRailsSaas
156
156
  describe "#scale" do
157
157
  context "mediocrapp" do
158
158
  it "should include the scaling settings defined in 'all'" do
159
- @scale = @config.scale('mediocreapp')
159
+ @scale = @config.scale('mediocreapp:development')
160
160
  @scale['web'].should_not be_nil
161
161
  @scale['worker'].should_not be_nil
162
162
  @scale['web'].should eql 1
@@ -2,13 +2,21 @@ require 'spec_helper'
2
2
 
3
3
  module HerokuRailsSaas
4
4
  describe Runner do
5
- describe "each_heroku_app" do
6
- it "should return my apps" do
7
- pending
5
+ describe "#each_heroku_app" do
6
+ it "should return all apps in all environments" do
7
+ config_files = {:default => config_path("heroku-config.yml"), :apps => [config_path("awesomeapp.yml"), config_path("mediocreapp.yml")]}
8
+ config = Config.new(config_files)
9
+ runner = Runner.new(config)
10
+ runner.all_environments
11
+ runner.each_heroku_app {}.should == ["awesomeapp:production", "awesomeapp:staging", "mediocreapp:development"]
8
12
  end
9
13
 
10
14
  it "should not return a production app if @environment is not specified and there's only one app" do
11
- pending
15
+ config_files = {:default => config_path("heroku-config.yml"), :apps => [config_path("mediocreapp.yml")]}
16
+ config = Config.new(config_files)
17
+ runner = Runner.new(config)
18
+ runner.instance_variable_set("@environments", [])
19
+ lambda { runner.each_heroku_app }.should raise_error(SystemExit)
12
20
  end
13
21
  end
14
22
  end
data/spec/spec_helper.rb CHANGED
@@ -2,16 +2,38 @@ require 'heroku-rails-saas'
2
2
  require 'bundler/setup'
3
3
 
4
4
 
5
- RSpec.configure do |c|
6
- # setup fixtures path
7
- c.before(:all) do
5
+ RSpec.configure do |config|
6
+ config.before(:all) do
8
7
  @fixture_path = Pathname.new(File.join(File.dirname(__FILE__), "/fixtures"))
9
8
  raise "Fixture folder not found: #{@fixture_path}" unless @fixture_path.directory?
9
+ silence_output
10
+ end
11
+
12
+ config.after(:all) do
13
+ enable_output
10
14
  end
11
15
 
12
16
  # returns the file path of a fixture setting file
13
17
  def config_path(filename)
14
18
  @fixture_path.join(filename)
15
19
  end
20
+
21
+ # Redirects stderr and stdout to /dev/null.
22
+ def silence_output
23
+ @orig_stderr = $stderr
24
+ @orig_stdout = $stdout
25
+
26
+ # redirect stderr and stdout to /dev/null
27
+ $stderr = File.new('/dev/null', 'w')
28
+ $stdout = File.new('/dev/null', 'w')
29
+ end
30
+
31
+ # Replace stdout and stderr so anything else is output correctly.
32
+ def enable_output
33
+ $stderr = @orig_stderr
34
+ $stdout = @orig_stdout
35
+ @orig_stderr = nil
36
+ @orig_stdout = nil
37
+ end
16
38
  end
17
39
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: heroku-rails-saas
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,14 +9,15 @@ authors:
9
9
  - Glenn Roberts
10
10
  - Jacques Crocker
11
11
  - Lance Sanchez
12
+ - Chris Trinh
12
13
  autorequire:
13
14
  bindir: bin
14
15
  cert_chain: []
15
- date: 2012-05-04 00:00:00.000000000Z
16
+ date: 2012-08-14 00:00:00.000000000Z
16
17
  dependencies:
17
18
  - !ruby/object:Gem::Dependency
18
19
  name: heroku
19
- requirement: &2156355220 !ruby/object:Gem::Requirement
20
+ requirement: &2165278020 !ruby/object:Gem::Requirement
20
21
  none: false
21
22
  requirements:
22
23
  - - ! '>='
@@ -24,10 +25,10 @@ dependencies:
24
25
  version: 2.24.1
25
26
  type: :runtime
26
27
  prerelease: false
27
- version_requirements: *2156355220
28
+ version_requirements: *2165278020
28
29
  - !ruby/object:Gem::Dependency
29
30
  name: rspec
30
- requirement: &2156354200 !ruby/object:Gem::Requirement
31
+ requirement: &2165277300 !ruby/object:Gem::Requirement
31
32
  none: false
32
33
  requirements:
33
34
  - - ~>
@@ -35,7 +36,18 @@ dependencies:
35
36
  version: '2.0'
36
37
  type: :development
37
38
  prerelease: false
38
- version_requirements: *2156354200
39
+ version_requirements: *2165277300
40
+ - !ruby/object:Gem::Dependency
41
+ name: activesupport
42
+ requirement: &2165276480 !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: *2165276480
39
51
  description: Manage multiple Heroku instances/apps for a single Rails app using Rake.
40
52
  email: lance.sanchez@gmail.com
41
53
  executables: []
@@ -84,7 +96,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
84
96
  version: '0'
85
97
  segments:
86
98
  - 0
87
- hash: 3808687770431151887
99
+ hash: 2780192577745053897
88
100
  required_rubygems_version: !ruby/object:Gem::Requirement
89
101
  none: false
90
102
  requirements:
@@ -93,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
105
  version: '0'
94
106
  segments:
95
107
  - 0
96
- hash: 3808687770431151887
108
+ hash: 2780192577745053897
97
109
  requirements: []
98
110
  rubyforge_project: none
99
111
  rubygems_version: 1.8.6