strobe 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/strobe +2 -12
- data/lib/strobe.rb +35 -88
- data/lib/strobe/association.rb +86 -0
- data/lib/strobe/cli.rb +39 -53
- data/lib/strobe/cli/action.rb +131 -0
- data/lib/strobe/cli/actions.rb +103 -0
- data/lib/strobe/cli/settings.rb +62 -0
- data/lib/strobe/collection.rb +53 -0
- data/lib/strobe/connection.rb +91 -0
- data/lib/strobe/resource/base.rb +235 -0
- data/lib/strobe/resource/collection.rb +50 -0
- data/lib/strobe/resource/singleton.rb +18 -0
- data/lib/strobe/resources/account.rb +12 -0
- data/lib/strobe/resources/application.rb +129 -0
- data/lib/strobe/resources/me.rb +11 -0
- data/lib/strobe/resources/signup.rb +27 -0
- data/lib/strobe/resources/team.rb +13 -0
- data/lib/strobe/resources/user.rb +11 -0
- data/lib/strobe/validations.rb +118 -0
- metadata +50 -124
- data/.gitignore +0 -5
- data/Gemfile +0 -4
- data/Gemfile.lock +0 -69
- data/Rakefile +0 -36
- data/features/1_sign_up.feature +0 -16
- data/features/2_deploying.feature +0 -35
- data/features/3_deploying_sproutcore_apps.feature +0 -19
- data/features/step_definitions/cli_steps.rb +0 -8
- data/features/step_definitions/deploying_steps.rb +0 -58
- data/features/step_definitions/sign_up.rb +0 -74
- data/features/support/helpers.rb +0 -104
- data/features/support/strobe.rb +0 -57
- data/lib/strobe/account.rb +0 -67
- data/lib/strobe/deploy.rb +0 -131
- data/lib/strobe/errors.rb +0 -12
- data/lib/strobe/http.rb +0 -94
- data/lib/strobe/server.rb +0 -13
- data/lib/strobe/settings.rb +0 -56
- data/lib/strobe/ui.rb +0 -81
- data/lib/strobe/user.rb +0 -9
- data/lib/strobe/version.rb +0 -3
- data/strobe.gemspec +0 -35
data/bin/strobe
CHANGED
@@ -1,14 +1,4 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
require 'strobe'
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
begin
|
6
|
-
Strobe::CLI.start
|
7
|
-
rescue Strobe::Error => e
|
8
|
-
Strobe.ui.error e.message
|
9
|
-
Strobe.ui.error e.backtrace.join("\n") if ENV["STROBE_DEBUG"]
|
10
|
-
exit e.status_code
|
11
|
-
rescue Interrupt
|
12
|
-
Strobe.ui.error "\nQuitting..."
|
13
|
-
exit 1
|
14
|
-
end
|
4
|
+
Strobe::CLI.start
|
data/lib/strobe.rb
CHANGED
@@ -1,100 +1,47 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
def root
|
23
|
-
main.root
|
24
|
-
end
|
25
|
-
|
26
|
-
def app_root
|
27
|
-
main.app_root
|
28
|
-
end
|
29
|
-
|
30
|
-
def account
|
31
|
-
main.account
|
32
|
-
end
|
33
|
-
|
34
|
-
def settings
|
35
|
-
main.settings
|
36
|
-
end
|
37
|
-
|
38
|
-
def config_dir
|
39
|
-
main.config_dir
|
40
|
-
end
|
41
|
-
|
42
|
-
def local_config_dir
|
43
|
-
main.local_config_dir
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
attr_writer :ui
|
48
|
-
|
49
|
-
def ui
|
50
|
-
@ui ||= UI::Basic.new
|
1
|
+
require 'base64'
|
2
|
+
require 'active_model'
|
3
|
+
require 'active_support/concern'
|
4
|
+
require 'active_support/core_ext/hash/deep_merge'
|
5
|
+
require 'active_support/core_ext/hash/reverse_merge'
|
6
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
7
|
+
require 'active_support/core_ext/string/inflections'
|
8
|
+
|
9
|
+
module Strobe
|
10
|
+
autoload :Association, 'strobe/association'
|
11
|
+
autoload :CLI, 'strobe/cli'
|
12
|
+
autoload :Collection, 'strobe/collection'
|
13
|
+
autoload :Connection, 'strobe/connection'
|
14
|
+
autoload :Validations, 'strobe/validations'
|
15
|
+
|
16
|
+
module Resource
|
17
|
+
autoload :Base, 'strobe/resource/base'
|
18
|
+
autoload :Collection, 'strobe/resource/collection'
|
19
|
+
autoload :Singleton, 'strobe/resource/singleton'
|
51
20
|
end
|
52
21
|
|
53
|
-
|
54
|
-
|
55
|
-
|
22
|
+
# Resources
|
23
|
+
module Resources
|
24
|
+
autoload :Account, 'strobe/resources/account'
|
25
|
+
autoload :Application, 'strobe/resources/application'
|
26
|
+
autoload :Me, 'strobe/resources/me'
|
27
|
+
autoload :Signup, 'strobe/resources/signup'
|
28
|
+
autoload :Team, 'strobe/resources/team'
|
29
|
+
autoload :User, 'strobe/resources/user'
|
56
30
|
end
|
57
31
|
|
58
|
-
|
59
|
-
|
60
|
-
end
|
32
|
+
# Errors
|
33
|
+
class StrobeError < StandardError ; end
|
34
|
+
class UnauthenticatedError < StrobeError ; end
|
35
|
+
class ResourceNotFoundError < StrobeError ; end
|
61
36
|
|
62
|
-
def
|
63
|
-
@
|
64
|
-
dir = Pathname.new(File.join(Strobe.user_home, ".strobe"))
|
65
|
-
FileUtils.mkdir_p(dir) unless dir.exist?
|
66
|
-
dir
|
67
|
-
end
|
37
|
+
def self.connection
|
38
|
+
@connection
|
68
39
|
end
|
69
40
|
|
70
|
-
def
|
71
|
-
@
|
72
|
-
dir = Pathname.new(File.join(app_root, ".strobe"))
|
73
|
-
FileUtils.mkdir_p(dir) unless dir.exist?
|
74
|
-
dir
|
75
|
-
end
|
41
|
+
def self.connection=(connection)
|
42
|
+
@connection = connection
|
76
43
|
end
|
77
44
|
|
78
|
-
def settings
|
79
|
-
@settings ||= Settings.new
|
80
|
-
end
|
81
|
-
|
82
|
-
autoload :Account, "strobe/account"
|
83
|
-
autoload :CLI, "strobe/cli"
|
84
|
-
autoload :Deploy, "strobe/deploy"
|
85
|
-
autoload :Error, "strobe/errors"
|
86
|
-
autoload :HTTP, "strobe/http"
|
87
|
-
autoload :Server, "strobe/server"
|
88
|
-
autoload :Settings, "strobe/settings"
|
89
|
-
autoload :UI, "strobe/ui"
|
90
|
-
autoload :User, "strobe/user"
|
91
|
-
autoload :Version, "strobe/version"
|
92
|
-
|
93
|
-
# ERRORS
|
94
|
-
autoload :AccountError, "strobe/errors"
|
95
|
-
autoload :ApplicationError, "strobe/errors"
|
96
|
-
|
97
|
-
private
|
98
45
|
# sadly, copied from Rubygems
|
99
46
|
def self.user_home
|
100
47
|
unless RUBY_VERSION > '1.9' then
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Strobe
|
2
|
+
class Association
|
3
|
+
attr_reader :source, :name, :cardinality, :options
|
4
|
+
|
5
|
+
def initialize(source, cardinality, name, options)
|
6
|
+
@source = source
|
7
|
+
@cardinality = cardinality
|
8
|
+
@name = name.to_sym
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
def target_name
|
13
|
+
'Strobe::Resources::' + name.to_s.classify
|
14
|
+
end
|
15
|
+
|
16
|
+
def target
|
17
|
+
@target ||= target_name.constantize
|
18
|
+
end
|
19
|
+
|
20
|
+
def collection?
|
21
|
+
cardinality == :n
|
22
|
+
end
|
23
|
+
|
24
|
+
def autoload?
|
25
|
+
!options.key?(:autoload) || options[:autoload]
|
26
|
+
end
|
27
|
+
|
28
|
+
def include?
|
29
|
+
options[:include]
|
30
|
+
end
|
31
|
+
|
32
|
+
def reader
|
33
|
+
ruby = []
|
34
|
+
ruby << "def #{name}"
|
35
|
+
|
36
|
+
if autoload? && collection?
|
37
|
+
|
38
|
+
ruby << " @__#{name} ||= Strobe::Collection.new( " \
|
39
|
+
" #{target_name}, '#{source.singular_resource_name}_id' " \
|
40
|
+
" => self[:id] ) if self[:id]"
|
41
|
+
|
42
|
+
elsif autoload?
|
43
|
+
|
44
|
+
ruby << " return @__#{name} if @__#{name}"
|
45
|
+
ruby << " return nil unless self[:#{name}_id]"
|
46
|
+
ruby << " @__#{name} = #{target_name}.get( self[:#{name}_id] )"
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
ruby << " @__#{name}"
|
51
|
+
|
52
|
+
ruby << "end"
|
53
|
+
ruby.join("\n")
|
54
|
+
end
|
55
|
+
|
56
|
+
def writer
|
57
|
+
ruby = []
|
58
|
+
ruby << "def #{name}=(val)"
|
59
|
+
|
60
|
+
if collection?
|
61
|
+
|
62
|
+
ruby << " raise NotImplementedError"
|
63
|
+
|
64
|
+
else
|
65
|
+
|
66
|
+
ruby << " if val"
|
67
|
+
ruby << " if val.is_a?(Hash)"
|
68
|
+
ruby << " val = #{target_name}.new(val)"
|
69
|
+
ruby << " elsif !val.is_a?(#{target_name})"
|
70
|
+
ruby << " raise 'fail'"
|
71
|
+
ruby << " end"
|
72
|
+
|
73
|
+
ruby << " self[:#{name}_id] = val[:id]" if autoload?
|
74
|
+
ruby << " @__#{name} = val"
|
75
|
+
ruby << " else"
|
76
|
+
ruby << " self[:#{name}_id] = nil" if autoload?
|
77
|
+
ruby << " @__#{name} = nil"
|
78
|
+
ruby << " end"
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
ruby << "end"
|
83
|
+
ruby.join("\n")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/strobe/cli.rb
CHANGED
@@ -1,78 +1,64 @@
|
|
1
|
-
require
|
1
|
+
require 'thor'
|
2
|
+
require 'pathname'
|
3
|
+
require 'fileutils'
|
2
4
|
|
3
|
-
|
5
|
+
module Strobe
|
4
6
|
class CLI < Thor
|
5
|
-
|
7
|
+
autoload :Action, 'strobe/cli/action'
|
8
|
+
autoload :Settings, 'strobe/cli/settings'
|
6
9
|
|
7
|
-
|
8
|
-
|
10
|
+
def self.start(*)
|
11
|
+
super
|
12
|
+
rescue Strobe::StrobeError => e
|
13
|
+
raise if $STROBE_BACKTRACE
|
14
|
+
abort "[ERROR] #{e.message}"
|
15
|
+
end
|
16
|
+
|
17
|
+
class_option "backtrace", :type => :boolean, :banner => "Show a backtrace in case of an exception"
|
9
18
|
|
10
19
|
def initialize(*)
|
11
20
|
super
|
12
21
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
use_shell = options["no-color"] ? Thor::Shell::Basic.new : shell
|
17
|
-
Strobe.ui = UI::Shell.new(use_shell)
|
22
|
+
$STROBE_BACKTRACE = true if options[:backtrace]
|
23
|
+
_settings.connect!
|
18
24
|
end
|
19
25
|
|
20
|
-
|
26
|
+
# Load the CLI actions
|
27
|
+
require "strobe/cli/actions"
|
28
|
+
|
29
|
+
desc "signup", "signup for a new Strobe account"
|
21
30
|
def signup
|
22
|
-
|
31
|
+
_run :signup
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "login", "register this computer with an existing Strobe account"
|
35
|
+
def login
|
36
|
+
_run :login
|
23
37
|
end
|
24
38
|
|
25
39
|
desc "deploy", "deploy your application to Strobe"
|
40
|
+
method_option "path", :type => :string, :banner => "The path to the application"
|
26
41
|
def deploy
|
27
|
-
|
28
|
-
|
42
|
+
path = options[:path] || Dir.pwd
|
43
|
+
config = Settings.new(Pathname.new(path).join(".strobe/config"))
|
29
44
|
|
30
|
-
|
31
|
-
def preview
|
32
|
-
Server.new(options[:path]).start
|
45
|
+
_run :deploy, :config => config, :path => path
|
33
46
|
end
|
34
47
|
|
35
|
-
|
36
|
-
case command
|
37
|
-
when "gemfile" then command = "gemfile.5"
|
38
|
-
when nil then command = "bundle"
|
39
|
-
else command = "bundle-#{cli}"
|
40
|
-
end
|
41
|
-
|
42
|
-
root = File.expand_path("../man", __FILE__)
|
43
|
-
|
44
|
-
if manpages.include?(command)
|
45
|
-
if have_groff?
|
46
|
-
groff = "groff -Wall -mtty-char -mandoc -Tascii"
|
47
|
-
pager = ENV['MANPAGER'] || ENV['PAGER'] || 'more'
|
48
|
+
private
|
48
49
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
else
|
54
|
-
super
|
55
|
-
end
|
50
|
+
def _init_application
|
51
|
+
path = options[:path]
|
52
|
+
dir = Pathname.new(path).join(".strobe")
|
53
|
+
FileUtils.mkdir_p dir
|
56
54
|
end
|
57
55
|
|
58
|
-
|
59
|
-
|
60
|
-
man_root = File.expand_path("../man", __FILE__)
|
61
|
-
return [] unless File.directory?(man_root)
|
62
|
-
|
63
|
-
man_pages = []
|
64
|
-
Dir["#{man_root}/*"].each do |file|
|
65
|
-
base = File.basename(file)
|
66
|
-
next if base.include?(".")
|
67
|
-
man_pages << base
|
68
|
-
end
|
69
|
-
man_pages
|
56
|
+
def _run(name, opts = {})
|
57
|
+
Action.run name, _settings, opts
|
70
58
|
end
|
71
59
|
|
72
|
-
def
|
73
|
-
|
74
|
-
$? == 0
|
60
|
+
def _settings
|
61
|
+
@settings ||= Settings.new
|
75
62
|
end
|
76
63
|
end
|
77
64
|
end
|
78
|
-
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'highline'
|
2
|
+
|
3
|
+
module Strobe
|
4
|
+
class CLI::Action
|
5
|
+
def self.run(action, settings, options = {})
|
6
|
+
success = false
|
7
|
+
klass = action.to_s.classify + 'Action'
|
8
|
+
klass = CLI::Actions.const_get(klass)
|
9
|
+
|
10
|
+
until success == true
|
11
|
+
action = klass.new(settings, options)
|
12
|
+
action.steps
|
13
|
+
success = !action.restart
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
include Resources
|
18
|
+
|
19
|
+
attr_reader :actions, :settings, :restart, :options
|
20
|
+
|
21
|
+
def initialize(settings, options)
|
22
|
+
@settings = settings
|
23
|
+
@options = options
|
24
|
+
@highline = HighLine.new
|
25
|
+
@resource = nil
|
26
|
+
|
27
|
+
# State
|
28
|
+
@in_group = false
|
29
|
+
@restart = false
|
30
|
+
end
|
31
|
+
|
32
|
+
def resource(resource = nil)
|
33
|
+
@resource = resource if resource
|
34
|
+
@resource
|
35
|
+
end
|
36
|
+
|
37
|
+
def say(what)
|
38
|
+
puts what
|
39
|
+
end
|
40
|
+
|
41
|
+
def agree(msg, *args)
|
42
|
+
@highline.agree(msg, *args) do |q|
|
43
|
+
next unless STDIN.tty? # For testing
|
44
|
+
q.readline = true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def ask(key, options = {})
|
49
|
+
input key, options do |msg|
|
50
|
+
resp = @highline.ask msg do |q|
|
51
|
+
next unless STDIN.tty? # For testing
|
52
|
+
q.readline = true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def password(key, options = {})
|
58
|
+
input key, options do |msg|
|
59
|
+
@highline.ask msg do |q|
|
60
|
+
next unless STDIN.tty? # For testing
|
61
|
+
q.echo = '*'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def choose
|
67
|
+
@highline.choose do |menu|
|
68
|
+
yield menu
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def group(options = {}, &blk)
|
73
|
+
case
|
74
|
+
when key = options[:validate]
|
75
|
+
validation_group(key, &blk)
|
76
|
+
else
|
77
|
+
yield if block_given?
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def save(opts = {})
|
82
|
+
if resource.save
|
83
|
+
yield
|
84
|
+
else
|
85
|
+
display_errors
|
86
|
+
if opts[:on_error] == :restart
|
87
|
+
@restart = true
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def run(action, opts = {})
|
93
|
+
CLI::Action.run(action, settings, opts)
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def input(key, options)
|
99
|
+
into = options[:into] || key
|
100
|
+
|
101
|
+
validation_group into do
|
102
|
+
msg = (key.to_s.humanize + ': ').ljust(25)
|
103
|
+
resource[into] = yield msg
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def validation_group(resource_key)
|
108
|
+
return yield if @in_group
|
109
|
+
|
110
|
+
begin
|
111
|
+
@in_group = true
|
112
|
+
while true
|
113
|
+
yield
|
114
|
+
|
115
|
+
break if resource.valid_attribute?(resource_key)
|
116
|
+
|
117
|
+
display_errors
|
118
|
+
end
|
119
|
+
ensure
|
120
|
+
@in_group = false
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def display_errors
|
125
|
+
resource.errors.each do |k, msg|
|
126
|
+
key = k.to_s.split('.').last
|
127
|
+
say "[ERROR] #{key.humanize} #{msg}"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|