strobe 0.0.2 → 0.0.2.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/lib/strobe.rb +1 -0
- data/lib/strobe/cli.rb +2 -1
- data/lib/strobe/cli/actions.rb +7 -6
- data/lib/strobe/cli/settings.rb +4 -2
- data/lib/strobe/connection.rb +87 -16
- data/lib/strobe/resource/base.rb +19 -15
- data/lib/strobe/resources/application.rb +46 -52
- metadata +9 -23
data/lib/strobe.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'base64'
|
2
2
|
require 'active_model'
|
3
3
|
require 'active_support/concern'
|
4
|
+
require 'active_support/json'
|
4
5
|
require 'active_support/core_ext/hash/deep_merge'
|
5
6
|
require 'active_support/core_ext/hash/reverse_merge'
|
6
7
|
require 'active_support/core_ext/hash/indifferent_access'
|
data/lib/strobe/cli.rb
CHANGED
@@ -40,7 +40,8 @@ module Strobe
|
|
40
40
|
method_option "path", :type => :string, :banner => "The path to the application"
|
41
41
|
def deploy
|
42
42
|
path = options[:path] || Dir.pwd
|
43
|
-
|
43
|
+
file = ENV['STROBE_CONFIG'] || 'config'
|
44
|
+
config = Settings.new(Pathname.new(path).join(".strobe/#{file}"))
|
44
45
|
|
45
46
|
_run :deploy, :config => config, :path => path
|
46
47
|
end
|
data/lib/strobe/cli/actions.rb
CHANGED
@@ -49,8 +49,7 @@ module Strobe
|
|
49
49
|
|
50
50
|
class DeployAction < CLI::Action
|
51
51
|
def steps
|
52
|
-
|
53
|
-
|
52
|
+
ensure_computer_is_registered
|
54
53
|
|
55
54
|
config = options[:config]
|
56
55
|
path = determine_path
|
@@ -68,12 +67,14 @@ module Strobe
|
|
68
67
|
|
69
68
|
ask :name
|
70
69
|
ask :url
|
71
|
-
end
|
72
70
|
|
73
|
-
|
74
|
-
|
75
|
-
|
71
|
+
save do
|
72
|
+
config[:application_id] ||= resource[:id]
|
73
|
+
end
|
76
74
|
end
|
75
|
+
|
76
|
+
resource.deploy!
|
77
|
+
say "The application has successfully been deployed and is available at #{resource[:url]}"
|
77
78
|
end
|
78
79
|
|
79
80
|
private
|
data/lib/strobe/cli/settings.rb
CHANGED
@@ -3,11 +3,13 @@ require 'yaml'
|
|
3
3
|
module Strobe
|
4
4
|
class CLI::Settings
|
5
5
|
def self.global_config_file
|
6
|
-
|
6
|
+
file = ENV['STROBE_CONFIG'] || 'config'
|
7
|
+
Pathname.new(Strobe.user_home).join(".strobe/#{file}")
|
7
8
|
end
|
8
9
|
|
9
10
|
def self.application_config_file(root)
|
10
|
-
|
11
|
+
file = ENV['STROBE_CONFIG'] || 'config'
|
12
|
+
Pathname.new(root).join(".strobe/#{file}")
|
11
13
|
end
|
12
14
|
|
13
15
|
def initialize(filename = self.class.global_config_file)
|
data/lib/strobe/connection.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'base64'
|
2
|
-
require '
|
2
|
+
require 'net/http'
|
3
3
|
|
4
4
|
module Strobe
|
5
5
|
class Connection
|
6
6
|
attr_reader :url
|
7
7
|
|
8
8
|
def initialize(url)
|
9
|
-
@url = url
|
9
|
+
@url = URI(url)
|
10
10
|
@user = nil
|
11
11
|
@password = nil
|
12
12
|
end
|
@@ -37,27 +37,100 @@ module Strobe
|
|
37
37
|
request :delete, *args
|
38
38
|
end
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
class Response
|
41
|
+
attr_reader :headers
|
42
|
+
|
43
|
+
def initialize(response)
|
44
|
+
@response = response
|
45
|
+
@headers = {}
|
46
|
+
|
47
|
+
response.each_header do |key, val|
|
48
|
+
@headers[key] = val
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def status
|
53
|
+
@response.code.to_i
|
54
|
+
end
|
55
|
+
|
56
|
+
def body
|
57
|
+
return @body if @body
|
58
|
+
|
59
|
+
case mime_type
|
60
|
+
when :json
|
61
|
+
@body = ActiveSupport::JSON.decode(@response.body)
|
62
|
+
else
|
63
|
+
@body = @response.body
|
64
|
+
end
|
65
|
+
|
66
|
+
@body
|
67
|
+
end
|
68
|
+
|
69
|
+
def success?
|
70
|
+
status == 200
|
71
|
+
end
|
72
|
+
|
73
|
+
def validate!
|
74
|
+
case status
|
75
|
+
when 401
|
76
|
+
# TODO Fix this on the server
|
77
|
+
raise UnauthenticatedError, body['errors']
|
78
|
+
when 404
|
79
|
+
raise ResourceNotFoundError, body['errors']
|
80
|
+
end
|
81
|
+
|
82
|
+
self
|
44
83
|
end
|
45
84
|
|
46
|
-
|
85
|
+
private
|
47
86
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
87
|
+
def mime_type
|
88
|
+
return nil unless content_type = headers['content-type']
|
89
|
+
|
90
|
+
if content_type =~ /^application\/json[,\;\s]/
|
91
|
+
:json
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def request(method, path, body = nil, headers = {})
|
97
|
+
headers.keys.each do |key|
|
98
|
+
headers[key.downcase] = headers.delete(key)
|
54
99
|
end
|
55
100
|
|
56
|
-
|
101
|
+
headers['authorization'] ||= authorization_header
|
102
|
+
|
103
|
+
if body
|
104
|
+
headers['content-type'] ||= 'application/json'
|
105
|
+
|
106
|
+
if headers['content-type'] == 'application/json'
|
107
|
+
body = ActiveSupport::JSON.encode(body)
|
108
|
+
else
|
109
|
+
body = body.to_s
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
if body.respond_to?(:read)
|
114
|
+
request.body_stream = body
|
115
|
+
body = nil
|
116
|
+
end
|
117
|
+
|
118
|
+
http = build_http
|
119
|
+
request = Net::HTTPGenericRequest.new(
|
120
|
+
method.to_s.upcase, !!body, true, path, headers)
|
121
|
+
|
122
|
+
Response.new(http.request(request, body)).validate!
|
57
123
|
end
|
58
124
|
|
59
125
|
private
|
60
126
|
|
127
|
+
def build_http
|
128
|
+
http = Net::HTTP.new @url.host, @url.port || 80
|
129
|
+
http.read_timeout = 60
|
130
|
+
http.open_timeout = 10
|
131
|
+
http
|
132
|
+
end
|
133
|
+
|
61
134
|
def authorization_header
|
62
135
|
auth = Base64.encode64("#{@user}:#{@password}")
|
63
136
|
auth.gsub!("\n", "")
|
@@ -74,7 +147,6 @@ module Strobe
|
|
74
147
|
b.use Faraday::Request::ActiveSupportJson
|
75
148
|
b.use Faraday::Adapter::NetHttp
|
76
149
|
b.use Faraday::Response::ActiveSupportJson
|
77
|
-
b.options[:timeout] = 30
|
78
150
|
b.headers['authorization'] = authorization_header if authorize?
|
79
151
|
end
|
80
152
|
end
|
@@ -83,7 +155,6 @@ module Strobe
|
|
83
155
|
@reg_connection ||= Faraday::Connection.new(:url => @url) do |b|
|
84
156
|
b.use Faraday::Adapter::NetHttp
|
85
157
|
b.use Faraday::Response::ActiveSupportJson
|
86
|
-
b.options[:timeout] = 30
|
87
158
|
b.headers['authorization'] = authorization_header if authorize?
|
88
159
|
end
|
89
160
|
end
|
data/lib/strobe/resource/base.rb
CHANGED
@@ -146,21 +146,7 @@ module Strobe
|
|
146
146
|
|
147
147
|
def save
|
148
148
|
if valid?
|
149
|
-
|
150
|
-
@response = self["id"] ? update : create
|
151
|
-
|
152
|
-
if @response.success?
|
153
|
-
merge! @response.body[root]
|
154
|
-
return true
|
155
|
-
elsif @response.status == 422
|
156
|
-
errors = @response.body['errors']
|
157
|
-
errors = errors[root] if errors
|
158
|
-
handle_errors(errors) if errors
|
159
|
-
else
|
160
|
-
raise "Something went wrong"
|
161
|
-
end
|
162
|
-
|
163
|
-
false
|
149
|
+
request { self["id"] ? update : create }
|
164
150
|
end
|
165
151
|
end
|
166
152
|
|
@@ -184,6 +170,24 @@ module Strobe
|
|
184
170
|
uri
|
185
171
|
end
|
186
172
|
|
173
|
+
def request
|
174
|
+
@response = yield
|
175
|
+
root = self.class.singular_resource_name
|
176
|
+
|
177
|
+
if @response.success?
|
178
|
+
merge! @response.body[root]
|
179
|
+
return true
|
180
|
+
elsif @response.status == 422
|
181
|
+
errors = @response.body['errors']
|
182
|
+
errors = errors[root] if errors
|
183
|
+
handle_errors(errors) if errors
|
184
|
+
else
|
185
|
+
raise "Something went wrong"
|
186
|
+
end
|
187
|
+
|
188
|
+
false
|
189
|
+
end
|
190
|
+
|
187
191
|
def request_params
|
188
192
|
filter = self.class.filter
|
189
193
|
{ self.class.singular_resource_name => params.except(*filter) }
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'digest/sha1'
|
1
2
|
require 'mime/types'
|
2
3
|
|
3
4
|
module Strobe
|
@@ -12,37 +13,45 @@ module Strobe
|
|
12
13
|
filter :path
|
13
14
|
|
14
15
|
validates "account", "name", "url", :presence => true
|
15
|
-
validates "path", :presence => true, :with => :ensure_sane_application_path,
|
16
|
-
:skippable => false
|
17
16
|
|
18
|
-
|
17
|
+
def deploy!(path = nil)
|
18
|
+
self['path'] = path if path
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
validate_for_deploy or return
|
21
|
+
|
22
|
+
request do
|
23
|
+
packfile = build_packfile
|
24
|
+
connection.put("#{http_uri}/deploy", packfile.to_s, packfile.headers)
|
23
25
|
end
|
24
26
|
end
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
private
|
29
|
+
|
30
|
+
def validate_for_deploy
|
31
|
+
errors.clear
|
32
|
+
|
33
|
+
validates_presence_of :path
|
34
|
+
ensure_sane_application_path
|
35
|
+
|
36
|
+
errors.empty?
|
29
37
|
end
|
30
38
|
|
31
|
-
def
|
32
|
-
|
33
|
-
|
39
|
+
def ensure_sane_application_path
|
40
|
+
if self[:path] && Dir["#{self[:path]}/**/*"].empty?
|
41
|
+
errors.add('path', 'is not a sane application directory')
|
42
|
+
end
|
34
43
|
end
|
35
44
|
|
36
|
-
def
|
45
|
+
def build_packfile
|
37
46
|
Dir.chdir self[:path] do
|
38
|
-
|
47
|
+
PackFile.build do |m|
|
39
48
|
Dir["**/*"].each do |filename|
|
40
49
|
next unless File.file?(filename)
|
41
50
|
|
42
51
|
mime_type = MIME::Types.type_for(filename).first
|
43
52
|
mime_type ||= "application/octet-stream"
|
44
53
|
|
45
|
-
m.file filename, mime_type.to_s,
|
54
|
+
m.file filename, mime_type.to_s, read(filename)
|
46
55
|
end
|
47
56
|
|
48
57
|
picked_root_app = false
|
@@ -56,8 +65,8 @@ module Strobe
|
|
56
65
|
next unless index && File.file?(index)
|
57
66
|
|
58
67
|
manifest = "#{File.dirname(index)}/app.manifest"
|
59
|
-
manifest =
|
60
|
-
content =
|
68
|
+
manifest = read(manifest) if File.file?(manifest)
|
69
|
+
content = read(index)
|
61
70
|
|
62
71
|
m.file "#{app_name}/index.html", "text/html", content
|
63
72
|
m.file "#{app_name}/app.manifest", "text/cache-manifest", manifest if manifest
|
@@ -73,14 +82,19 @@ module Strobe
|
|
73
82
|
end
|
74
83
|
end
|
75
84
|
|
76
|
-
|
77
|
-
|
85
|
+
def read(path)
|
86
|
+
File.open(path, 'rb') { |f| f.read }
|
87
|
+
end
|
78
88
|
|
79
|
-
|
80
|
-
|
81
|
-
|
89
|
+
class PackFile
|
90
|
+
def self.build
|
91
|
+
inst = new
|
92
|
+
yield inst
|
93
|
+
inst
|
94
|
+
end
|
82
95
|
|
83
|
-
|
96
|
+
def initialize
|
97
|
+
@files = []
|
84
98
|
end
|
85
99
|
|
86
100
|
def file(path, content_type, body)
|
@@ -88,40 +102,20 @@ module Strobe
|
|
88
102
|
end
|
89
103
|
|
90
104
|
def headers
|
91
|
-
{
|
105
|
+
{ 'Content-Type' => 'application/x-strobe-deploy' }
|
92
106
|
end
|
93
107
|
|
94
|
-
def
|
95
|
-
|
96
|
-
|
97
|
-
b << "--#{boundary}\r\n"
|
108
|
+
def to_s
|
109
|
+
head = ""
|
110
|
+
body = ""
|
98
111
|
|
99
|
-
@files.each do |path, type,
|
100
|
-
|
101
|
-
|
112
|
+
@files.each do |path, type, data|
|
113
|
+
size = data.respond_to?(:bytesize) ? data.bytesize : data.size
|
114
|
+
head << "#{Digest::SHA1.hexdigest(data)} #{size} #{path} #{type}\n"
|
115
|
+
body << data
|
102
116
|
end
|
103
117
|
|
104
|
-
|
105
|
-
end
|
106
|
-
|
107
|
-
private
|
108
|
-
|
109
|
-
def boundary
|
110
|
-
@boundary ||= ActiveSupport::SecureRandom.hex(25)
|
111
|
-
end
|
112
|
-
|
113
|
-
def metadata
|
114
|
-
params['application']['paths'] = @files.map { |parts| parts.first }
|
115
|
-
params.to_json
|
116
|
-
end
|
117
|
-
|
118
|
-
def part(name, type, body)
|
119
|
-
b = ""
|
120
|
-
b << %[Content-Disposition: form-data; name="#{name}"; filename="array"\r\n]
|
121
|
-
b << %[Content-Type: #{type}\r\n]
|
122
|
-
b << %[\r\n]
|
123
|
-
b << body
|
124
|
-
b << %[\r\n]
|
118
|
+
"#{head}\n#{body}"
|
125
119
|
end
|
126
120
|
end
|
127
121
|
end
|
metadata
CHANGED
@@ -6,7 +6,8 @@ version: !ruby/object:Gem::Version
|
|
6
6
|
- 0
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
|
9
|
+
- 1
|
10
|
+
version: 0.0.2.1
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Yehuda Katz
|
@@ -15,7 +16,7 @@ autorequire:
|
|
15
16
|
bindir: bin
|
16
17
|
cert_chain: []
|
17
18
|
|
18
|
-
date: 2010-12-
|
19
|
+
date: 2010-12-15 00:00:00 -08:00
|
19
20
|
default_executable:
|
20
21
|
dependencies:
|
21
22
|
- !ruby/object:Gem::Dependency
|
@@ -48,25 +49,10 @@ dependencies:
|
|
48
49
|
version: 3.0.0
|
49
50
|
type: :runtime
|
50
51
|
version_requirements: *id002
|
51
|
-
- !ruby/object:Gem::Dependency
|
52
|
-
name: faraday
|
53
|
-
prerelease: false
|
54
|
-
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
-
none: false
|
56
|
-
requirements:
|
57
|
-
- - ~>
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
segments:
|
60
|
-
- 0
|
61
|
-
- 5
|
62
|
-
- 0
|
63
|
-
version: 0.5.0
|
64
|
-
type: :runtime
|
65
|
-
version_requirements: *id003
|
66
52
|
- !ruby/object:Gem::Dependency
|
67
53
|
name: highline
|
68
54
|
prerelease: false
|
69
|
-
requirement: &
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
70
56
|
none: false
|
71
57
|
requirements:
|
72
58
|
- - ~>
|
@@ -77,11 +63,11 @@ dependencies:
|
|
77
63
|
- 0
|
78
64
|
version: 1.6.0
|
79
65
|
type: :runtime
|
80
|
-
version_requirements: *
|
66
|
+
version_requirements: *id003
|
81
67
|
- !ruby/object:Gem::Dependency
|
82
68
|
name: thor
|
83
69
|
prerelease: false
|
84
|
-
requirement: &
|
70
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
85
71
|
none: false
|
86
72
|
requirements:
|
87
73
|
- - ~>
|
@@ -92,11 +78,11 @@ dependencies:
|
|
92
78
|
- 0
|
93
79
|
version: 0.14.0
|
94
80
|
type: :runtime
|
95
|
-
version_requirements: *
|
81
|
+
version_requirements: *id004
|
96
82
|
- !ruby/object:Gem::Dependency
|
97
83
|
name: mime-types
|
98
84
|
prerelease: false
|
99
|
-
requirement: &
|
85
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
100
86
|
none: false
|
101
87
|
requirements:
|
102
88
|
- - ~>
|
@@ -107,7 +93,7 @@ dependencies:
|
|
107
93
|
- 0
|
108
94
|
version: 1.16.0
|
109
95
|
type: :runtime
|
110
|
-
version_requirements: *
|
96
|
+
version_requirements: *id005
|
111
97
|
description: The client library for deploying applications to Strobe's HTML5 deployment platform
|
112
98
|
email:
|
113
99
|
- wycats@strobecorp.com
|