heroku-rails 0.3.0 → 0.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/Gemfile.lock +4 -7
- data/heroku-rails.gemspec +1 -1
- data/lib/heroku-rails.rb +3 -3
- data/lib/heroku-rails/config.rb +76 -0
- data/lib/{heroku/rails → heroku-rails}/railtie.rb +1 -0
- data/lib/heroku-rails/runner.rb +256 -0
- data/lib/heroku/rails/tasks.rb +8 -6
- data/spec/heroku/rails/heroku_config_spec.rb +3 -3
- metadata +9 -20
- data/lib/heroku/rails/heroku_config.rb +0 -69
- data/lib/heroku/rails/heroku_runner.rb +0 -254
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
heroku-rails (0.3.
|
4
|
+
heroku-rails (0.3.1)
|
5
5
|
heroku (>= 1.11.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -10,14 +10,12 @@ GEM
|
|
10
10
|
archive-tar-minitar (0.5.2)
|
11
11
|
autotest (4.4.1)
|
12
12
|
columnize (0.3.1)
|
13
|
-
configuration (1.
|
13
|
+
configuration (1.2.0)
|
14
14
|
diff-lcs (1.1.2)
|
15
15
|
growl-glue (1.0.7)
|
16
|
-
heroku (1.
|
17
|
-
json_pure (>= 1.2.0, < 1.5.0)
|
16
|
+
heroku (1.20.1)
|
18
17
|
launchy (~> 0.3.2)
|
19
|
-
rest-client (
|
20
|
-
json_pure (1.4.6)
|
18
|
+
rest-client (< 1.7.0, >= 1.4.0)
|
21
19
|
launchy (0.3.7)
|
22
20
|
configuration (>= 0.0.5)
|
23
21
|
rake (>= 0.8.1)
|
@@ -60,7 +58,6 @@ PLATFORMS
|
|
60
58
|
DEPENDENCIES
|
61
59
|
autotest
|
62
60
|
growl-glue
|
63
|
-
heroku (>= 1.11.0)
|
64
61
|
heroku-rails!
|
65
62
|
rspec (~> 2.0)
|
66
63
|
ruby-debug
|
data/heroku-rails.gemspec
CHANGED
data/lib/heroku-rails.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
require 'heroku
|
2
|
-
require 'heroku
|
3
|
-
require 'heroku
|
1
|
+
require 'heroku-rails/config'
|
2
|
+
require 'heroku-rails/runner'
|
3
|
+
require 'heroku-rails/railtie' if defined?(::Rails::Railtie)
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module HerokuRails
|
2
|
+
class Config
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def root
|
6
|
+
@heroku_rails_root || ENV["RAILS_ROOT"] || "."
|
7
|
+
end
|
8
|
+
def root=(root)
|
9
|
+
@heroku_rails_root = root
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :settings
|
14
|
+
|
15
|
+
def initialize(config_filepath)
|
16
|
+
if File.exists?(config_filepath)
|
17
|
+
self.settings = YAML.load_file(config_filepath) || {}
|
18
|
+
else
|
19
|
+
self.settings = {}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def apps
|
24
|
+
self.settings['apps'] || {}
|
25
|
+
end
|
26
|
+
|
27
|
+
def app_names
|
28
|
+
apps.values
|
29
|
+
end
|
30
|
+
|
31
|
+
def app_environments
|
32
|
+
apps.keys
|
33
|
+
end
|
34
|
+
|
35
|
+
# return the stack setting for a particular app environment
|
36
|
+
def stack(app_env)
|
37
|
+
stacks = self.settings['stacks'] || {}
|
38
|
+
stacks[app_env] || stacks['all']
|
39
|
+
end
|
40
|
+
|
41
|
+
# pull out the config setting hash for a particular app environment
|
42
|
+
def config(app_env)
|
43
|
+
config = self.settings['config'] || {}
|
44
|
+
all = config['all'] || {}
|
45
|
+
|
46
|
+
# overwrite all configs with the environment specific ones
|
47
|
+
all.merge(config[app_env] || {})
|
48
|
+
end
|
49
|
+
|
50
|
+
# return a list of domains for a particular app environment
|
51
|
+
def domains(app_env)
|
52
|
+
domains = self.settings['domains'] || {}
|
53
|
+
domains[app_env] || []
|
54
|
+
end
|
55
|
+
|
56
|
+
# return a list of collaborators for a particular app environment
|
57
|
+
def collaborators(app_env)
|
58
|
+
app_setting_list('collaborators', app_env)
|
59
|
+
end
|
60
|
+
|
61
|
+
# return a list of addons for a particular app environment
|
62
|
+
def addons(app_env)
|
63
|
+
app_setting_list('addons', app_env)
|
64
|
+
end
|
65
|
+
|
66
|
+
protected
|
67
|
+
|
68
|
+
def app_setting_list(setting_key, app)
|
69
|
+
setting = self.settings[setting_key] || {}
|
70
|
+
all = setting['all'] || []
|
71
|
+
|
72
|
+
# add in collaborators from app environment to the ones defined in all
|
73
|
+
(all + (setting[app] || [])).uniq
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,256 @@
|
|
1
|
+
require 'heroku/client'
|
2
|
+
|
3
|
+
module HerokuRails
|
4
|
+
class Runner
|
5
|
+
def initialize(config)
|
6
|
+
@config = config
|
7
|
+
@environments = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def authorize
|
11
|
+
return if @heroku
|
12
|
+
|
13
|
+
# setup heroku username and password so we can start up a heroku client
|
14
|
+
credentials_path = File.expand_path("~/.heroku/credentials")
|
15
|
+
|
16
|
+
# read in the username,password so we can build the client
|
17
|
+
if File.exists?(credentials_path)
|
18
|
+
auth = File.read(credentials_path)
|
19
|
+
username, password = auth.split("\n")
|
20
|
+
@heroku = Heroku::Client.new(username, password)
|
21
|
+
else
|
22
|
+
puts "Heroku not set up. Run `heroku list` in order to input your credentials and try again"
|
23
|
+
exit(1)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# add a specific environment to the run list
|
28
|
+
def add_environment(env)
|
29
|
+
@environments << env
|
30
|
+
end
|
31
|
+
|
32
|
+
# use all environments
|
33
|
+
def all_environments
|
34
|
+
@environments = @config.app_environments
|
35
|
+
end
|
36
|
+
|
37
|
+
# setup apps (create if necessary)
|
38
|
+
def setup_apps
|
39
|
+
authorize unless @heroku
|
40
|
+
|
41
|
+
# get a list of all my current apps on Heroku (so we don't create dupes)
|
42
|
+
@my_apps = @heroku.list.map{|a| a.first}
|
43
|
+
|
44
|
+
each_heroku_app do |heroku_env, app_name, repo|
|
45
|
+
next if @my_apps.include?(app_name)
|
46
|
+
|
47
|
+
stack = @config.stack(heroku_env)
|
48
|
+
stack_option = " --stack #{stack}" if stack.to_s.size > 0
|
49
|
+
system_with_echo "heroku create #{app_name}#{stack_option} --remote #{app_name}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# setup the stacks for each app (migrating if necessary)
|
54
|
+
def setup_stacks
|
55
|
+
authorize unless @heroku
|
56
|
+
each_heroku_app do |heroku_env, app_name, repo|
|
57
|
+
# get the intended stack setting
|
58
|
+
stack = @config.stack(heroku_env)
|
59
|
+
|
60
|
+
# get the remote info about the app from heroku
|
61
|
+
heroku_app_info = @heroku.info(app_name) || {}
|
62
|
+
|
63
|
+
# if the stacks don't match, then perform a migration
|
64
|
+
if stack != heroku_app_info[:stack]
|
65
|
+
puts "Migrating the app: #{app_name} to the stack: #{stack}"
|
66
|
+
system_with_echo "heroku stack:migrate #{stack} --app #{app_name}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# setup the list of collaborators
|
72
|
+
def setup_collaborators
|
73
|
+
authorize unless @heroku
|
74
|
+
each_heroku_app do |heroku_env, app_name, repo|
|
75
|
+
# get the remote info about the app from heroku
|
76
|
+
heroku_app_info = @heroku.info(app_name) || {}
|
77
|
+
|
78
|
+
# get the intended list of collaborators to add
|
79
|
+
collaborator_emails = @config.collaborators(heroku_env)
|
80
|
+
|
81
|
+
# add current user to collaborator list (always)
|
82
|
+
collaborator_emails << @heroku.user unless collaborator_emails.include?(@heroku.user)
|
83
|
+
collaborator_emails << heroku_app_info[:owner] unless collaborator_emails.include?(heroku_app_info[:owner])
|
84
|
+
|
85
|
+
# get existing collaborators
|
86
|
+
existing_emails = heroku_app_info[:collaborators].to_a.map{|c| c[:email]}
|
87
|
+
|
88
|
+
# get the list of collaborators to delete
|
89
|
+
existing_emails.each do |existing_email|
|
90
|
+
# check to see if we need to delete this person
|
91
|
+
unless collaborator_emails.include?(existing_email)
|
92
|
+
# delete that collaborator if they arent on the approved list
|
93
|
+
system_with_echo "heroku sharing:remove #{existing_email} --app #{app_name}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# get the list of collaborators to add
|
98
|
+
collaborator_emails.each do |collaborator_email|
|
99
|
+
# check to see if we need to add this person
|
100
|
+
unless existing_emails.include?(collaborator_email)
|
101
|
+
# add the collaborator if they are not already on the server
|
102
|
+
system_with_echo "heroku sharing:add #{collaborator_email} --app #{app_name}"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# setup configuration
|
109
|
+
def setup_config
|
110
|
+
authorize unless @heroku
|
111
|
+
each_heroku_app do |heroku_env, app_name, repo|
|
112
|
+
# get the configuration that we are aiming towards
|
113
|
+
new_config = @config.config(heroku_env)
|
114
|
+
|
115
|
+
# default RACK_ENV to the heroku_env (unless its manually set to something else)
|
116
|
+
unless new_config["RACK_ENV"].to_s.length > 0
|
117
|
+
new_config["RACK_ENV"] = heroku_env
|
118
|
+
end
|
119
|
+
|
120
|
+
# get the existing config from heroku's servers
|
121
|
+
existing_config = @heroku.config_vars(app_name) || {}
|
122
|
+
|
123
|
+
# find the config variables to add
|
124
|
+
add_config = {}
|
125
|
+
new_config.each do |new_key, new_val|
|
126
|
+
add_config[new_key] = new_val unless existing_config[new_key] == new_val
|
127
|
+
end
|
128
|
+
|
129
|
+
# persist the changes onto heroku
|
130
|
+
unless add_config.empty?
|
131
|
+
# add the config
|
132
|
+
set_config = ""
|
133
|
+
add_config.each do |key, val|
|
134
|
+
set_config << "#{key}='#{val}' "
|
135
|
+
end
|
136
|
+
|
137
|
+
system_with_echo "heroku config:add #{set_config} --app #{app_name}"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# setup the addons for heroku
|
143
|
+
def setup_addons
|
144
|
+
authorize unless @heroku
|
145
|
+
each_heroku_app do |heroku_env, app_name, repo|
|
146
|
+
# get the addons that we are aiming towards
|
147
|
+
addons = @config.addons(heroku_env)
|
148
|
+
|
149
|
+
# get the addons that are already on the servers
|
150
|
+
existing_addons = (@heroku.installed_addons(app_name) || []).map{|a| a["name"]}
|
151
|
+
|
152
|
+
# all apps need the shared database
|
153
|
+
addons << "shared-database:5mb" unless addons.index("shared-database:5mb")
|
154
|
+
|
155
|
+
# add "custom_domains" if that addon doesnt already exist
|
156
|
+
# and we have domains configured for this app
|
157
|
+
addons << "custom_domains:basic" unless @config.domains(heroku_env).empty? or
|
158
|
+
addons.any?{|a| a =~ /custom_domains/} or
|
159
|
+
existing_addons.any?{|a| a =~ /custom_domains/}
|
160
|
+
|
161
|
+
# remove the addons that need to be removed
|
162
|
+
existing_addons.each do |existing_addon|
|
163
|
+
# check to see if we need to delete this addon
|
164
|
+
unless addons.include?(existing_addon)
|
165
|
+
# delete this addon if they arent on the approved list
|
166
|
+
system_with_echo "heroku addons:remove #{existing_addon} --app #{app_name}"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# add the addons that dont exist already
|
171
|
+
addons.each do |addon|
|
172
|
+
# check to see if we need to add this addon
|
173
|
+
unless existing_addons.include?(addon)
|
174
|
+
# add this addon if they are not already added
|
175
|
+
system_with_echo "heroku addons:add #{addon} --app #{app_name}"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# setup the domains for heroku
|
182
|
+
def setup_domains
|
183
|
+
authorize unless @heroku
|
184
|
+
each_heroku_app do |heroku_env, app_name, repo|
|
185
|
+
# get the domains that we are aiming towards
|
186
|
+
domains = @config.domains(heroku_env)
|
187
|
+
|
188
|
+
# get the domains that are already on the servers
|
189
|
+
existing_domains = (@heroku.list_domains(app_name) || []).map{|a| a[:domain]}
|
190
|
+
|
191
|
+
# remove the domains that need to be removed
|
192
|
+
existing_domains.each do |existing_domain|
|
193
|
+
# check to see if we need to delete this domain
|
194
|
+
unless domains.include?(existing_domain)
|
195
|
+
# delete this domain if they arent on the approved list
|
196
|
+
system_with_echo "heroku domains:remove #{existing_domain} --app #{app_name}"
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# add the domains that dont exist already
|
201
|
+
domains.each do |domain|
|
202
|
+
# check to see if we need to add this domain
|
203
|
+
unless existing_domains.include?(domain)
|
204
|
+
# add this domain if they are not already added
|
205
|
+
system_with_echo "heroku domains:add #{domain} --app #{app_name}"
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# cycles through each configured heroku app
|
212
|
+
# yields the environment name, the app name, and the repo url
|
213
|
+
def each_heroku_app
|
214
|
+
|
215
|
+
if @config.apps.size == 0
|
216
|
+
puts "\nNo heroku apps are configured. Run:
|
217
|
+
rails generate heroku:config\n\n"
|
218
|
+
puts "this will generate a default config/heroku.yml that you should edit"
|
219
|
+
puts "and then try running this command again"
|
220
|
+
|
221
|
+
exit(1)
|
222
|
+
end
|
223
|
+
|
224
|
+
if @environments.blank? && @config.apps.size == 1
|
225
|
+
@environments = [@config.app_environments.first]
|
226
|
+
end
|
227
|
+
|
228
|
+
if @environments.present?
|
229
|
+
@environments.each do |heroku_env|
|
230
|
+
app_name = @config.apps[heroku_env]
|
231
|
+
yield(heroku_env, app_name, "git@heroku.com:#{app_name}.git")
|
232
|
+
end
|
233
|
+
else
|
234
|
+
puts "\nYou must first specify at least one Heroku app:
|
235
|
+
rake <app> [<app>] <command>
|
236
|
+
rake production restart
|
237
|
+
rake demo staging deploy"
|
238
|
+
|
239
|
+
puts "\n\nYou can use also command all Heroku apps for this project:
|
240
|
+
rake all heroku:setup\n"
|
241
|
+
|
242
|
+
exit(1)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def system_with_echo(*args)
|
247
|
+
puts args.join(' ')
|
248
|
+
command(*args)
|
249
|
+
end
|
250
|
+
|
251
|
+
def command(*args)
|
252
|
+
system(*args)
|
253
|
+
end
|
254
|
+
|
255
|
+
end
|
256
|
+
end
|
data/lib/heroku/rails/tasks.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require 'heroku-rails'
|
2
|
+
|
3
|
+
HEROKU_CONFIG_FILE = File.join(HerokuRails::Config.root, 'config', 'heroku.yml')
|
4
|
+
HEROKU_CONFIG = HerokuRails::Config.new(HEROKU_CONFIG_FILE)
|
5
|
+
HEROKU_RUNNER = HerokuRails::Runner.new(HEROKU_CONFIG)
|
4
6
|
|
5
7
|
# create all the the environment specific tasks
|
6
8
|
(HEROKU_CONFIG.apps).each do |heroku_env, app_name|
|
@@ -186,14 +188,14 @@ namespace :heroku do
|
|
186
188
|
HEROKU_RUNNER.each_heroku_app do |heroku_env, app_name, repo|
|
187
189
|
system_with_echo "heroku pgdumps:capture --app #{app_name}"
|
188
190
|
dump = `heroku pgdumps --app #{app_name}`.split("\n").last.split(" ").first
|
189
|
-
system_with_echo "mkdir -p #{
|
190
|
-
file = "#{
|
191
|
+
system_with_echo "mkdir -p #{HerokuRails::Config.root}/db/dumps"
|
192
|
+
file = "#{HerokuRails::Config.root}/db/dumps/#{dump}.sql.gz"
|
191
193
|
url = `heroku pgdumps:url --app #{app_name} #{dump}`.chomp
|
192
194
|
system_with_echo "wget", url, "-O", file
|
193
195
|
|
194
196
|
# TODO: these are a bit distructive...
|
195
197
|
# system_with_echo "rake db:drop db:create"
|
196
|
-
# system_with_echo "gunzip -c #{file} | #{
|
198
|
+
# system_with_echo "gunzip -c #{file} | #{HerokuRails::Config.root}/script/dbconsole"
|
197
199
|
# system_with_echo "rake jobs:clear"
|
198
200
|
end
|
199
201
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
module
|
4
|
-
describe
|
3
|
+
module HerokuRails
|
4
|
+
describe Config do
|
5
5
|
before(:each) do
|
6
|
-
@config =
|
6
|
+
@config = Config.new(config_path("heroku-config.yml"))
|
7
7
|
end
|
8
8
|
|
9
9
|
it "should read the configuration file" do
|
metadata
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: heroku-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 3
|
8
|
-
- 0
|
9
|
-
version: 0.3.0
|
4
|
+
prerelease:
|
5
|
+
version: 0.3.1
|
10
6
|
platform: ruby
|
11
7
|
authors:
|
12
8
|
- Elijah Miller
|
@@ -16,7 +12,7 @@ autorequire:
|
|
16
12
|
bindir: bin
|
17
13
|
cert_chain: []
|
18
14
|
|
19
|
-
date:
|
15
|
+
date: 2011-04-08 00:00:00 -07:00
|
20
16
|
default_executable:
|
21
17
|
dependencies:
|
22
18
|
- !ruby/object:Gem::Dependency
|
@@ -26,10 +22,6 @@ dependencies:
|
|
26
22
|
requirements:
|
27
23
|
- - ">="
|
28
24
|
- !ruby/object:Gem::Version
|
29
|
-
segments:
|
30
|
-
- 1
|
31
|
-
- 11
|
32
|
-
- 0
|
33
25
|
version: 1.11.0
|
34
26
|
type: :runtime
|
35
27
|
prerelease: false
|
@@ -41,9 +33,6 @@ dependencies:
|
|
41
33
|
requirements:
|
42
34
|
- - ~>
|
43
35
|
- !ruby/object:Gem::Version
|
44
|
-
segments:
|
45
|
-
- 2
|
46
|
-
- 0
|
47
36
|
version: "2.0"
|
48
37
|
type: :development
|
49
38
|
prerelease: false
|
@@ -63,10 +52,10 @@ files:
|
|
63
52
|
- lib/generators/heroku/config_generator.rb
|
64
53
|
- lib/generators/templates/heroku.rake
|
65
54
|
- lib/generators/templates/heroku.yml
|
66
|
-
- lib/heroku/rails/heroku_config.rb
|
67
|
-
- lib/heroku/rails/heroku_runner.rb
|
68
|
-
- lib/heroku/rails/railtie.rb
|
69
55
|
- lib/heroku/rails/tasks.rb
|
56
|
+
- lib/heroku-rails/config.rb
|
57
|
+
- lib/heroku-rails/railtie.rb
|
58
|
+
- lib/heroku-rails/runner.rb
|
70
59
|
- lib/heroku-rails.rb
|
71
60
|
- spec/fixtures/heroku-config.yml
|
72
61
|
- spec/heroku/rails/heroku_config_spec.rb
|
@@ -94,7 +83,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
94
83
|
requirements:
|
95
84
|
- - ">="
|
96
85
|
- !ruby/object:Gem::Version
|
97
|
-
hash:
|
86
|
+
hash: 680656138277193896
|
98
87
|
segments:
|
99
88
|
- 0
|
100
89
|
version: "0"
|
@@ -103,14 +92,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
92
|
requirements:
|
104
93
|
- - ">="
|
105
94
|
- !ruby/object:Gem::Version
|
106
|
-
hash:
|
95
|
+
hash: 680656138277193896
|
107
96
|
segments:
|
108
97
|
- 0
|
109
98
|
version: "0"
|
110
99
|
requirements: []
|
111
100
|
|
112
101
|
rubyforge_project: none
|
113
|
-
rubygems_version: 1.
|
102
|
+
rubygems_version: 1.6.2
|
114
103
|
signing_key:
|
115
104
|
specification_version: 3
|
116
105
|
summary: Deployment and configuration tools for Heroku/Rails
|
@@ -1,69 +0,0 @@
|
|
1
|
-
module Heroku
|
2
|
-
module Rails
|
3
|
-
class HerokuConfig
|
4
|
-
|
5
|
-
attr_accessor :settings
|
6
|
-
|
7
|
-
def initialize(config_filepath)
|
8
|
-
if File.exists?(config_filepath)
|
9
|
-
self.settings = YAML.load_file(config_filepath) || {}
|
10
|
-
else
|
11
|
-
self.settings = {}
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def apps
|
16
|
-
self.settings['apps'] || {}
|
17
|
-
end
|
18
|
-
|
19
|
-
def app_names
|
20
|
-
apps.values
|
21
|
-
end
|
22
|
-
|
23
|
-
def app_environments
|
24
|
-
apps.keys
|
25
|
-
end
|
26
|
-
|
27
|
-
# return the stack setting for a particular app environment
|
28
|
-
def stack(app_env)
|
29
|
-
stacks = self.settings['stacks'] || {}
|
30
|
-
stacks[app_env] || stacks['all']
|
31
|
-
end
|
32
|
-
|
33
|
-
# pull out the config setting hash for a particular app environment
|
34
|
-
def config(app_env)
|
35
|
-
config = self.settings['config'] || {}
|
36
|
-
all = config['all'] || {}
|
37
|
-
|
38
|
-
# overwrite all configs with the environment specific ones
|
39
|
-
all.merge(config[app_env] || {})
|
40
|
-
end
|
41
|
-
|
42
|
-
# return a list of domains for a particular app environment
|
43
|
-
def domains(app_env)
|
44
|
-
domains = self.settings['domains'] || {}
|
45
|
-
domains[app_env] || []
|
46
|
-
end
|
47
|
-
|
48
|
-
# return a list of collaborators for a particular app environment
|
49
|
-
def collaborators(app_env)
|
50
|
-
app_setting_list('collaborators', app_env)
|
51
|
-
end
|
52
|
-
|
53
|
-
# return a list of addons for a particular app environment
|
54
|
-
def addons(app_env)
|
55
|
-
app_setting_list('addons', app_env)
|
56
|
-
end
|
57
|
-
|
58
|
-
protected
|
59
|
-
|
60
|
-
def app_setting_list(setting_key, app)
|
61
|
-
setting = self.settings[setting_key] || {}
|
62
|
-
all = setting['all'] || []
|
63
|
-
|
64
|
-
# add in collaborators from app environment to the ones defined in all
|
65
|
-
(all + (setting[app] || [])).uniq
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
@@ -1,254 +0,0 @@
|
|
1
|
-
require 'heroku/client'
|
2
|
-
|
3
|
-
module Heroku
|
4
|
-
module Rails
|
5
|
-
class HerokuRunner
|
6
|
-
def initialize(config)
|
7
|
-
@config = config
|
8
|
-
@environments = []
|
9
|
-
end
|
10
|
-
|
11
|
-
def authorize
|
12
|
-
return if @heroku
|
13
|
-
|
14
|
-
# setup heroku username and password so we can start up a heroku client
|
15
|
-
credentials_path = File.expand_path("~/.heroku/credentials")
|
16
|
-
|
17
|
-
# read in the username,password so we can build the client
|
18
|
-
if File.exists?(credentials_path)
|
19
|
-
auth = File.read(credentials_path)
|
20
|
-
username, password = auth.split("\n")
|
21
|
-
@heroku = Heroku::Client.new(username, password)
|
22
|
-
else
|
23
|
-
puts "Heroku not set up. Run `heroku list` in order to input your credentials and try again"
|
24
|
-
exit(1)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# add a specific environment to the run list
|
29
|
-
def add_environment(env)
|
30
|
-
@environments << env
|
31
|
-
end
|
32
|
-
|
33
|
-
# use all environments
|
34
|
-
def all_environments
|
35
|
-
@environments = @config.app_environments
|
36
|
-
end
|
37
|
-
|
38
|
-
# setup apps (create if necessary)
|
39
|
-
def setup_apps
|
40
|
-
authorize unless @heroku
|
41
|
-
|
42
|
-
# get a list of all my current apps on Heroku (so we don't create dupes)
|
43
|
-
@my_apps = @heroku.list.map{|a| a.first}
|
44
|
-
|
45
|
-
each_heroku_app do |heroku_env, app_name, repo|
|
46
|
-
next if @my_apps.include?(app_name)
|
47
|
-
|
48
|
-
stack = @config.stack(heroku_env)
|
49
|
-
stack_option = " --stack #{stack}" if stack.to_s.size > 0
|
50
|
-
system_with_echo "heroku create #{app_name}#{stack_option} --remote #{app_name}"
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
# setup the stacks for each app (migrating if necessary)
|
55
|
-
def setup_stacks
|
56
|
-
authorize unless @heroku
|
57
|
-
each_heroku_app do |heroku_env, app_name, repo|
|
58
|
-
# get the intended stack setting
|
59
|
-
stack = @config.stack(heroku_env)
|
60
|
-
|
61
|
-
# get the remote info about the app from heroku
|
62
|
-
heroku_app_info = @heroku.info(app_name) || {}
|
63
|
-
|
64
|
-
# if the stacks don't match, then perform a migration
|
65
|
-
if stack != heroku_app_info[:stack]
|
66
|
-
puts "Migrating the app: #{app_name} to the stack: #{stack}"
|
67
|
-
system_with_echo "heroku stack:migrate #{stack} --app #{app_name}"
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
# setup the list of collaborators
|
73
|
-
def setup_collaborators
|
74
|
-
authorize unless @heroku
|
75
|
-
each_heroku_app do |heroku_env, app_name, repo|
|
76
|
-
# get the remote info about the app from heroku
|
77
|
-
heroku_app_info = @heroku.info(app_name) || {}
|
78
|
-
|
79
|
-
# get the intended list of collaborators to add
|
80
|
-
collaborator_emails = @config.collaborators(heroku_env)
|
81
|
-
|
82
|
-
# get existing collaborators
|
83
|
-
existing_emails = heroku_app_info[:collaborators].to_a.map{|c| c[:email]}
|
84
|
-
|
85
|
-
# get the list of collaborators to delete
|
86
|
-
existing_emails.each do |existing_email|
|
87
|
-
# check to see if we need to delete this person
|
88
|
-
unless collaborator_emails.include?(existing_email)
|
89
|
-
# delete that collaborator if they arent on the approved list
|
90
|
-
system_with_echo "heroku sharing:remove #{existing_email} --app #{app_name}"
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
# get the list of collaborators to add
|
95
|
-
collaborator_emails.each do |collaborator_email|
|
96
|
-
# check to see if we need to add this person
|
97
|
-
unless existing_emails.include?(collaborator_email)
|
98
|
-
# add the collaborator if they are not already on the server
|
99
|
-
system_with_echo "heroku sharing:add #{collaborator_email} --app #{app_name}"
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
# setup configuration
|
106
|
-
def setup_config
|
107
|
-
authorize unless @heroku
|
108
|
-
each_heroku_app do |heroku_env, app_name, repo|
|
109
|
-
# get the configuration that we are aiming towards
|
110
|
-
new_config = @config.config(heroku_env)
|
111
|
-
|
112
|
-
# default RACK_ENV to the heroku_env (unless its manually set to something else)
|
113
|
-
unless new_config["RACK_ENV"].to_s.length > 0
|
114
|
-
new_config["RACK_ENV"] = heroku_env
|
115
|
-
end
|
116
|
-
|
117
|
-
# get the existing config from heroku's servers
|
118
|
-
existing_config = @heroku.config_vars(app_name) || {}
|
119
|
-
|
120
|
-
# find the config variables to add
|
121
|
-
add_config = {}
|
122
|
-
new_config.each do |new_key, new_val|
|
123
|
-
add_config[new_key] = new_val unless existing_config[new_key] == new_val
|
124
|
-
end
|
125
|
-
|
126
|
-
# persist the changes onto heroku
|
127
|
-
unless add_config.empty?
|
128
|
-
# add the config
|
129
|
-
set_config = ""
|
130
|
-
add_config.each do |key, val|
|
131
|
-
set_config << "#{key}='#{val}' "
|
132
|
-
end
|
133
|
-
|
134
|
-
system_with_echo "heroku config:add #{set_config} --app #{app_name}"
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
# setup the addons for heroku
|
140
|
-
def setup_addons
|
141
|
-
authorize unless @heroku
|
142
|
-
each_heroku_app do |heroku_env, app_name, repo|
|
143
|
-
# get the addons that we are aiming towards
|
144
|
-
addons = @config.addons(heroku_env)
|
145
|
-
|
146
|
-
# get the addons that are already on the servers
|
147
|
-
existing_addons = (@heroku.installed_addons(app_name) || []).map{|a| a["name"]}
|
148
|
-
|
149
|
-
# all apps need the shared database
|
150
|
-
addons << "shared-database:5mb" unless addons.index("shared-database:5mb")
|
151
|
-
|
152
|
-
# add "custom_domains" if that addon doesnt already exist
|
153
|
-
# and we have domains configured for this app
|
154
|
-
addons << "custom_domains:basic" unless @config.domains(heroku_env).empty? or
|
155
|
-
addons.any?{|a| a =~ /custom_domains/} or
|
156
|
-
existing_addons.any?{|a| a =~ /custom_domains/}
|
157
|
-
|
158
|
-
# remove the addons that need to be removed
|
159
|
-
existing_addons.each do |existing_addon|
|
160
|
-
# check to see if we need to delete this addon
|
161
|
-
unless addons.include?(existing_addon)
|
162
|
-
# delete this addon if they arent on the approved list
|
163
|
-
system_with_echo "heroku addons:remove #{existing_addon} --app #{app_name}"
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
# add the addons that dont exist already
|
168
|
-
addons.each do |addon|
|
169
|
-
# check to see if we need to add this addon
|
170
|
-
unless existing_addons.include?(addon)
|
171
|
-
# add this addon if they are not already added
|
172
|
-
system_with_echo "heroku addons:add #{addon} --app #{app_name}"
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
# setup the domains for heroku
|
179
|
-
def setup_domains
|
180
|
-
authorize unless @heroku
|
181
|
-
each_heroku_app do |heroku_env, app_name, repo|
|
182
|
-
# get the domains that we are aiming towards
|
183
|
-
domains = @config.domains(heroku_env)
|
184
|
-
|
185
|
-
# get the domains that are already on the servers
|
186
|
-
existing_domains = (@heroku.list_domains(app_name) || []).map{|a| a[:domain]}
|
187
|
-
|
188
|
-
# remove the domains that need to be removed
|
189
|
-
existing_domains.each do |existing_domain|
|
190
|
-
# check to see if we need to delete this domain
|
191
|
-
unless domains.include?(existing_domain)
|
192
|
-
# delete this domain if they arent on the approved list
|
193
|
-
system_with_echo "heroku domains:remove #{existing_domain} --app #{app_name}"
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
# add the domains that dont exist already
|
198
|
-
domains.each do |domain|
|
199
|
-
# check to see if we need to add this domain
|
200
|
-
unless existing_domains.include?(domain)
|
201
|
-
# add this domain if they are not already added
|
202
|
-
system_with_echo "heroku domains:add #{domain} --app #{app_name}"
|
203
|
-
end
|
204
|
-
end
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
# cycles through each configured heroku app
|
209
|
-
# yields the environment name, the app name, and the repo url
|
210
|
-
def each_heroku_app
|
211
|
-
|
212
|
-
if @config.apps.size == 0
|
213
|
-
puts "\nNo heroku apps are configured. Run:
|
214
|
-
rails generate heroku:config\n\n"
|
215
|
-
puts "this will generate a default config/heroku.yml that you should edit"
|
216
|
-
puts "and then try running this command again"
|
217
|
-
|
218
|
-
exit(1)
|
219
|
-
end
|
220
|
-
|
221
|
-
if @environments.blank? && @config.apps.size == 1
|
222
|
-
@environments = [@config.app_environments.first]
|
223
|
-
end
|
224
|
-
|
225
|
-
if @environments.present?
|
226
|
-
@environments.each do |heroku_env|
|
227
|
-
app_name = @config.apps[heroku_env]
|
228
|
-
yield(heroku_env, app_name, "git@heroku.com:#{app_name}.git")
|
229
|
-
end
|
230
|
-
else
|
231
|
-
puts "\nYou must first specify at least one Heroku app:
|
232
|
-
rake <app> [<app>] <command>
|
233
|
-
rake production restart
|
234
|
-
rake demo staging deploy"
|
235
|
-
|
236
|
-
puts "\n\nYou can use also command all Heroku apps for this project:
|
237
|
-
rake all heroku:setup\n"
|
238
|
-
|
239
|
-
exit(1)
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
def system_with_echo(*args)
|
244
|
-
puts args.join(' ')
|
245
|
-
command(*args)
|
246
|
-
end
|
247
|
-
|
248
|
-
def command(*args)
|
249
|
-
system(*args)
|
250
|
-
end
|
251
|
-
|
252
|
-
end
|
253
|
-
end
|
254
|
-
end
|