strobe 0.1.0.beta.2 → 0.1.0.beta.3
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/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
|