kibo 0.1.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -1
- data/Gemfile.lock +46 -0
- data/kibo.gemspec +2 -2
- data/lib/kibo/bin/yuicompressor-2.4.7.jar +0 -0
- data/lib/kibo/commandline.rb +46 -55
- data/lib/kibo/commands/compress.rb +85 -0
- data/lib/kibo/commands/create.rb +56 -0
- data/lib/kibo/commands/deploy.rb +69 -0
- data/lib/kibo/commands/generate.rb +53 -0
- data/lib/kibo/commands/info.rb +19 -0
- data/lib/kibo/commands/reconfigure.rb +12 -0
- data/lib/kibo/commands/spin.rb +39 -0
- data/lib/kibo/commands.rb +44 -0
- data/lib/kibo/config.rb +22 -10
- data/lib/kibo/helpers/heroku.rb +75 -0
- data/lib/kibo/helpers/info.rb +50 -0
- data/lib/kibo/helpers.rb +70 -0
- data/lib/kibo/log.rb +29 -3
- data/lib/kibo/system.rb +32 -12
- data/lib/kibo/version.rb +1 -1
- data/lib/kibo.rb +10 -196
- data/man/kibo.1 +65 -12
- data/man/kibo.1.html +63 -19
- data/man/kibo.1.markdown +57 -17
- data/man/kibo.1.ronn +55 -17
- metadata +34 -5
@@ -0,0 +1,75 @@
|
|
1
|
+
# It would be great if we could just use Heroku.read_credentials or `heroku whoami`
|
2
|
+
# to check for a user's current login. Well, we can't:
|
3
|
+
#
|
4
|
+
# - since heroku aggressively pushes its heroku toolbelt people
|
5
|
+
# might be forced to uninstall the heroku gem.
|
6
|
+
# - `heroku whoami` blocks for input, if the user is not logged in.
|
7
|
+
#
|
8
|
+
# Hence this code, which is based on code from the heroku gem.
|
9
|
+
#
|
10
|
+
# == Copyright and licensing ==================================================
|
11
|
+
#
|
12
|
+
# The heroku gem is licensed under the terms of the MIT license,
|
13
|
+
# see the file License.MIT.
|
14
|
+
#
|
15
|
+
# The heroku has been created by Adam Wiggins, and is currently maintained
|
16
|
+
# by Wesley Beary.
|
17
|
+
module Kibo::Helpers::Heroku
|
18
|
+
require "netrc"
|
19
|
+
|
20
|
+
def whoami
|
21
|
+
(read_credentials || []).first
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def host
|
27
|
+
ENV['HEROKU_HOST'] || default_host
|
28
|
+
end
|
29
|
+
|
30
|
+
def default_host
|
31
|
+
"heroku.com"
|
32
|
+
end
|
33
|
+
|
34
|
+
def netrc_path
|
35
|
+
default = Netrc.default_path
|
36
|
+
encrypted = default + ".gpg"
|
37
|
+
if File.exists?(encrypted)
|
38
|
+
encrypted
|
39
|
+
else
|
40
|
+
default
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def netrc # :nodoc:
|
45
|
+
@netrc ||= begin
|
46
|
+
File.exists?(netrc_path) && Netrc.read(netrc_path)
|
47
|
+
rescue => error
|
48
|
+
if error.message =~ /^Permission bits for/
|
49
|
+
perm = File.stat(netrc_path).mode & 0777
|
50
|
+
abort("Permissions #{perm} for '#{netrc_path}' are too open. You should run `chmod 0600 #{netrc_path}` so that your credentials are NOT accessible by others.")
|
51
|
+
else
|
52
|
+
raise error
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def read_credentials
|
58
|
+
if ENV['HEROKU_API_KEY']
|
59
|
+
['', ENV['HEROKU_API_KEY']]
|
60
|
+
else
|
61
|
+
# read netrc credentials if they exist
|
62
|
+
if netrc
|
63
|
+
# force migration of long api tokens (80 chars) to short ones (40)
|
64
|
+
# #write_credentials rewrites both api.* and code.*
|
65
|
+
credentials = netrc["api.#{host}"]
|
66
|
+
if credentials && credentials[1].length > 40
|
67
|
+
@credentials = [ credentials[0], credentials[1][0,40] ]
|
68
|
+
write_credentials
|
69
|
+
end
|
70
|
+
|
71
|
+
netrc["api.#{host}"]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class Kibo::Helpers::Info < Array
|
2
|
+
def self.print(out = STDOUT, &block)
|
3
|
+
out.puts build(&block).to_s
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.build(&block)
|
7
|
+
info = new
|
8
|
+
yield info
|
9
|
+
info
|
10
|
+
end
|
11
|
+
|
12
|
+
def head(msg)
|
13
|
+
push [ :head, msg ]
|
14
|
+
end
|
15
|
+
|
16
|
+
def line(msg, value)
|
17
|
+
push [ :line, msg, value ]
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
key_length = map do |kind, msg, value|
|
22
|
+
kind == :line ? msg.length : 0
|
23
|
+
end.max
|
24
|
+
|
25
|
+
key_length = 60 if key_length > 60
|
26
|
+
|
27
|
+
key_format = "%#{key_length + 4}s"
|
28
|
+
|
29
|
+
map do |kind, msg, value|
|
30
|
+
case kind
|
31
|
+
when :head
|
32
|
+
"== #{msg} " + "=" * (100 - msg.length)
|
33
|
+
when :line
|
34
|
+
case value
|
35
|
+
when [], nil then value = "<none>"
|
36
|
+
when Array then value = value.map(&:inspect).join(", ")
|
37
|
+
end
|
38
|
+
|
39
|
+
if msg == ""
|
40
|
+
"#{key_format % msg} #{value}"
|
41
|
+
elsif msg.length > key_length
|
42
|
+
msg = msg[0..20] + "..." + msg[(25 - key_length) ..-1]
|
43
|
+
"#{key_format % msg}: #{value}"
|
44
|
+
else
|
45
|
+
"#{key_format % msg}: #{value}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end.join("\n")
|
49
|
+
end
|
50
|
+
end
|
data/lib/kibo/helpers.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
module Kibo::Helpers
|
2
|
+
end
|
3
|
+
|
4
|
+
require_relative "./helpers/heroku"
|
5
|
+
require_relative "./helpers/info"
|
6
|
+
|
7
|
+
module Kibo::Helpers
|
8
|
+
extend self
|
9
|
+
|
10
|
+
extend Heroku
|
11
|
+
|
12
|
+
def check_missing_remotes(mode = :warn)
|
13
|
+
return if missing_remotes.empty?
|
14
|
+
|
15
|
+
if mode == :warn
|
16
|
+
W "Ignoring missing remote(s)", *missing_remotes
|
17
|
+
return
|
18
|
+
end
|
19
|
+
|
20
|
+
E <<-MSG
|
21
|
+
Missing remote(s): #{missing_remotes.map(&:inspect).join(", ")}. Run
|
22
|
+
|
23
|
+
kibo --environment #{environment} create --all # ... to create all missing remotes.
|
24
|
+
kibo --environment #{environment} spinup --force # ... to ignore missing remotes.
|
25
|
+
|
26
|
+
MSG
|
27
|
+
end
|
28
|
+
|
29
|
+
# -- configure remotes ----------------------------------------------
|
30
|
+
|
31
|
+
def configure_remote!(remote)
|
32
|
+
heroku "config:set",
|
33
|
+
"RACK_ENV=#{environment}",
|
34
|
+
"RAILS_ENV=#{environment}",
|
35
|
+
"INSTANCE=#{instance_for_remote(remote)}",
|
36
|
+
"--app", remote
|
37
|
+
end
|
38
|
+
|
39
|
+
def instance_for_remote(remote)
|
40
|
+
remote[config.namespace.length + 1 .. -1]
|
41
|
+
end
|
42
|
+
|
43
|
+
def configure_remote(remote)
|
44
|
+
# the correct value for the INSTANCE configuration setting is the
|
45
|
+
# name of the of the remote without the namespace part; e.g. the
|
46
|
+
# INSTANCE for the remote named "bountyhill-staging-twirl2" is
|
47
|
+
# "staging-twirl2".
|
48
|
+
instance = remote[config.namespace.length + 1 .. -1]
|
49
|
+
current_instance = heroku "config:get", "INSTANCE", "--app", remote
|
50
|
+
return if instance == current_instance
|
51
|
+
end
|
52
|
+
|
53
|
+
# -- which remotes are defined, present and configured --------------
|
54
|
+
|
55
|
+
def expected_remotes
|
56
|
+
namespace, environment = Kibo.config.namespace, Kibo.environment
|
57
|
+
|
58
|
+
Kibo.config.processes.map do |name, count|
|
59
|
+
1.upto(count).map { |idx| "#{namespace}-#{environment}-#{name}#{idx}" }
|
60
|
+
end.flatten.sort
|
61
|
+
end
|
62
|
+
|
63
|
+
def configured_remotes
|
64
|
+
Kibo.config.remotes_by_process.values.flatten
|
65
|
+
end
|
66
|
+
|
67
|
+
def missing_remotes
|
68
|
+
expected_remotes - configured_remotes
|
69
|
+
end
|
70
|
+
end
|
data/lib/kibo/log.rb
CHANGED
@@ -1,18 +1,44 @@
|
|
1
|
+
require "bundler/ui"
|
2
|
+
require "thor/shell"
|
3
|
+
|
4
|
+
UI = Bundler::UI::Shell.new(Thor::Shell::Color.new)
|
5
|
+
|
1
6
|
def log_message(msg, *args)
|
2
7
|
return msg if args.empty?
|
3
8
|
"#{msg}: " + args.map(&:inspect).join(", ")
|
4
9
|
end
|
5
10
|
|
6
11
|
def D(*args)
|
7
|
-
|
12
|
+
UI.info log_message(*args)
|
8
13
|
end
|
9
14
|
|
10
15
|
def W(*args)
|
11
|
-
|
16
|
+
UI.warn log_message(*args)
|
12
17
|
end
|
13
18
|
|
14
19
|
def E(*args)
|
15
|
-
|
20
|
+
UI.error log_message(*args)
|
16
21
|
exit 1
|
17
22
|
end
|
18
23
|
|
24
|
+
def B(*args, &block)
|
25
|
+
msg = log_message(*args)
|
26
|
+
W msg
|
27
|
+
|
28
|
+
start = Time.now
|
29
|
+
yield.tap do
|
30
|
+
W "#{msg}: #{(1000 * (Time.now - start)).to_i} msecs."
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Success!
|
35
|
+
def S(*args)
|
36
|
+
UI.confirm log_message(*args)
|
37
|
+
end
|
38
|
+
|
39
|
+
def confirm!(msg)
|
40
|
+
puts msg
|
41
|
+
puts "\n\nPress ^C to abort or return to continue."
|
42
|
+
|
43
|
+
STDIN.readline
|
44
|
+
end
|
data/lib/kibo/system.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Kibo::System
|
2
2
|
extend self
|
3
|
-
|
3
|
+
|
4
4
|
def heroku(*args)
|
5
5
|
sys! "heroku", *args
|
6
6
|
end
|
@@ -10,22 +10,42 @@ module Kibo::System
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def sys(*args)
|
13
|
+
cmd = build_command(*args)
|
14
|
+
result = Kernel.send "`", "bash -c \"#{cmd}\""
|
15
|
+
if command_succeeded?(cmd)
|
16
|
+
result.chomp
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def sys!(*args)
|
21
|
+
sys(*args) || exit(1)
|
22
|
+
end
|
23
|
+
|
24
|
+
def sh(*args)
|
25
|
+
cmd = build_command(*args)
|
26
|
+
system(cmd)
|
27
|
+
command_succeeded?(cmd)
|
28
|
+
end
|
29
|
+
|
30
|
+
def sh!(*args)
|
31
|
+
sh(*args) || exit(1)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def build_command(*args)
|
13
37
|
quiet = args.pop if args.last == :quiet
|
38
|
+
args[0].sub!(/^kibo\b/, $0)
|
14
39
|
cmd = args.map(&:to_s).join(" ")
|
15
40
|
W cmd unless quiet
|
16
|
-
|
17
|
-
# A command is run because it either is "quiet", i.e. is non-obstrusive anyway,
|
18
|
-
# or we are not in a dry. Dry run mode could go with some improvements, though.
|
19
|
-
if quiet || !Kibo::CommandLine.dry?
|
20
|
-
stdout = Kernel.send "`", "bash -c \"#{cmd}\""
|
21
|
-
stdout.chomp if $?.exitstatus == 0
|
22
|
-
else
|
23
|
-
""
|
24
|
-
end
|
41
|
+
cmd
|
25
42
|
end
|
26
43
|
|
27
|
-
def
|
28
|
-
|
44
|
+
def command_succeeded?(cmd)
|
45
|
+
return true if $?.exitstatus == 0
|
46
|
+
|
47
|
+
UI.error("Command failed: #{cmd}")
|
48
|
+
false
|
29
49
|
end
|
30
50
|
end
|
31
51
|
|
data/lib/kibo/version.rb
CHANGED
data/lib/kibo.rb
CHANGED
@@ -7,215 +7,29 @@ end
|
|
7
7
|
require_relative "kibo/log"
|
8
8
|
require_relative "kibo/system"
|
9
9
|
require_relative "kibo/config"
|
10
|
+
require_relative "kibo/commands"
|
10
11
|
require_relative "kibo/commandline"
|
11
12
|
|
12
13
|
module Kibo
|
13
14
|
extend self
|
14
|
-
|
15
|
+
|
15
16
|
def config
|
16
|
-
@config ||= Config.new(
|
17
|
+
@config ||= Config.new(kibofile)
|
17
18
|
end
|
18
19
|
|
19
20
|
def environment
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
def expected_remotes
|
24
|
-
config.processes.inject([]) do |ary, (name, count)|
|
25
|
-
ary.concat 1.upto(count).map { |idx| "#{config.namespace}-#{environment}-#{name}#{idx}" }
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def configured_remotes
|
30
|
-
config.remotes_by_process.values.flatten
|
31
|
-
end
|
32
|
-
|
33
|
-
def missing_remotes
|
34
|
-
expected_remotes - configured_remotes
|
35
|
-
end
|
36
|
-
|
37
|
-
# -- configure a remote
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
def instance_for_remote(remote)
|
42
|
-
remote[config.namespace.length + 1 .. -1]
|
43
|
-
end
|
44
|
-
|
45
|
-
public
|
46
|
-
|
47
|
-
def configure_remote!(remote)
|
48
|
-
heroku "config:set",
|
49
|
-
"RACK_ENV=#{environment}",
|
50
|
-
"RAILS_ENV=#{environment}",
|
51
|
-
"INSTANCE=#{instance_for_remote(remote)}",
|
52
|
-
"--app", remote
|
53
|
-
end
|
54
|
-
|
55
|
-
def configure_remote(remote)
|
56
|
-
# the correct value for the INSTANCE configuration setting is the
|
57
|
-
# name of the of the remote without the namespace part; e.g. the
|
58
|
-
# INSTANCE for the remote named "bountyhill-staging-twirl2" is
|
59
|
-
# "staging-twirl2".
|
60
|
-
instance = remote[config.namespace.length + 1 .. -1]
|
61
|
-
current_instance = heroku "config:get", "INSTANCE", "--app", remote
|
62
|
-
return if instance == current_instance
|
63
|
-
end
|
64
|
-
|
65
|
-
# --spin up/spin down remotes
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
def spin(processes)
|
70
|
-
config.remotes_by_process.each do |name, remotes|
|
71
|
-
number_of_processes = processes[name] || 0
|
72
|
-
|
73
|
-
remotes.each do |remote|
|
74
|
-
if number_of_processes > 0
|
75
|
-
configure_remote remote
|
76
|
-
heroku "ps:scale", "#{name}=1", "--app", remote
|
77
|
-
number_of_processes -= 1
|
78
|
-
else
|
79
|
-
heroku "ps:scale", "#{name}=0", "--app", remote
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
if number_of_processes > 0
|
84
|
-
W "Missing #{name} remote(s)", number_of_processes
|
85
|
-
end
|
86
|
-
end
|
21
|
+
CommandLine.environment
|
87
22
|
end
|
88
23
|
|
89
|
-
|
90
|
-
|
91
|
-
def spinup
|
92
|
-
check_missing_remotes(CommandLine.force? ? :warn : :error)
|
93
|
-
spin config.processes
|
94
|
-
end
|
95
|
-
|
96
|
-
def spindown
|
97
|
-
spin({})
|
98
|
-
end
|
99
|
-
|
100
|
-
# reconfigure existing remotes
|
101
|
-
public
|
102
|
-
|
103
|
-
# kibo [options] reconfigure ... reconfigure all existing remotes
|
104
|
-
def reconfigure
|
105
|
-
check_missing_remotes :warn
|
106
|
-
|
107
|
-
configured_remotes.each do |remote|
|
108
|
-
configure_remote! remote
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
private
|
113
|
-
|
114
|
-
def prepare_deployment
|
115
|
-
end
|
116
|
-
|
117
|
-
def deploy_remote!(remote)
|
118
|
-
git "push", remote, "master"
|
119
|
-
end
|
120
|
-
|
121
|
-
public
|
122
|
-
|
123
|
-
def deploy
|
124
|
-
check_missing_remotes(CommandLine.force? ? :warn : :error)
|
125
|
-
|
126
|
-
prepare_deployment
|
127
|
-
configured_remotes.each do |remote|
|
128
|
-
deploy_remote! remote
|
129
|
-
end
|
130
|
-
|
131
|
-
W "Deployment succeeded."
|
24
|
+
def run
|
25
|
+
Commands.send CommandLine.subcommand
|
132
26
|
end
|
133
|
-
|
134
|
-
private
|
135
|
-
|
136
|
-
def check_missing_remotes(mode = :warn)
|
137
|
-
return if missing_remotes.empty?
|
138
|
-
|
139
|
-
if mode == :warn
|
140
|
-
W "Ignoring missing remote(s)", *missing_remotes
|
141
|
-
return
|
142
|
-
end
|
143
|
-
|
144
|
-
E <<-MSG
|
145
|
-
Missing remote(s): #{missing_remotes.map(&:inspect).join(", ")}. Run
|
146
27
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
MSG
|
28
|
+
def command_line
|
29
|
+
CommandLine
|
151
30
|
end
|
152
|
-
|
153
|
-
public
|
154
|
-
|
155
|
-
def create
|
156
|
-
verify_heroku_login
|
157
|
-
|
158
|
-
if CommandLine.all?
|
159
|
-
instances = missing_remotes
|
160
|
-
if instances.empty?
|
161
|
-
W "Nothing to do."
|
162
|
-
exit 0
|
163
|
-
end
|
164
|
-
else
|
165
|
-
instances = CommandLine.args
|
166
|
-
if instances.empty?
|
167
|
-
W "Add the names of the remotes to create on the command line or use the --all parameter."
|
168
|
-
exit 0
|
169
|
-
end
|
170
31
|
|
171
|
-
|
172
|
-
|
173
|
-
unless extra_instances.empty?
|
174
|
-
E <<-MSG
|
175
|
-
kibo cannot create these instances for you: #{extra_instances.map(&:inspect).join(", ")}, because I don't not know anything about these.
|
176
|
-
MSG
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
confirm! <<-MSG
|
181
|
-
I am going to create these instances: #{instances.map(&:inspect).join(", ")}. Is this what you want? Note:
|
182
|
-
You are logged in at heroku as #{config.heroku}.
|
183
|
-
MSG
|
184
|
-
|
185
|
-
instances.each do |instance|
|
186
|
-
create_instance(instance)
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
def confirm!(msg)
|
191
|
-
puts msg
|
192
|
-
puts "\n\nPress ^C to abort or return to continue."
|
193
|
-
|
194
|
-
STDIN.read
|
195
|
-
end
|
196
|
-
|
197
|
-
private
|
198
|
-
|
199
|
-
def verify_heroku_login
|
200
|
-
(Heroku::Auth.read_credentials || []).first.tap do |whoami|
|
201
|
-
msg = if !whoami
|
202
|
-
"Please log into heroku as #{config.heroku.inspect}."
|
203
|
-
elsif whoami != config.heroku
|
204
|
-
"You are currently logged into heroku as #{whoami.inspect}; please log in as #{config.heroku.inspect}."
|
205
|
-
end
|
206
|
-
|
207
|
-
E "#{msg}\n\n\theroku auth:login" if msg
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
def create_instance(remote)
|
212
|
-
# TODO: Test whether these instances already exist, using `heroku apps`
|
213
|
-
heroku "apps:create", remote, "--remote", remote
|
214
|
-
end
|
215
|
-
|
216
|
-
public
|
217
|
-
|
218
|
-
def run
|
219
|
-
self.send CommandLine.subcommand
|
32
|
+
def kibofile
|
33
|
+
command_line.kibofile
|
220
34
|
end
|
221
35
|
end
|
data/man/kibo.1
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
.\" generated with Ronn/v0.7.3
|
2
2
|
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
3
3
|
.
|
4
|
-
.TH "KIBO" "1" "
|
4
|
+
.TH "KIBO" "1" "September 2012" "Kibo 0.3.0" "Kibo Manual"
|
5
5
|
.
|
6
6
|
.SH "NAME"
|
7
7
|
\fBkibo\fR \- manage heroku applications
|
@@ -21,41 +21,94 @@
|
|
21
21
|
.br
|
22
22
|
\fBkibo [options] reconfigure\fR
|
23
23
|
.
|
24
|
+
.br
|
25
|
+
\fBkibo [options] generate\fR
|
26
|
+
.
|
24
27
|
.SH "DESCRIPTION"
|
25
|
-
kibo
|
28
|
+
kibo manages multiple application roles on single heroku dynos\.
|
26
29
|
.
|
27
30
|
.SH "DESCRIPTION"
|
28
|
-
|
31
|
+
Kibo is a perfect addition to Procfile based deployment on heroku\.com\. While heroku itself provides adequate tools to manage a single application on multiple dynos, Kibo adds tools to manage multiple application roles on single dynos with automatic instance provisioning\.
|
32
|
+
.
|
33
|
+
.P
|
34
|
+
The application roles are read from the Procfile (see foreman(1))\. The concurrency options \- i\.e\. the number of applications to run each role \- is read from the Kibofile\.
|
35
|
+
.
|
36
|
+
.SH "INSTANCE PROVISIONING"
|
37
|
+
Each instance gets automatically configured using `heroku config\. kibo sets the environment variables INSTANCE, RAILS_ENV and RACK_ENV to reflect instance role and number and runtime environment\.
|
38
|
+
.
|
39
|
+
.IP "" 4
|
40
|
+
.
|
41
|
+
.nf
|
42
|
+
|
43
|
+
INSTANCE="kibo\-staging\-web1"
|
44
|
+
RAILS_ENV="staging"
|
45
|
+
RACK_ENV="staging"
|
46
|
+
.
|
47
|
+
.fi
|
48
|
+
.
|
49
|
+
.IP "" 0
|
29
50
|
.
|
30
51
|
.SH "GLOBAL OPTIONS"
|
31
52
|
The following options control how kibo is run:
|
32
53
|
.
|
33
54
|
.TP
|
34
55
|
\fB\-e\fR, \fB\-\-environment\fR
|
35
|
-
Set the target environment\.
|
56
|
+
Set the target environment\. Defaults to "staging"
|
36
57
|
.
|
37
58
|
.TP
|
38
59
|
\fB\-k\fR, \fB\-\-kibofile\fR
|
39
|
-
Specify
|
60
|
+
Specify an alternate Kibofile to use\.
|
40
61
|
.
|
41
62
|
.TP
|
42
63
|
\fB\-p\fR, \fB\-\-procfile\fR
|
43
|
-
Specify an alternate Procfile to
|
64
|
+
Specify an alternate Procfile to use\.
|
44
65
|
.
|
45
66
|
.SH "Kibofile"
|
46
|
-
|
67
|
+
A Kibofile scaffold can be generated via \fBkibo generate\fR\. The following is an example:
|
47
68
|
.
|
48
69
|
.IP "" 4
|
49
70
|
.
|
50
71
|
.nf
|
51
72
|
|
73
|
+
kibo:
|
74
|
+
# The email of the heroku account to create app instances on heroku\.
|
75
|
+
heroku: user@domain\.com
|
76
|
+
# You instances will be called \'kiboex\-staging\-web0\', \'kiboex\-production\-worker0\', etc\.
|
77
|
+
namespace: kibo
|
52
78
|
defaults:
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
twirl: 1
|
79
|
+
procfile: Procfile\.other
|
80
|
+
web: 1
|
81
|
+
worker: 1
|
57
82
|
production:
|
58
|
-
|
83
|
+
web: 1
|
84
|
+
worker: 2
|
85
|
+
.
|
86
|
+
.fi
|
87
|
+
.
|
88
|
+
.IP "" 0
|
89
|
+
.
|
90
|
+
.P
|
91
|
+
This defines the roles "web" and "worker", which are running at one resp\. two instances in the "production" environment\.
|
92
|
+
.
|
93
|
+
.SH "Example session"
|
94
|
+
This is a session using the example Kibofile from above:
|
95
|
+
.
|
96
|
+
.IP "" 4
|
97
|
+
.
|
98
|
+
.nf
|
99
|
+
|
100
|
+
# creates the heroku applications "kibo\-production\-web1",
|
101
|
+
# "kibo\-production\-worker1", and "kibo\-production\-worker2"\.
|
102
|
+
kibo \-e production create
|
103
|
+
|
104
|
+
# deploy all applications\.
|
105
|
+
kibo \-e production deploy
|
106
|
+
|
107
|
+
# start all instances
|
108
|
+
kibo \-e production spinup
|
109
|
+
|
110
|
+
# stop all instances
|
111
|
+
kibo \-e production spindown
|
59
112
|
.
|
60
113
|
.fi
|
61
114
|
.
|