strobe 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/bin/strobe +2 -12
  2. data/lib/strobe.rb +35 -88
  3. data/lib/strobe/association.rb +86 -0
  4. data/lib/strobe/cli.rb +39 -53
  5. data/lib/strobe/cli/action.rb +131 -0
  6. data/lib/strobe/cli/actions.rb +103 -0
  7. data/lib/strobe/cli/settings.rb +62 -0
  8. data/lib/strobe/collection.rb +53 -0
  9. data/lib/strobe/connection.rb +91 -0
  10. data/lib/strobe/resource/base.rb +235 -0
  11. data/lib/strobe/resource/collection.rb +50 -0
  12. data/lib/strobe/resource/singleton.rb +18 -0
  13. data/lib/strobe/resources/account.rb +12 -0
  14. data/lib/strobe/resources/application.rb +129 -0
  15. data/lib/strobe/resources/me.rb +11 -0
  16. data/lib/strobe/resources/signup.rb +27 -0
  17. data/lib/strobe/resources/team.rb +13 -0
  18. data/lib/strobe/resources/user.rb +11 -0
  19. data/lib/strobe/validations.rb +118 -0
  20. metadata +50 -124
  21. data/.gitignore +0 -5
  22. data/Gemfile +0 -4
  23. data/Gemfile.lock +0 -69
  24. data/Rakefile +0 -36
  25. data/features/1_sign_up.feature +0 -16
  26. data/features/2_deploying.feature +0 -35
  27. data/features/3_deploying_sproutcore_apps.feature +0 -19
  28. data/features/step_definitions/cli_steps.rb +0 -8
  29. data/features/step_definitions/deploying_steps.rb +0 -58
  30. data/features/step_definitions/sign_up.rb +0 -74
  31. data/features/support/helpers.rb +0 -104
  32. data/features/support/strobe.rb +0 -57
  33. data/lib/strobe/account.rb +0 -67
  34. data/lib/strobe/deploy.rb +0 -131
  35. data/lib/strobe/errors.rb +0 -12
  36. data/lib/strobe/http.rb +0 -94
  37. data/lib/strobe/server.rb +0 -13
  38. data/lib/strobe/settings.rb +0 -56
  39. data/lib/strobe/ui.rb +0 -81
  40. data/lib/strobe/user.rb +0 -9
  41. data/lib/strobe/version.rb +0 -3
  42. data/strobe.gemspec +0 -35
