strobe 0.0.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/.gitignore +5 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +69 -0
- data/Rakefile +36 -0
- data/bin/strobe +14 -0
- data/features/1_sign_up.feature +16 -0
- data/features/2_deploying.feature +35 -0
- data/features/3_deploying_sproutcore_apps.feature +19 -0
- data/features/step_definitions/cli_steps.rb +8 -0
- data/features/step_definitions/deploying_steps.rb +58 -0
- data/features/step_definitions/sign_up.rb +74 -0
- data/features/support/helpers.rb +104 -0
- data/features/support/strobe.rb +57 -0
- data/lib/strobe.rb +118 -0
- data/lib/strobe/account.rb +67 -0
- data/lib/strobe/cli.rb +78 -0
- data/lib/strobe/deploy.rb +131 -0
- data/lib/strobe/errors.rb +12 -0
- data/lib/strobe/http.rb +94 -0
- data/lib/strobe/server.rb +13 -0
- data/lib/strobe/settings.rb +56 -0
- data/lib/strobe/ui.rb +81 -0
- data/lib/strobe/user.rb +9 -0
- data/lib/strobe/version.rb +3 -0
- data/strobe.gemspec +35 -0
- metadata +250 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
strobe (0.0.1)
|
5
|
+
activesupport (~> 3.0.0)
|
6
|
+
excon (~> 0.2.2)
|
7
|
+
highline (~> 1.6.1)
|
8
|
+
mime-types (= 1.16)
|
9
|
+
rack (~> 1.2.1)
|
10
|
+
thor (~> 0.14.1)
|
11
|
+
|
12
|
+
GEM
|
13
|
+
remote: http://rubygems.org/
|
14
|
+
specs:
|
15
|
+
activesupport (3.0.0)
|
16
|
+
builder (2.1.2)
|
17
|
+
childlabor (0.0.3)
|
18
|
+
cucumber (0.9.2)
|
19
|
+
builder (~> 2.1.2)
|
20
|
+
diff-lcs (~> 1.1.2)
|
21
|
+
gherkin (~> 2.2.5)
|
22
|
+
json (~> 1.4.6)
|
23
|
+
term-ansicolor (~> 1.0.5)
|
24
|
+
diff-lcs (1.1.2)
|
25
|
+
excon (0.2.3)
|
26
|
+
gherkin (2.2.8)
|
27
|
+
json (~> 1.4.6)
|
28
|
+
term-ansicolor (~> 1.0.5)
|
29
|
+
highline (1.6.1)
|
30
|
+
json (1.4.6)
|
31
|
+
mime-types (1.16)
|
32
|
+
prawn (0.8.4)
|
33
|
+
prawn-core (>= 0.8.4, < 0.9)
|
34
|
+
prawn-layout (>= 0.8.4, < 0.9)
|
35
|
+
prawn-security (>= 0.8.4, < 0.9)
|
36
|
+
prawn-core (0.8.4)
|
37
|
+
prawn-layout (0.8.4)
|
38
|
+
prawn-security (0.8.4)
|
39
|
+
rack (1.2.1)
|
40
|
+
rake (0.8.7)
|
41
|
+
rspec (2.0.0.beta.22)
|
42
|
+
rspec-core (= 2.0.0.beta.22)
|
43
|
+
rspec-expectations (= 2.0.0.beta.22)
|
44
|
+
rspec-mocks (= 2.0.0.beta.22)
|
45
|
+
rspec-core (2.0.0.beta.22)
|
46
|
+
rspec-expectations (2.0.0.beta.22)
|
47
|
+
diff-lcs (>= 1.1.2)
|
48
|
+
rspec-mocks (2.0.0.beta.22)
|
49
|
+
rspec-core (= 2.0.0.beta.22)
|
50
|
+
rspec-expectations (= 2.0.0.beta.22)
|
51
|
+
term-ansicolor (1.0.5)
|
52
|
+
thor (0.14.3)
|
53
|
+
|
54
|
+
PLATFORMS
|
55
|
+
ruby
|
56
|
+
|
57
|
+
DEPENDENCIES
|
58
|
+
activesupport (~> 3.0.0)
|
59
|
+
childlabor (= 0.0.3)
|
60
|
+
cucumber
|
61
|
+
excon (~> 0.2.2)
|
62
|
+
highline (~> 1.6.1)
|
63
|
+
mime-types (= 1.16)
|
64
|
+
prawn
|
65
|
+
rack (~> 1.2.1)
|
66
|
+
rake
|
67
|
+
rspec (~> 2.0.0)
|
68
|
+
strobe!
|
69
|
+
thor (~> 0.14.1)
|
data/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
RSpec::Core::RakeTask.new("spec") do |task|
|
6
|
+
task.rspec_opts = "-cfs"
|
7
|
+
task.ruby_opts = "-W"
|
8
|
+
end
|
9
|
+
|
10
|
+
namespace :man do
|
11
|
+
directory "lib/strobe/man"
|
12
|
+
|
13
|
+
Dir["man/*.ronn"].each do |ronn|
|
14
|
+
basename = File.basename(ronn, ".ronn")
|
15
|
+
roff = "lib/strobe/man/#{basename}"
|
16
|
+
|
17
|
+
file roff => ["lib/strobe/man", ronn] do
|
18
|
+
sh "ronn --roff --pipe #{ronn} > #{roff}"
|
19
|
+
end
|
20
|
+
|
21
|
+
file "#{roff}.txt" => roff do
|
22
|
+
sh "groff -Wall -mtty-char -mandoc -Tascii #{roff} | col -b > #{roff}.txt"
|
23
|
+
end
|
24
|
+
|
25
|
+
task :build => "#{roff}.txt"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "Build the man pages"
|
30
|
+
task :build => "man:build"
|
31
|
+
|
32
|
+
desc "Clean up from the built man pages"
|
33
|
+
task :clean do
|
34
|
+
rm_rf "lib/strobe/man"
|
35
|
+
end
|
36
|
+
|
data/bin/strobe
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "strobe"
|
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
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Feature: Signing up
|
2
|
+
Scenario Outline: A successful signup
|
3
|
+
Given the user is signing up
|
4
|
+
And his password is <password>
|
5
|
+
And his password confirmation is <confirmation>
|
6
|
+
Then the server should respond with "<response>"
|
7
|
+
|
8
|
+
Examples:
|
9
|
+
| password | confirmation | response |
|
10
|
+
| z0mgz0mg | z0mgz0mg | created successfully |
|
11
|
+
| z0mgz0mg | z0mgz0mg2 | do not match |
|
12
|
+
|
13
|
+
Scenario: Using a duplicate email
|
14
|
+
Given the user is signing up with a duplicate email
|
15
|
+
Then the server should respond with /creation failed.*email/
|
16
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
Feature: Deploying an application
|
2
|
+
Scenario: Deploying an app
|
3
|
+
Given the user successfully signs up
|
4
|
+
And the user creates a file named "hello.html" containing "<html><body>hello</body></html>"
|
5
|
+
And runs "strobe deploy"
|
6
|
+
And creates a new application
|
7
|
+
Then the deployment should be successful
|
8
|
+
And a request for "/hello.html" should return "<html><body>hello</body></html>"
|
9
|
+
|
10
|
+
Scenario: Deploying a second time
|
11
|
+
Given the app was already deployed
|
12
|
+
When the user creates a file named "hello.html" containing "<html><body>hello!</body></html>"
|
13
|
+
And the user creates a file named "goodbye.html" containing "<html><body>goodbye</body></html>"
|
14
|
+
And runs "strobe deploy"
|
15
|
+
And creates a new application
|
16
|
+
Then the deployment should be successful
|
17
|
+
And a request for "/hello.html" should return "<html><body>hello!</body></html>"
|
18
|
+
And a request for "/goodbye.html" should return "<html><body>goodbye</body></html>"
|
19
|
+
|
20
|
+
Scenario: Deploying with an account, but not yet signed in on this machine
|
21
|
+
Given an existing user
|
22
|
+
And the user creates a file named "hello.html" containing "<html><body>hello</body></html>"
|
23
|
+
And runs "strobe deploy"
|
24
|
+
And enters "2" for /You aren't logged in with a Strobe user/
|
25
|
+
And enters his username and password
|
26
|
+
And creates a new application
|
27
|
+
Then a request for "/hello.html" should return "<html><body>hello</body></html>"
|
28
|
+
|
29
|
+
Scenario: Deploying with an account, and giving the wrong username and password
|
30
|
+
Given an existing user
|
31
|
+
And the user creates a file named "hello.html" containing "<html><body>hello</body></html>"
|
32
|
+
And runs "strobe deploy"
|
33
|
+
And enters "2" for /Please select an option/
|
34
|
+
And enters an incorrect username and password
|
35
|
+
Then the client should output /Log in failed/
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Feature: Deploying a SproutCore app
|
2
|
+
Scenario: Deploying an app
|
3
|
+
Given the user successfully signs up
|
4
|
+
And the user creates a file named "tmp/build/static/hello.html" containing "<html><body>hello</body></html>"
|
5
|
+
And runs "strobe deploy"
|
6
|
+
And creates a new application
|
7
|
+
Then the deployment should be successful
|
8
|
+
And a request for "/static/hello.html" should return "<html><body>hello</body></html>"
|
9
|
+
|
10
|
+
Scenario: Deploying an app with build numbers
|
11
|
+
Given the user successfully signs up
|
12
|
+
And the user creates a file named "tmp/build/static/myapp/en/01ff039192795e1254c448b804522c75708e3414/index.html" containing "<html><body>hello</body></html>"
|
13
|
+
And the user creates a file named "tmp/build/static/framework/foo.js" containing "alert('hello')"
|
14
|
+
And runs "strobe deploy"
|
15
|
+
And creates a new application
|
16
|
+
Then the deployment should be successful
|
17
|
+
And a request for "/myapp" should return "<html><body>hello</body></html>"
|
18
|
+
And a request for "/" should return "<html><body>hello</body></html>"
|
19
|
+
And a request for "/static/framework/foo.js" should return "alert('hello')"
|
@@ -0,0 +1,8 @@
|
|
1
|
+
And /^enters "(.*)" for ["\/](.*)["\/]/ do |entry, expected_input|
|
2
|
+
out_until_block.should =~ Regexp.new(expected_input)
|
3
|
+
task.write "#{entry}\n"
|
4
|
+
end
|
5
|
+
|
6
|
+
Then /^the client should output ["\/](.*)["\/]$/ do |output|
|
7
|
+
out_until_block.should =~ Regexp.new(output)
|
8
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require "active_support/secure_random"
|
2
|
+
|
3
|
+
Given /^the user creates a file named "([^"]*)" containing "([^"]*)"$/ do |name, contents|
|
4
|
+
FileUtils.mkdir_p(File.dirname("#{html5_app}/#{name}"))
|
5
|
+
File.open("#{html5_app}/#{name}", "w") do |file|
|
6
|
+
file.write contents
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
And /^runs "strobe deploy"$/ do
|
11
|
+
strobe "deploy"
|
12
|
+
end
|
13
|
+
|
14
|
+
And /^creates a new application$/ do
|
15
|
+
@host ||= "foobar#{ActiveSupport::SecureRandom.hex(50)}.local"
|
16
|
+
|
17
|
+
unless @deployed
|
18
|
+
out_until_block.should =~ /Please enter your application's name:\s*/
|
19
|
+
task.write "foobar\n"
|
20
|
+
out_until_block.should =~ /URL to deploy to:\s*/
|
21
|
+
task.write "#{@host}\n"
|
22
|
+
@deployed = true
|
23
|
+
end
|
24
|
+
|
25
|
+
out_until_block.should =~ /Your app was successfully deployed on #{@host}/
|
26
|
+
end
|
27
|
+
|
28
|
+
Then /^the deployment should be successful$/ do
|
29
|
+
task.should be_terminated
|
30
|
+
task.exit_status.should == 0
|
31
|
+
end
|
32
|
+
|
33
|
+
And /^a request for "([^"]+)" should return "(.*)"$/ do |url, body|
|
34
|
+
When "the client makes a request for \"#{url}\""
|
35
|
+
Then "the response status should be 200"
|
36
|
+
And "the response body should be \"#{body}\""
|
37
|
+
end
|
38
|
+
|
39
|
+
When /^the client makes a request for "(.*)"$/ do |url|
|
40
|
+
connection = Excon::Connection.new("http://127.0.0.1:3000#{url}")
|
41
|
+
@response = connection.request(:method => "GET", :headers => {"Host" => @host})
|
42
|
+
end
|
43
|
+
|
44
|
+
Then /^the response status should be (\d+)$/ do |status|
|
45
|
+
@response.status.should == status.to_i
|
46
|
+
end
|
47
|
+
|
48
|
+
Then /^the response body should be "(.*)"$/ do |body|
|
49
|
+
@response.body.should == body
|
50
|
+
end
|
51
|
+
|
52
|
+
Given /^the app was already deployed$/ do
|
53
|
+
Given "the user successfully signs up"
|
54
|
+
And "the user creates a file named \"hello.html\" containing \"<html><body>hello</body></html>\""
|
55
|
+
And "runs \"strobe deploy\""
|
56
|
+
And "creates a new application"
|
57
|
+
Then "the deployment should be successful"
|
58
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require "active_support/secure_random"
|
2
|
+
|
3
|
+
Before do
|
4
|
+
reset!
|
5
|
+
|
6
|
+
cd html5_app
|
7
|
+
env({})
|
8
|
+
end
|
9
|
+
|
10
|
+
After do
|
11
|
+
unless task.terminated?
|
12
|
+
task.terminate
|
13
|
+
task.wait
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Given /^the user is signing up$/ do
|
18
|
+
@email = ActiveSupport::SecureRandom.hex(100) << "@zomg.com"
|
19
|
+
end
|
20
|
+
|
21
|
+
Given /^the user successfully signs up$/ do
|
22
|
+
Given "the user is signing up"
|
23
|
+
Then "the server should respond with \"created successfully\""
|
24
|
+
end
|
25
|
+
|
26
|
+
Given /^an existing user$/ do
|
27
|
+
Given "the user successfully signs up"
|
28
|
+
reset_home
|
29
|
+
end
|
30
|
+
|
31
|
+
Given /^the user is signing up with a duplicate email$/ do
|
32
|
+
Given "the user is signing up"
|
33
|
+
Then "the server should respond with \"created successfully\""
|
34
|
+
@email = @last_email
|
35
|
+
end
|
36
|
+
|
37
|
+
Given /^his password is (\w+)$/ do |password|
|
38
|
+
@password = password
|
39
|
+
end
|
40
|
+
|
41
|
+
Given /^his password confirmation is (\w+)$/ do |confirm|
|
42
|
+
@confirm = confirm
|
43
|
+
end
|
44
|
+
|
45
|
+
And /^enters (his|an incorrect) username and password$/ do |correct|
|
46
|
+
correct = correct == "his"
|
47
|
+
|
48
|
+
task.readline.should =~ /Please enter your Strobe username and password/
|
49
|
+
out_until_block.should =~ /Email:/
|
50
|
+
task.write "#{@last_email}\n"
|
51
|
+
out_until_block.should =~ /Password:\s*/
|
52
|
+
task.write correct ? "z0mgz0mg\n" : "z0mgz0mg2\n"
|
53
|
+
task.readline.should =~ /You are now logged in as/ if correct
|
54
|
+
end
|
55
|
+
|
56
|
+
Then /^the server should respond with ["\/](.+)["\/]$/ do |expected|
|
57
|
+
email = @email || ActiveSupport::SecureRandom.hex(100) << "@zomg.com"
|
58
|
+
password = @password || "z0mgz0mg"
|
59
|
+
confirm = @confirm || "z0mgz0mg"
|
60
|
+
|
61
|
+
@last_email = email
|
62
|
+
|
63
|
+
strobe "signup" do |task|
|
64
|
+
task.readline.should == "Please enter your Strobe username and password.\n"
|
65
|
+
out_until_block.should =~ /Email:\s*/
|
66
|
+
task.write "#{email}\n"
|
67
|
+
out_until_block.should =~ /Password:\s*/
|
68
|
+
task.write "#{password}\n"
|
69
|
+
out_until_block.should =~ /Repeat Password:\s*/
|
70
|
+
task.write "#{confirm}\n"
|
71
|
+
out_until_block.should =~ Regexp.new(expected, Regexp::MULTILINE)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require "pathname"
|
2
|
+
require "fileutils"
|
3
|
+
|
4
|
+
class Strobe
|
5
|
+
module Spec
|
6
|
+
module Helpers
|
7
|
+
def tmp
|
8
|
+
tmp = File.expand_path("../../../tmp", __FILE__)
|
9
|
+
Pathname.new(tmp)
|
10
|
+
end
|
11
|
+
|
12
|
+
def base_app
|
13
|
+
tmp.join("app")
|
14
|
+
end
|
15
|
+
|
16
|
+
def base_home
|
17
|
+
tmp.join("system_home")
|
18
|
+
end
|
19
|
+
|
20
|
+
def build_tmp
|
21
|
+
FileUtils.rm_rf(tmp)
|
22
|
+
FileUtils.mkdir_p(base_app)
|
23
|
+
FileUtils.mkdir_p(base_home)
|
24
|
+
end
|
25
|
+
|
26
|
+
def reset_home
|
27
|
+
FileUtils.rm_rf(system_home) if File.directory?(system_home)
|
28
|
+
Thread.current[:system_home] = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def reset_html5_app
|
32
|
+
FileUtils.rm_rf(html5_app) if File.directory?(html5_app)
|
33
|
+
Thread.current[:html5_app] = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def copy_html5_app(dest)
|
37
|
+
FileUtils.cp_r(base_app, dest) unless File.directory?(dest)
|
38
|
+
end
|
39
|
+
|
40
|
+
def html5_app
|
41
|
+
Thread.current[:html5_app] ||= begin
|
42
|
+
location = tmp.join("app_#{Thread.current.object_id}")
|
43
|
+
copy_html5_app(location)
|
44
|
+
location
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def system_home
|
49
|
+
Thread.current[:system_home] ||= begin
|
50
|
+
location = tmp.join("system_home_#{Thread.current.object_id}")
|
51
|
+
copy_system_home(location)
|
52
|
+
location
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def copy_system_home(dest)
|
57
|
+
FileUtils.cp_r(base_home, dest) unless File.directory?(dest)
|
58
|
+
end
|
59
|
+
|
60
|
+
def dir
|
61
|
+
Thread.current[:strobe_dir]
|
62
|
+
end
|
63
|
+
|
64
|
+
def dir=(dir)
|
65
|
+
Thread.current[:strobe_dir] = dir
|
66
|
+
end
|
67
|
+
|
68
|
+
def env=(env)
|
69
|
+
Thread.current[:strobe_env] = env
|
70
|
+
end
|
71
|
+
|
72
|
+
def cd(change_into)
|
73
|
+
original, self.dir = dir, change_into
|
74
|
+
yield if block_given?
|
75
|
+
ensure
|
76
|
+
self.dir = original if block_given?
|
77
|
+
end
|
78
|
+
|
79
|
+
def env(hash = nil)
|
80
|
+
return Thread.current[:strobe_env] unless hash
|
81
|
+
|
82
|
+
original, self.env = env, hash
|
83
|
+
yield if block_given?
|
84
|
+
ensure
|
85
|
+
self.env = original if block_given?
|
86
|
+
end
|
87
|
+
|
88
|
+
def reset!
|
89
|
+
reset_home
|
90
|
+
reset_html5_app
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
module Setup
|
95
|
+
extend Strobe::Spec::Helpers
|
96
|
+
|
97
|
+
build_tmp
|
98
|
+
cd html5_app
|
99
|
+
env({})
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
World(Strobe::Spec::Helpers)
|