strobe 0.0.1 → 0.0.2

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.
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
-