@@ -1,67 +0,0 @@
1
- require "excon"
2
- require "json"
3
-
4
- class Strobe
5
- class Account
6
- def self.signup_or_login
7
- Strobe.ui.info "You aren't logged in with a Strobe user on this machine"
8
- Strobe.ui.info " 1. Create a new Strobe user"
9
- Strobe.ui.info " 2. Log in with an existing Strobe user"
10
- option = Strobe.ui.ask "Please select an option: "
11
-
12
- case option
13
- when "1"
14
- signup
15
- when "2"
16
- login
17
- end
18
- end
19
-
20
- def self.signup
21
- while true
22
- email, pass = ask_for_login
23
- passc = Strobe.ui.password "Repeat Password: "
24
- break if pass == passc
25
-
26
- Strobe.ui.info "The password and confirmation do not match. Please try again."
27
- end
28
-
29
- response = HTTP.new.signup(email, pass)
30
- persist_details(*response)
31
-
32
- Strobe.ui.info "Your account was created successfully."
33
- end
34
-
35
- def self.login
36
- email, pass = ask_for_login
37
-
38
- response = HTTP.new.login(email, pass)
39
- persist_details(*response)
40
-
41
- Strobe.ui.info "You are now logged in as #{email}"
42
- end
43
-
44
- # we don't need the account for anything yet, so leave it
45
- def initialize(json)
46
- end
47
-
48
- private
49
- def self.ask_for_login
50
- Strobe.ui.info "Please enter your Strobe username and password."
51
-
52
- email = Strobe.ui.ask "Email: "
53
- pass = Strobe.ui.password "Password: "
54
- return email, pass
55
- end
56
-
57
- def self.persist_details(user, account = nil, errors = nil)
58
- if account && errors
59
- raise Strobe::AccountError, "Account creation failed. Please try again.\n#{errors}"
60
- elsif errors
61
- raise Strobe::AccountError, "Log in failed. Please try again.\n#{errors}"
62
- else
63
- Strobe.settings[:token] = user.token
64
- end
65
- end
66
- end
67
- end
@@ -1,131 +0,0 @@
1
- require "excon"
2
- require "json"
3
- require "mime/types"
4
- require "active_support/secure_random"
5
-
6
- cache_manifest = MIME::Type.new("text/cache-manifest") { |m| m.extensions = %w(manifest) }
7
- MIME::Types.add(cache_manifest)
8
-
9
- class Strobe
10
- class Deploy
11
- def initialize(path)
12
- @path = path
13
- @connection, @method = Strobe.settings.app_connection_and_method
14
- end
15
-
16
- def deploy
17
- Strobe::Account.signup_or_login unless Strobe.settings[:token]
18
-
19
- application, errors = HTTP.new.deploy(multipart)
20
-
21
- if errors
22
- raise Strobe::ApplicationError, "Application creation failed. Please try again.\n#{errors}"
23
- else
24
- # Update this every time for now, in case the app has changed
25
- # on the server. This assumes that the server returns JSON
26
- Strobe.settings.set_local(:application, application)
27
- Strobe.ui.confirm "Your app was successfully deployed on #{application["url"]}"
28
- end
29
- end
30
-
31
- def multipart
32
- Multipart.new do |m|
33
- if application = Strobe.settings[:application]
34
- name = application["name"]
35
- url = application["url"]
36
- else
37
- name = Strobe.ui.ask "Please enter your application's name: "
38
- url = Strobe.ui.ask "URL to deploy to: "
39
- end
40
-
41
- m.name name
42
- m.url url
43
-
44
- Dir["#{@path}/**/*"].each do |file|
45
- next unless File.file?(file)
46
-
47
- filename = file.sub(/^#{@path}/, '')
48
- mime_type = MIME::Types.type_for(file).first
49
- m.file filename, mime_type ? mime_type.to_s : "application/octet-stream", File.read(file)
50
- end
51
-
52
- apps = []
53
-
54
- Dir["#{@path}/static/*"].each do |app|
55
- next if File.file?(app)
56
-
57
- dir = File.basename(app)
58
- index = Dir["#{app}/*/*/index.html"].first
59
-
60
- next if !index || !File.file?(index)
61
-
62
- index = File.read(index)
63
- apps << index
64
-
65
- m.file "#{dir}/index.html", "text/html", index
66
- end
67
-
68
- m.file "index.html", "text/html", apps.first if apps.size == 1
69
- end
70
- end
71
-
72
- class Multipart
73
- def initialize
74
- @name = nil
75
- @url = nil
76
- @files = []
77
- yield self if block_given?
78
- end
79
-
80
- def name(name)
81
- @name = name
82
- end
83
-
84
- def url(url)
85
- @url = url
86
- end
87
-
88
- def file(path, content_type, body)
89
- @files << [path, content_type, body]
90
- end
91
-
92
- def headers
93
- { "Content-Type" => %[multipart/form-data; boundary="#{boundary}"] }
94
- end
95
-
96
- def body
97
- b = "--#{boundary}\r\n"
98
- b << part("metadata", "application/json", metadata)
99
- b << "--#{boundary}\r\n"
100
-
101
- @files.each do |path, type, body|
102
- b << part("files[]", type, body)
103
- b << "--#{boundary}\r\n"
104
- end
105
-
106
- b
107
- end
108
-
109
- private
110
-
111
- def boundary
112
- @boundary ||= ActiveSupport::SecureRandom.hex(25)
113
- end
114
-
115
- def metadata
116
- hash = { "name" => @name, "url" => @url }
117
- hash.merge!( "paths" => @files.map { |path,*| path } )
118
- hash.to_json
119
- end
120
-
121
- def part(name, type, body)
122
- b = ""
123
- b << %[Content-Disposition: form-data; name="#{name}"; filename="array"\r\n]
124
- b << %[Content-Type: #{type}\r\n]
125
- b << %[\r\n]
126
- b << body
127
- b << %[\r\n]
128
- end
129
- end
130
- end
131
- end
@@ -1,12 +0,0 @@
1
- class Strobe
2
- class Error < StandardError; end
3
-
4
- def self.Error(code)
5
- Class.new(Error) do
6
- define_method(:status_code) { code }
7
- end
8
- end
9
-
10
- class AccountError < Error(2); end
11
- class ApplicationError < Error(3); end
12
- end
@@ -1,94 +0,0 @@
1
- class Strobe
2
- class HTTP
3
- def signup(email, pass)
4
- body = {
5
- :account => {:name => "default"},
6
- :user => {:email => email, :password => pass}
7
- }.to_json
8
-
9
- response = http_request(
10
- "POST",
11
- Strobe.settings.url("accounts"),
12
- {"Content-Type" => "application/json"},
13
- body
14
- )
15
-
16
- # user, account, error
17
-
18
- json = JSON.parse(response.body)
19
-
20
- if error = json["error"]
21
- return nil, nil, error_messages(error)
22
- else
23
- user = json["user"] && User.new(json["user"])
24
- account = json["account"] ? Account.new(json["account"]) : true
25
- errors = json["errors"] && error_messages(json["errors"])
26
- return user, account, errors
27
- end
28
- end
29
-
30
- def login(email, pass)
31
- response = http_request(
32
- "GET",
33
- Strobe.settings.url("account"),
34
- {"Content-Type" => "application/json"}.merge(auth_header(email, pass))
35
- )
36
-
37
- json = JSON.parse(response.body)
38
-
39
- if error = json["error"]
40
- return nil, nil, "The email and password were invalid"
41
- else
42
- user = json["user"] && User.new(json["user"])
43
- errors = json["errors"] && error_messages(json["errors"])
44
- return user, nil, errors
45
- end
46
- end
47
-
48
- def deploy(deployment)
49
- connection, method = Strobe.settings.app_connection_and_method
50
-
51
- response = connection.request(
52
- :method => method,
53
- :headers => auth_header.merge(deployment.headers),
54
- :body => deployment.body.force_encoding("BINARY")
55
- )
56
-
57
- json = JSON.parse(response.body)
58
-
59
- if error = json["error"]
60
- return nil, error
61
- else
62
- application = json["application"]
63
- errors = json["errors"] && error_messages(json["errors"])
64
- return application, errors
65
- end
66
- end
67
-
68
- private
69
- def http_request(method, uri, headers = {}, body = nil)
70
- connection = Excon::Connection.new(uri)
71
- connection.request(:method => method, :headers => headers, :body => body)
72
- end
73
-
74
- def auth_header(username=Strobe.settings[:token], password=nil)
75
- header = "Basic " << ["#{username}:#{password}"].pack("m")
76
- header.gsub!(/\n/, '')
77
- {"Authorization" => header}
78
- end
79
-
80
- def error_messages(errors)
81
- messages = []
82
- errors.each do |k, v|
83
- if v
84
- v.each do |field, error|
85
- messages << " * #{field} #{error}"
86
- end
87
- else
88
- messages << " * #{k}"
89
- end
90
- end
91
- messages.join("\n")
92
- end
93
- end
94
- end
@@ -1,13 +0,0 @@
1
- require "rack"
2
-
3
- class Strobe
4
- class Server < ::Rack::Server
5
- def initialize(path = nil)
6
- @path = path
7
- end
8
-
9
- def app
10
- Rack::Directory.new(@path)
11
- end
12
- end
13
- end
@@ -1,56 +0,0 @@
1
- require "excon"
2
-
3
- class Strobe
4
- class Settings
5
- def initialize
6
- @location = ENV["STROBE_SETTINGS"] || Strobe.config_dir.join("config")
7
- @local = ENV["STROBE_APP_CONFIG"] || Strobe.local_config_dir.join("config")
8
- @hash = File.file?(@location) ? YAML.load(@location) : {}
9
- @local_hash = File.file?(@local) ? YAML.load(@local) : {}
10
- end
11
-
12
- def [](key)
13
- ENV[key_for(key)] || @local_hash[key_for(key)] || @hash[key_for(key)]
14
- end
15
-
16
- def []=(key, value)
17
- @hash[key_for(key)] = value
18
- File.open(@location, "wb") { |file| file.puts @hash.to_yaml }
19
- value
20
- end
21
-
22
- def set_local(key, value)
23
- @local_hash[key_for(key)] = value
24
- File.open(@local, "wb") { |file| file.puts @local_hash.to_yaml }
25
- end
26
-
27
- def url(path)
28
- self["url"] ||= "http://api.strobeapp.com/"
29
- self["url"] + path
30
- end
31
-
32
- def auth_header(username=self[:token], password=nil)
33
- header = "Basic " << ["#{username}:#{password}"].pack("m")
34
- header.gsub!(/\n/, '')
35
- {"Authorization" => header}
36
- end
37
-
38
- def app_connection_and_method
39
- app_url = url("applications")
40
-
41
- if application = self[:application]
42
- app_url << "/#{application["id"]}"
43
- method = "PUT"
44
- else
45
- method = "POST"
46
- end
47
-
48
- return Excon::Connection.new(app_url), method
49
- end
50
-
51
- private
52
- def key_for(key)
53
- "STROBE_#{key.to_s.upcase}"
54
- end
55
- end
56
- end
@@ -1,81 +0,0 @@
1
- require "highline"
2
-
3
- class Strobe
4
- module UI
5
- class Basic
6
- def debug(msg)
7
- puts msg
8
- end
9
-
10
- def info(msg)
11
- puts msg
12
- end
13
-
14
- def confirm(msg)
15
- puts msg
16
- end
17
-
18
- def warn(msg)
19
- puts msg
20
- end
21
-
22
- def error(msg)
23
- puts msg
24
- end
25
-
26
- def highline
27
- @highline ||= HighLine.new
28
- end
29
-
30
- def password(message)
31
- highline.ask(message) do |q|
32
- next unless STDIN.tty?
33
- q.echo = "*"
34
- end
35
- rescue EOFError
36
- ''
37
- end
38
-
39
- def ask(message)
40
- highline.ask(message) do |q|
41
- next unless STDIN.tty?
42
- q.readline = true
43
- end
44
- rescue EOFError
45
- ''
46
- end
47
- end
48
-
49
- class Shell < Basic
50
- def initialize(shell)
51
- @shell = shell
52
- @quiet = false
53
- end
54
-
55
- def debug(msg)
56
- @shell.say(msg) if ENV['DEBUG'] && !@quiet
57
- end
58
-
59
- def info(msg)
60
- @shell.say(msg) if !@quiet
61
- end
62
-
63
- def confirm(msg)
64
- @shell.say(msg, :green) if !@quiet
65
- end
66
-
67
- def warn(msg)
68
- @shell.say(msg, :yellow)
69
- end
70
-
71
- def error(msg)
72
- @shell.say(msg, :red)
73
- end
74
-
75
- def be_quiet!
76
- @quiet = true
77
- end
78
- end
79
- end
80
- end
81
-