strobe 0.1.0.beta.2 → 0.1.0.beta.3
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/strobe/cli/main.rb +119 -10
- data/lib/strobe/cli/table.rb +19 -7
- data/lib/strobe/cli.rb +8 -1
- data/lib/strobe/collection.rb +4 -0
- data/lib/strobe/connection.rb +4 -6
- data/lib/strobe/resources/application.rb +64 -16
- metadata +3 -3
data/lib/strobe/cli/main.rb
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
module Strobe
|
2
2
|
class CLI::Main < CLI
|
3
3
|
|
4
|
+
def help(*args)
|
5
|
+
if args.first == "users"
|
6
|
+
CLI::Users.start( [ "help" ] + args[1..-1] )
|
7
|
+
else
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
4
12
|
action "users", 'manage users' do |*args|
|
5
13
|
argv = $ARGV[1..-1]
|
6
14
|
argv = [ 'list' ] + argv if args.empty?
|
@@ -55,7 +63,9 @@ module Strobe
|
|
55
63
|
end
|
56
64
|
|
57
65
|
application_path_option
|
58
|
-
method_option
|
66
|
+
method_option "staging", :type => :boolean, :banner => "deploy to a staging environment"
|
67
|
+
method_option "sc-build", :type => :boolean, :banner => "run `sc-build -c` before deploying"
|
68
|
+
method_option "no-sc-build", :type => :boolean, :banner => "skip the `sc-build -c` step"
|
59
69
|
action "deploy", "deploy your application to Strobe" do
|
60
70
|
ensure_computer_is_registered
|
61
71
|
|
@@ -77,17 +87,56 @@ module Strobe
|
|
77
87
|
end
|
78
88
|
end
|
79
89
|
|
80
|
-
|
90
|
+
run_sc_build
|
91
|
+
|
92
|
+
if STDOUT.tty?
|
93
|
+
thread = nil
|
94
|
+
read, write = IO.pipe
|
95
|
+
|
96
|
+
upload_callback = lambda do |percentage|
|
97
|
+
if percentage
|
98
|
+
width = 50
|
99
|
+
left = ( percentage * width ).round
|
100
|
+
right = ( ( 1.0 - percentage ) * width ).round
|
101
|
+
|
102
|
+
if left < width
|
103
|
+
right -= 1
|
104
|
+
arrow = ">"
|
105
|
+
end
|
106
|
+
|
107
|
+
print "Uploading [#{'=' * left}#{arrow}#{' ' * right}]\r"
|
108
|
+
else
|
109
|
+
puts
|
110
|
+
thread = Thread.new do
|
111
|
+
print "Reticulating splines..."
|
112
|
+
|
113
|
+
while true
|
114
|
+
break if IO.select( [read ], nil, nil, 0.5 )
|
115
|
+
print "."
|
116
|
+
end
|
117
|
+
|
118
|
+
puts
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
else
|
123
|
+
upload_callback = nil
|
124
|
+
end
|
125
|
+
|
126
|
+
host = resource.deploy! :environment => options[:staging] && 'staging',
|
127
|
+
:upload_callback => upload_callback
|
128
|
+
|
129
|
+
if STDOUT.tty?
|
130
|
+
write << '1'
|
131
|
+
thread.join
|
132
|
+
end
|
133
|
+
|
81
134
|
say "The application has successfully been deployed and is available at #{host}"
|
82
135
|
end
|
83
136
|
|
84
137
|
action "applications", "list all of your applications" do
|
85
138
|
empty = "You do not have any applications. Try deploying one with `strobe deploy`."
|
86
|
-
|
87
|
-
t.column :id
|
88
|
-
t.column :name
|
89
|
-
t.column :url
|
90
|
-
end
|
139
|
+
list_applications :empty => empty
|
91
140
|
end
|
92
141
|
|
93
142
|
method_option "url", :type => :string
|
@@ -119,7 +168,7 @@ module Strobe
|
|
119
168
|
end
|
120
169
|
|
121
170
|
application_path_option
|
122
|
-
method_option "id", :type => :numeric, :banner => "The ID of the remote application"
|
171
|
+
method_option "application-id", :type => :numeric, :banner => "The ID of the remote application"
|
123
172
|
action "register", "registers a local application with an existing Strobe application" do
|
124
173
|
if config[:application_id] && app = Application.get(config[:application_id])
|
125
174
|
say "The directory is already registered with the application `#{app[:name]}`"
|
@@ -129,21 +178,81 @@ module Strobe
|
|
129
178
|
config.delete
|
130
179
|
end
|
131
180
|
|
132
|
-
application = Application.get!
|
181
|
+
application = options['application-id'] ? Application.get!(options['application-id']) : pick_application
|
182
|
+
|
133
183
|
config[:application_id] = application[:id]
|
184
|
+
|
134
185
|
say "You can now deploy to #{application[:name]} (http://#{application[:url]})"
|
135
186
|
end
|
136
187
|
|
137
188
|
private
|
138
189
|
|
190
|
+
def run_sc_build
|
191
|
+
return unless is_sproutcore? # Bail if this isn't a SC application
|
192
|
+
|
193
|
+
# Using both options at the same time makes no sense
|
194
|
+
if options["sc-build"] && options["no-sc-build"]
|
195
|
+
error! "--sc-build and --no-sc-build cannot be used at the same time"
|
196
|
+
end
|
197
|
+
|
198
|
+
# If the user explicitly says that they don't want to run sc-build,
|
199
|
+
# then just skip it
|
200
|
+
return if options["no-sc-build"]
|
201
|
+
|
202
|
+
# If the user doesn't ask either way, confirm first
|
203
|
+
unless options["sc-build"]
|
204
|
+
say "This appears to be a SproutCore application."
|
205
|
+
return unless agree "Run `sc-build -c`? [Yn] "
|
206
|
+
end
|
207
|
+
|
208
|
+
unless system "sc-build", "-c"
|
209
|
+
error! "Something went wrong while running `sc-build -c`"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def is_sproutcore?
|
214
|
+
File.exist?("#{path}/tmp/build")
|
215
|
+
end
|
216
|
+
|
139
217
|
def determine_application_root
|
140
|
-
if
|
218
|
+
if is_sproutcore?
|
141
219
|
return "#{path}/tmp/build"
|
142
220
|
end
|
143
221
|
|
144
222
|
path
|
145
223
|
end
|
146
224
|
|
225
|
+
def list_applications(*args)
|
226
|
+
options = Hash === args.last ? args.pop : {}
|
227
|
+
applications = args.first || Resources::Application.all
|
228
|
+
|
229
|
+
table applications, options do |t|
|
230
|
+
t.column :id
|
231
|
+
t.column :name
|
232
|
+
t.column :url
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def pick_application
|
237
|
+
applications = Resources::Application.all
|
238
|
+
|
239
|
+
if applications.empty?
|
240
|
+
error! "You currently do not have any applications. Create some with `strobe deploy`"
|
241
|
+
end
|
242
|
+
|
243
|
+
list_applications applications, :index => true
|
244
|
+
|
245
|
+
while true
|
246
|
+
index = ask "Pick an application: ", :direct => true
|
247
|
+
|
248
|
+
if index.to_i > 0 and application = applications[index.to_i - 1]
|
249
|
+
return application
|
250
|
+
end
|
251
|
+
|
252
|
+
say "Invalid entry. Please enter one of the numbers in brackets"
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
147
256
|
def ensure_computer_is_registered
|
148
257
|
unless settings[:token]
|
149
258
|
say "This computer is not yet registered with a Strobe account."
|
data/lib/strobe/cli/table.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
module Strobe
|
2
2
|
class CLI::Table
|
3
|
+
class Index ; end
|
4
|
+
|
3
5
|
def initialize(collection, opts = {})
|
4
6
|
@collection = collection
|
5
7
|
@columns = []
|
6
8
|
@computed = []
|
7
9
|
@opts = opts
|
10
|
+
|
11
|
+
if opts[:index]
|
12
|
+
@columns.unshift({ :key => Index, :max => 0 })
|
13
|
+
end
|
8
14
|
end
|
9
15
|
|
10
16
|
def column(key)
|
@@ -14,7 +20,8 @@ module Strobe
|
|
14
20
|
def to_s
|
15
21
|
@collection.each do |obj|
|
16
22
|
@computed << @columns.map do |col|
|
17
|
-
cell
|
23
|
+
cell = obj [ col[:key] ] unless col[:key] == Index
|
24
|
+
cell = cell.to_s
|
18
25
|
col[:max] = [ cell.length, col[:max] ].max
|
19
26
|
cell
|
20
27
|
end
|
@@ -27,14 +34,15 @@ module Strobe
|
|
27
34
|
str = ""
|
28
35
|
|
29
36
|
@columns.each do |col|
|
30
|
-
|
37
|
+
cell = col[:key].to_s.upcase unless col[:key] == Index
|
38
|
+
str << cell_to_s(col, cell)
|
31
39
|
end
|
32
40
|
|
33
41
|
str << "\n"
|
34
42
|
|
35
|
-
@computed.
|
36
|
-
cells.each_with_index do |cell,
|
37
|
-
str << cell_to_s(@columns[
|
43
|
+
@computed.each_with_index do |cells, i|
|
44
|
+
cells.each_with_index do |cell, j|
|
45
|
+
str << cell_to_s(@columns[j], cell, i)
|
38
46
|
end
|
39
47
|
str << "\n"
|
40
48
|
end
|
@@ -43,9 +51,13 @@ module Strobe
|
|
43
51
|
|
44
52
|
private
|
45
53
|
|
46
|
-
def cell_to_s(col, cell)
|
54
|
+
def cell_to_s(col, cell, index = nil)
|
55
|
+
if index && col[:key] == Index
|
56
|
+
cell = "[#{index + 1}]"
|
57
|
+
end
|
58
|
+
|
47
59
|
width = [ col[:max], 25 ].max + 5
|
48
|
-
cell.ljust(width)
|
60
|
+
cell.to_s.ljust(width)
|
49
61
|
end
|
50
62
|
end
|
51
63
|
end
|
data/lib/strobe/cli.rb
CHANGED
@@ -27,7 +27,8 @@ module Strobe
|
|
27
27
|
def self.action(name, *args, &blk)
|
28
28
|
@haxliases ||= []
|
29
29
|
@haxliases << name.to_s
|
30
|
-
|
30
|
+
usage = self == Users ? "users #{name}" : name
|
31
|
+
desc usage, *args
|
31
32
|
define_method("__hax__#{name}", &blk)
|
32
33
|
map name => "__hax__#{name}"
|
33
34
|
end
|
@@ -119,6 +120,10 @@ module Strobe
|
|
119
120
|
STDERR.puts "[ERROR] #{what}"
|
120
121
|
end
|
121
122
|
|
123
|
+
def error!(what)
|
124
|
+
abort what
|
125
|
+
end
|
126
|
+
|
122
127
|
def agree(msg, *args)
|
123
128
|
@highline.agree(msg, *args) do |q|
|
124
129
|
next unless STDIN.tty? # For testing
|
@@ -160,6 +165,8 @@ module Strobe
|
|
160
165
|
end
|
161
166
|
|
162
167
|
def input(key, options)
|
168
|
+
return yield key if options[:direct]
|
169
|
+
|
163
170
|
into = options[:into] || key
|
164
171
|
|
165
172
|
validation_group into do
|
data/lib/strobe/collection.rb
CHANGED
data/lib/strobe/connection.rb
CHANGED
@@ -108,20 +108,18 @@ module Strobe
|
|
108
108
|
|
109
109
|
if headers['content-type'] == 'application/json'
|
110
110
|
body = ActiveSupport::JSON.encode(body)
|
111
|
-
else
|
112
|
-
body = body.to_s
|
113
111
|
end
|
114
112
|
end
|
115
113
|
|
114
|
+
http = build_http
|
115
|
+
request = Net::HTTPGenericRequest.new(
|
116
|
+
method.to_s.upcase, !!body, true, path, headers)
|
117
|
+
|
116
118
|
if body.respond_to?(:read)
|
117
119
|
request.body_stream = body
|
118
120
|
body = nil
|
119
121
|
end
|
120
122
|
|
121
|
-
http = build_http
|
122
|
-
request = Net::HTTPGenericRequest.new(
|
123
|
-
method.to_s.upcase, !!body, true, path, headers)
|
124
|
-
|
125
123
|
Response.new(http.request(request, body))
|
126
124
|
end
|
127
125
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'zlib'
|
1
2
|
require 'digest/sha1'
|
2
3
|
require 'mime/types'
|
3
4
|
|
@@ -22,8 +23,8 @@ module Strobe
|
|
22
23
|
|
23
24
|
request do
|
24
25
|
qs = "?environment=#{environment}" if environment
|
25
|
-
packfile = build_packfile
|
26
|
-
connection.put("#{http_uri}/deploy#{qs}", packfile
|
26
|
+
packfile = build_packfile(opts)
|
27
|
+
connection.put("#{http_uri}/deploy#{qs}", packfile, packfile.headers)
|
27
28
|
end
|
28
29
|
|
29
30
|
[ environment, self['url'] ].compact.join('.')
|
@@ -46,9 +47,9 @@ module Strobe
|
|
46
47
|
end
|
47
48
|
end
|
48
49
|
|
49
|
-
def build_packfile
|
50
|
+
def build_packfile(opts)
|
50
51
|
Dir.chdir self[:path] do
|
51
|
-
PackFile.build do |m|
|
52
|
+
PackFile.build(opts) do |m|
|
52
53
|
Dir["**/*"].each do |filename|
|
53
54
|
next unless File.file?(filename)
|
54
55
|
|
@@ -91,13 +92,14 @@ module Strobe
|
|
91
92
|
end
|
92
93
|
|
93
94
|
class PackFile
|
94
|
-
def self.build
|
95
|
-
inst = new
|
95
|
+
def self.build(opts)
|
96
|
+
inst = new(opts)
|
96
97
|
yield inst
|
97
98
|
inst
|
98
99
|
end
|
99
100
|
|
100
|
-
def initialize
|
101
|
+
def initialize(opts)
|
102
|
+
@opts = opts
|
101
103
|
@files = []
|
102
104
|
end
|
103
105
|
|
@@ -106,20 +108,66 @@ module Strobe
|
|
106
108
|
end
|
107
109
|
|
108
110
|
def headers
|
109
|
-
{ 'Content-Type'
|
111
|
+
{ 'Content-Type' => 'application/x-strobe-deploy',
|
112
|
+
'Content-Length' => size.to_s,
|
113
|
+
'Content-Encoding' => 'deflate' }
|
110
114
|
end
|
111
115
|
|
112
|
-
def
|
113
|
-
|
114
|
-
|
116
|
+
def each(*args, &blk)
|
117
|
+
to_io.each(*args, &blk)
|
118
|
+
end
|
119
|
+
|
120
|
+
def read(*args)
|
121
|
+
ret = to_io.read(*args)
|
115
122
|
|
116
|
-
|
117
|
-
|
118
|
-
head << "#{Digest::SHA1.hexdigest(data)} #{size} #{path} #{type}\n"
|
119
|
-
body << data
|
123
|
+
if callback = @opts[:upload_callback]
|
124
|
+
ret ? callback.call(pos.to_f / size.to_f) : callback.call(nil)
|
120
125
|
end
|
121
126
|
|
122
|
-
|
127
|
+
ret
|
128
|
+
end
|
129
|
+
|
130
|
+
def rewind
|
131
|
+
to_io.rewind
|
132
|
+
end
|
133
|
+
|
134
|
+
def seek(*args)
|
135
|
+
to_io.seek(*args)
|
136
|
+
end
|
137
|
+
|
138
|
+
def pos
|
139
|
+
to_io.pos
|
140
|
+
end
|
141
|
+
|
142
|
+
def size
|
143
|
+
to_io.size
|
144
|
+
end
|
145
|
+
|
146
|
+
def eof
|
147
|
+
to_io.eof
|
148
|
+
end
|
149
|
+
|
150
|
+
alias eof? eof
|
151
|
+
|
152
|
+
def to_io
|
153
|
+
@to_io ||= StringIO.new(to_s)
|
154
|
+
end
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
def to_s
|
159
|
+
@to_s ||= begin
|
160
|
+
head = ""
|
161
|
+
body = ""
|
162
|
+
|
163
|
+
@files.each do |path, type, data|
|
164
|
+
size = data.respond_to?(:bytesize) ? data.bytesize : data.size
|
165
|
+
head << "#{Digest::SHA1.hexdigest(data)} #{size} #{path} #{type}\n"
|
166
|
+
body << data
|
167
|
+
end
|
168
|
+
|
169
|
+
Zlib::Deflate.deflate("#{head}\n#{body}", 9)
|
170
|
+
end
|
123
171
|
end
|
124
172
|
end
|
125
173
|
end
|
metadata
CHANGED
@@ -7,8 +7,8 @@ version: !ruby/object:Gem::Version
|
|
7
7
|
- 1
|
8
8
|
- 0
|
9
9
|
- beta
|
10
|
-
-
|
11
|
-
version: 0.1.0.beta.
|
10
|
+
- 3
|
11
|
+
version: 0.1.0.beta.3
|
12
12
|
platform: ruby
|
13
13
|
authors:
|
14
14
|
- Yehuda Katz
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2011-01-
|
20
|
+
date: 2011-01-03 00:00:00 -08:00
|
21
21
|
default_executable:
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|