bait 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +7 -7
- data/Rakefile +51 -0
- data/VERSION +1 -1
- data/{assets/stylesheets → app/css}/build.scss +0 -0
- data/{assets/stylesheets → app/css}/main.scss +0 -0
- data/{assets → app}/js/bait.coffee +0 -0
- data/{assets → app}/js/build.coffee +0 -0
- data/{assets → app}/js/main.coffee +0 -0
- data/{assets → app}/js/manual_clone.coffee +0 -0
- data/lib/bait/api.rb +7 -3
- data/lib/bait/build.rb +38 -65
- data/lib/bait/build_helper.rb +36 -0
- data/lib/bait/cli.rb +2 -3
- data/lib/bait/phase.rb +56 -0
- data/lib/bait/public/css/application.css +52 -0
- data/lib/bait/public/{stylesheets → css}/reset.css +0 -0
- data/lib/bait/public/{javascript → js}/ansi2html.js +0 -0
- data/lib/bait/public/js/application.js +168 -0
- data/lib/bait/public/{javascript → js}/zepto.min.js +0 -0
- data/lib/bait/tester.rb +4 -1
- data/lib/bait/views/layout.haml +5 -5
- data/spec/lib/bait/analyzer_spec.rb +0 -0
- data/spec/lib/bait/{api_spec.rb → app/api_spec.rb} +0 -0
- data/spec/lib/bait/tester_spec.rb +4 -4
- metadata +19 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b666fc3bbdb851fbda76133436c798dfa3160350
|
4
|
+
data.tar.gz: 3b853992f6a475aa02b7eaa518519b9e53ecb05b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b41192c233b1441cd2e4e893fe13251840944962ba25c4eb1a4fbc13f246b245d6fee38e67fbc78e5efb208596b934ec17967deeea8a90b252718921d91a947b
|
7
|
+
data.tar.gz: 7ab8bba3752f07e033289d9283c6a8e2767067a5317a9ad0f3574d51641728b8d71c1f37ea757d00575935ed34fb1cc27d33fc8ef953d7a4ec9cc0cce26ae40e
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -24,18 +24,18 @@ You may also test manually by inputting a clone URL within the UI
|
|
24
24
|
|
|
25
25
|
+----------------------------------------|------+
|
26
26
|
| +------------+ +--\|/--+ | +-------------+
|
27
|
-
| | new Build <------------------| API
|
27
|
+
| | new Build <------------------| API <------ GET / |
|
28
28
|
| +-----+------+ | | | | |
|
29
29
|
| | | | | | |
|
30
|
+
| | |/build------> Build.all() |
|
30
31
|
| | +-------------+ | | | | |
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
| | |Subscription | | | | | | |
|
32
|
+
| +---\|/----+ |Subscription <------+ | | | |
|
33
|
+
| |Queue Job | | to Build | | | | | | UI Changes |
|
34
|
+
| +----+-----+ | Event | | | | | | | |
|
35
|
+
| | | Broadcasts | | | | | | | |
|
36
36
|
| | +--+------+---+ |/events----->[EventSource]|
|
37
37
|
| +----\|/-----+ | | +---+---+ | +-------------+
|
38
|
-
| |
|
38
|
+
| | Workers | | | | |
|
39
39
|
| |[subprocess]+----+ +----------+ |
|
40
40
|
| +------------+ |
|
41
41
|
| |
|
data/Rakefile
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
ENV['RACK_ENV'] = "development"
|
2
|
+
|
1
3
|
require "bundler/gem_tasks"
|
2
4
|
require "rspec/core/rake_task"
|
3
5
|
|
@@ -8,3 +10,52 @@ task :default => :spec
|
|
8
10
|
task :pry do
|
9
11
|
require 'pry'; binding.pry
|
10
12
|
end
|
13
|
+
|
14
|
+
namespace :assets do
|
15
|
+
task :precompile do
|
16
|
+
public = File.join File.dirname(__FILE__), %w(lib bait public)
|
17
|
+
require 'bait/api'
|
18
|
+
include Sinatra::AssetSnack::InstanceMethods
|
19
|
+
Sinatra::AssetSnack.assets.each do |assets|
|
20
|
+
compiled_path = File.join public, assets[:route]
|
21
|
+
puts "compiling #{compiled_path}"
|
22
|
+
File.open(compiled_path, 'w') do |file|
|
23
|
+
response = compile assets[:paths]
|
24
|
+
file.write response[:body]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def git_master?
|
32
|
+
`git branch | grep '* master'`
|
33
|
+
$?.exitstatus == 0
|
34
|
+
end
|
35
|
+
|
36
|
+
def git_dirty?
|
37
|
+
`git status --porcelain`.match(/^\sM/)
|
38
|
+
end
|
39
|
+
|
40
|
+
namespace :gem do
|
41
|
+
task :build => 'assets:precompile' do
|
42
|
+
`bundle install`
|
43
|
+
if git_dirty?
|
44
|
+
puts "dirty! commit first before building"
|
45
|
+
else
|
46
|
+
if git_master?
|
47
|
+
puts "On master branch"
|
48
|
+
`rspec spec`
|
49
|
+
if $?.exitstatus == 0
|
50
|
+
puts "Specs pass. you're ready"
|
51
|
+
puts `gem build bait.gemspec`
|
52
|
+
puts "Done! You can gem push that now"
|
53
|
+
else
|
54
|
+
puts "Uhh.. you have failing specs -- not building the gem"
|
55
|
+
end
|
56
|
+
else
|
57
|
+
puts "I'll only build the gem on the master branch"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/VERSION
CHANGED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/lib/bait/api.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'bait'
|
1
2
|
require 'sinatra'
|
2
3
|
require 'sinatra/streaming'
|
3
4
|
require 'sinatra/asset_snack'
|
@@ -8,12 +9,15 @@ require 'bait/build'
|
|
8
9
|
|
9
10
|
module Bait
|
10
11
|
class Api < Sinatra::Base
|
11
|
-
register Sinatra::AssetSnack
|
12
12
|
set :port, 8417
|
13
13
|
set server: 'thin'
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
unless Bait.env == "production"
|
16
|
+
register Sinatra::AssetSnack
|
17
|
+
|
18
|
+
asset_map '/js/application.js', ['app/js/**/*.js', 'app/js/**/*.coffee']
|
19
|
+
asset_map '/css/application.css', ['app/css/**/*.css', 'app/css/**/*.scss']
|
20
|
+
end
|
17
21
|
|
18
22
|
get '/' do
|
19
23
|
haml :builds
|
data/lib/bait/build.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
require 'bait/object'
|
2
2
|
require 'bait/tester'
|
3
|
-
require '
|
3
|
+
require 'bait/build_helper'
|
4
4
|
require 'bait/pubsub'
|
5
|
+
require 'bait/phase'
|
6
|
+
require 'json'
|
5
7
|
|
6
8
|
module Bait
|
7
9
|
class Build < Bait::Object
|
10
|
+
include Bait::BuildHelper
|
11
|
+
|
8
12
|
adapter :memory,
|
9
13
|
Moneta.new(:YAML, :file => Bait.db_file('builds'))
|
10
14
|
|
@@ -28,29 +32,6 @@ module Bait
|
|
28
32
|
self.cleanup!
|
29
33
|
end
|
30
34
|
|
31
|
-
def test!
|
32
|
-
Open3.popen2e(self.script) do |stdin, oe, wait_thr|
|
33
|
-
self.status = "testing"
|
34
|
-
self.broadcast :status, self.status
|
35
|
-
self.save
|
36
|
-
oe.each do |line|
|
37
|
-
self.output << line
|
38
|
-
self.broadcast(:output, line)
|
39
|
-
end
|
40
|
-
if wait_thr.value.exitstatus == 0
|
41
|
-
self.status = "passed"
|
42
|
-
else
|
43
|
-
self.status = "failed"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
rescue Errno::ENOENT => ex
|
47
|
-
self.output << "A test script was expected but missing.\nError: #{ex.message}"
|
48
|
-
self.status = "script missing"
|
49
|
-
ensure
|
50
|
-
self.save
|
51
|
-
self.broadcast(:status, status)
|
52
|
-
end
|
53
|
-
|
54
35
|
def test_later
|
55
36
|
self.status = "queued"
|
56
37
|
self.output = ""
|
@@ -59,50 +40,42 @@ module Bait
|
|
59
40
|
self
|
60
41
|
end
|
61
42
|
|
62
|
-
def
|
63
|
-
self.
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
end
|
85
|
-
|
86
|
-
def cleanup!
|
87
|
-
FileUtils.rm_rf(sandbox_directory) if Dir.exists?(sandbox_directory)
|
88
|
-
end
|
89
|
-
|
90
|
-
def sandbox_directory
|
91
|
-
File.join Bait.storage_dir, "tester", self.name, self.id
|
43
|
+
def test!
|
44
|
+
Bait::Phase.new(self.script("test")).on(:init) do
|
45
|
+
self.status = 'testing'
|
46
|
+
self.save
|
47
|
+
self.broadcast(:status, self.status)
|
48
|
+
end.on(:output) do |line|
|
49
|
+
self.output << line
|
50
|
+
self.broadcast(:output, line)
|
51
|
+
end.on(:missing) do |message|
|
52
|
+
self.output << message
|
53
|
+
self.status = "script missing"
|
54
|
+
self.save
|
55
|
+
end.on(:done) do |zerostatus|
|
56
|
+
if zerostatus
|
57
|
+
self.status = "passed"
|
58
|
+
else
|
59
|
+
self.status = "failed"
|
60
|
+
end
|
61
|
+
self.save
|
62
|
+
self.broadcast(:status, self.status)
|
63
|
+
# good place to check for a coverage report
|
64
|
+
end.run!
|
92
65
|
end
|
93
66
|
|
94
67
|
def clone!
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
68
|
+
return if cloned?
|
69
|
+
unless Dir.exists?(sandbox_directory)
|
70
|
+
FileUtils.mkdir_p sandbox_directory
|
71
|
+
end
|
72
|
+
begin
|
73
|
+
Git.clone(clone_url, name, :path => sandbox_directory)
|
74
|
+
rescue => ex
|
75
|
+
msg = "Failed to clone #{clone_url}"
|
76
|
+
self.output << "#{msg}\n\n#{ex.message}\n\n#{ex.backtrace.join("\n")}"
|
77
|
+
self.status = "failed to clone"
|
78
|
+
self.save
|
106
79
|
end
|
107
80
|
end
|
108
81
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Bait
|
2
|
+
module BuildHelper
|
3
|
+
def queued?
|
4
|
+
self.reload.status == "queued"
|
5
|
+
end
|
6
|
+
|
7
|
+
def passed?
|
8
|
+
self.reload.status == "passed"
|
9
|
+
end
|
10
|
+
|
11
|
+
def clone_path
|
12
|
+
File.join(sandbox_directory, self.name)
|
13
|
+
end
|
14
|
+
|
15
|
+
def bait_dir
|
16
|
+
File.join(clone_path, ".bait")
|
17
|
+
end
|
18
|
+
|
19
|
+
def script name
|
20
|
+
File.join(bait_dir, "#{name}.sh")
|
21
|
+
end
|
22
|
+
|
23
|
+
def cloned?
|
24
|
+
Dir.exists? File.join(clone_path, ".git/")
|
25
|
+
end
|
26
|
+
|
27
|
+
def cleanup!
|
28
|
+
FileUtils.rm_rf(sandbox_directory) if Dir.exists?(sandbox_directory)
|
29
|
+
end
|
30
|
+
|
31
|
+
def sandbox_directory
|
32
|
+
File.join Bait.storage_dir, "tester", self.name, self.id
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
data/lib/bait/cli.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
require '
|
2
|
-
require 'bait/build'
|
1
|
+
require 'bait'
|
3
2
|
|
4
3
|
module Bait
|
5
4
|
module CLI
|
@@ -12,7 +11,7 @@ module Bait
|
|
12
11
|
##
|
13
12
|
# Start the server
|
14
13
|
def self.server
|
15
|
-
puts "
|
14
|
+
puts "** Bait/#{Bait::VERSION} booting up in #{Bait.env} environment"
|
16
15
|
require 'bait/api'
|
17
16
|
Bait::Api.run!
|
18
17
|
end
|
data/lib/bait/phase.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
module Bait
|
2
|
+
class Phase
|
3
|
+
class UnexpectedHandlerDefinition < StandardError ; end
|
4
|
+
POSSIBLE_HANDLERS = %w(init output rescue missing done)
|
5
|
+
|
6
|
+
def initialize script
|
7
|
+
@script = script
|
8
|
+
@handlers = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def handle name, &block
|
12
|
+
if POSSIBLE_HANDLERS.include? name.to_s
|
13
|
+
@handlers[name] = block
|
14
|
+
else
|
15
|
+
raise UnexpectedHandlerDefinition
|
16
|
+
end
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
alias_method :on, :handle
|
21
|
+
|
22
|
+
def run!
|
23
|
+
if File.exists?(@script)
|
24
|
+
handler(:init)
|
25
|
+
zerostatus = execute_subprocess do |output_line|
|
26
|
+
handler(:output, output_line)
|
27
|
+
end
|
28
|
+
handler(:done, zerostatus)
|
29
|
+
else
|
30
|
+
msg = "Script #{@script} was expected but is missing."
|
31
|
+
handler(:missing, msg)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def handler name, *args
|
38
|
+
if target = @handlers[name]
|
39
|
+
target.call(*args)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def execute_subprocess &block
|
44
|
+
zerostatus = false
|
45
|
+
Open3.popen2e(@script) do |stdin, oe, wait_thr|
|
46
|
+
oe.each {|line| block.call(line) }
|
47
|
+
zerostatus = wait_thr.value.exitstatus == 0
|
48
|
+
end
|
49
|
+
rescue => ex
|
50
|
+
handler(:rescue, ex)
|
51
|
+
zerostatus = false
|
52
|
+
ensure
|
53
|
+
return zerostatus
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
/** build.scss **/
|
4
|
+
|
5
|
+
.build {
|
6
|
+
border-radius: 12px;
|
7
|
+
border: 2px solid RGB(201, 49, 20);
|
8
|
+
margin: 20px; }
|
9
|
+
.build .header {
|
10
|
+
border-top-left-radius: 10px;
|
11
|
+
border-top-right-radius: 10px;
|
12
|
+
padding: 5px;
|
13
|
+
position: relative; }
|
14
|
+
.build .header .status {
|
15
|
+
top: 4px;
|
16
|
+
right: 4px;
|
17
|
+
position: absolute; }
|
18
|
+
.build .header.passed {
|
19
|
+
background-color: RGB(71, 213, 86); }
|
20
|
+
.build .header.failed {
|
21
|
+
background-color: RGB(247, 65, 67); }
|
22
|
+
.build .output pre {
|
23
|
+
cursor: pointer;
|
24
|
+
color: white;
|
25
|
+
background-color: black;
|
26
|
+
max-height: 100px;
|
27
|
+
overflow-y: hidden;
|
28
|
+
overflow-x: scroll; }
|
29
|
+
|
30
|
+
|
31
|
+
/** main.scss **/
|
32
|
+
|
33
|
+
@font-face {
|
34
|
+
font-family: 'Ubuntu';
|
35
|
+
font-style: normal;
|
36
|
+
font-weight: 400;
|
37
|
+
src: local("Ubuntu"), url(/fonts/ubuntu.woff) format("woff"); }
|
38
|
+
|
39
|
+
body {
|
40
|
+
font-family: 'Ubuntu';
|
41
|
+
background-color: RGB(255, 254, 254); }
|
42
|
+
|
43
|
+
.actions {
|
44
|
+
background-color: RGB(254, 238, 195);
|
45
|
+
text-align: center;
|
46
|
+
border-bottom-left-radius: 10px;
|
47
|
+
border-bottom-right-radius: 10px; }
|
48
|
+
.actions a {
|
49
|
+
color: RGB(20, 77, 105);
|
50
|
+
text-decoration: none; }
|
51
|
+
.actions a:hover {
|
52
|
+
color: RGB(201, 49, 20); }
|
File without changes
|
File without changes
|
@@ -0,0 +1,168 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
/** bait.coffee **/
|
4
|
+
|
5
|
+
(function() {
|
6
|
+
window.Bait = {
|
7
|
+
subscribe: function(handlers) {
|
8
|
+
var source;
|
9
|
+
source = new EventSource('/events');
|
10
|
+
return source.addEventListener("message", function(e) {
|
11
|
+
var data, handler;
|
12
|
+
data = JSON.parse(e.data);
|
13
|
+
handler = handlers[data[0]][data[1]];
|
14
|
+
return handler.apply(this, data.slice(2));
|
15
|
+
});
|
16
|
+
}
|
17
|
+
};
|
18
|
+
|
19
|
+
}).call(this);
|
20
|
+
|
21
|
+
|
22
|
+
/** build.coffee **/
|
23
|
+
|
24
|
+
(function() {
|
25
|
+
window.Build = {
|
26
|
+
find: function(id) {
|
27
|
+
return $("#" + id);
|
28
|
+
},
|
29
|
+
all: function(cb) {
|
30
|
+
return $.getJSON('/build', function(data) {
|
31
|
+
return cb(data);
|
32
|
+
});
|
33
|
+
},
|
34
|
+
DOM: {
|
35
|
+
UIHelper: {
|
36
|
+
expand_toggle: function(el) {
|
37
|
+
return el.on("click", function(e) {
|
38
|
+
if (el.css("max-height") === "100px") {
|
39
|
+
return el.css("max-height", "100%");
|
40
|
+
} else {
|
41
|
+
return el.css("max-height", "100px");
|
42
|
+
}
|
43
|
+
});
|
44
|
+
},
|
45
|
+
enable_links: function(element) {
|
46
|
+
element.find('a.remove').click(function() {
|
47
|
+
$.ajax({
|
48
|
+
type: "DELETE",
|
49
|
+
url: $(this).data('url')
|
50
|
+
});
|
51
|
+
return false;
|
52
|
+
});
|
53
|
+
return element.find('a.retest').click(function() {
|
54
|
+
$(this).parents('.build').find('pre').html("");
|
55
|
+
$.post($(this).data('url'));
|
56
|
+
return false;
|
57
|
+
});
|
58
|
+
}
|
59
|
+
},
|
60
|
+
init: function(build_id) {
|
61
|
+
var build, output, pre;
|
62
|
+
build = Build.find(build_id);
|
63
|
+
pre = build.find(".output pre");
|
64
|
+
output = pre.html();
|
65
|
+
if ((output != null) && output.size > 0) {
|
66
|
+
pre.html(ansi2html(output));
|
67
|
+
}
|
68
|
+
Build.DOM.UIHelper.expand_toggle(pre);
|
69
|
+
return Build.DOM.UIHelper.enable_links(build);
|
70
|
+
}
|
71
|
+
},
|
72
|
+
List: {
|
73
|
+
add: function(build) {
|
74
|
+
var html;
|
75
|
+
html = Build.to_html(build);
|
76
|
+
if ($('.build').length > 0) {
|
77
|
+
$('.build').first().before(html);
|
78
|
+
} else {
|
79
|
+
$('ul#builds').append(html);
|
80
|
+
}
|
81
|
+
return Build.DOM.init(build.id);
|
82
|
+
}
|
83
|
+
},
|
84
|
+
to_html: function(build) {
|
85
|
+
return "<li id=\"" + build.id + "\" class=\"build\">\n <div class=\"header " + build.status + "\">\n <div class=\"status\">" + build.status + "</div>\n <a href=\"" + build.clone_url + "\">" + build.name + "</a>\n <div class=\"ref\">" + (build.ref != null ? build.ref : build.ref = '') + "</div>\n </div>\n <div class=\"output\">\n <pre>" + build.output + "</pre>\n </div>\n <div class=\"actions\">\n <a href=\"#\" class=\"remove\" data-url=\"/build/" + build.id + "\">Remove</a>\n |\n <a href=\"#\" class=\"retest\" data-url=\"/build/" + build.id + "/retest\">Retest</a>\n </div>\n</li>";
|
86
|
+
}
|
87
|
+
};
|
88
|
+
|
89
|
+
}).call(this);
|
90
|
+
|
91
|
+
|
92
|
+
/** main.coffee **/
|
93
|
+
|
94
|
+
(function() {
|
95
|
+
Zepto(function($) {
|
96
|
+
ManualClone.init();
|
97
|
+
Build.all(function(builds) {
|
98
|
+
$.each(builds, function(i, d) {
|
99
|
+
return Build.List.add(d.build);
|
100
|
+
});
|
101
|
+
return $("#loading").remove();
|
102
|
+
});
|
103
|
+
return Bait.subscribe({
|
104
|
+
global: {
|
105
|
+
new_build: function(data) {
|
106
|
+
return Build.List.add(data.build);
|
107
|
+
}
|
108
|
+
},
|
109
|
+
build: {
|
110
|
+
output: function(id, text) {
|
111
|
+
var pre;
|
112
|
+
pre = Build.find(id).find('pre');
|
113
|
+
return pre.append(ansi2html(text));
|
114
|
+
},
|
115
|
+
status: function(id, text) {
|
116
|
+
var header;
|
117
|
+
header = Build.find(id).find(".header");
|
118
|
+
header.find(".status").html(text);
|
119
|
+
return header.attr("class", "header " + text);
|
120
|
+
},
|
121
|
+
remove: function(id) {
|
122
|
+
return Build.find(id).remove();
|
123
|
+
}
|
124
|
+
}
|
125
|
+
});
|
126
|
+
});
|
127
|
+
|
128
|
+
}).call(this);
|
129
|
+
|
130
|
+
|
131
|
+
/** manual_clone.coffee **/
|
132
|
+
|
133
|
+
(function() {
|
134
|
+
window.ManualClone = {
|
135
|
+
init: function() {
|
136
|
+
var button, field, form, manual_clone;
|
137
|
+
form = $('.manual_clone');
|
138
|
+
field = form.find('input');
|
139
|
+
button = form.find('button');
|
140
|
+
manual_clone = function() {
|
141
|
+
var input;
|
142
|
+
input = field.val();
|
143
|
+
if (input.length > 0) {
|
144
|
+
if (!button.attr('disabled')) {
|
145
|
+
button.attr('disabled', 'disabled');
|
146
|
+
return $.post('/build/create', {
|
147
|
+
clone_url: input
|
148
|
+
}, function(response) {
|
149
|
+
console.log(response);
|
150
|
+
return button.removeAttr('disabled');
|
151
|
+
});
|
152
|
+
}
|
153
|
+
} else {
|
154
|
+
return alert("Enter a local path or remote url to a git repo, e.g.:\n Local: /Users/your/project\n Remote: https://github.com/your/project");
|
155
|
+
}
|
156
|
+
};
|
157
|
+
field.keypress(function(e) {
|
158
|
+
if (e.keyCode === 13) {
|
159
|
+
return manual_clone();
|
160
|
+
}
|
161
|
+
});
|
162
|
+
return button.on('click', function() {
|
163
|
+
return manual_clone();
|
164
|
+
});
|
165
|
+
}
|
166
|
+
};
|
167
|
+
|
168
|
+
}).call(this);
|
File without changes
|
data/lib/bait/tester.rb
CHANGED
data/lib/bait/views/layout.haml
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
%html
|
3
3
|
%head
|
4
4
|
%title Bait
|
5
|
-
%link{rel:'stylesheet', href:'/
|
6
|
-
%link{rel:'stylesheet', href:
|
7
|
-
%script{src:'/
|
8
|
-
%script{src:'/
|
9
|
-
%script{src:
|
5
|
+
%link{rel:'stylesheet', href:'/css/reset.css'}
|
6
|
+
%link{rel:'stylesheet', href:'/css/application.css'}
|
7
|
+
%script{src:'/js/zepto.min.js'}
|
8
|
+
%script{src:'/js/ansi2html.js'}
|
9
|
+
%script{src:'/js/application.js'}
|
10
10
|
%body
|
11
11
|
#nav
|
12
12
|
%a{href:'/'}Home
|
File without changes
|
File without changes
|
@@ -17,7 +17,7 @@ describe Bait::Tester do
|
|
17
17
|
|
18
18
|
describe "real-time events" do
|
19
19
|
before do
|
20
|
-
write_script_with_status build.script, 0
|
20
|
+
write_script_with_status build.script("test"), 0
|
21
21
|
end
|
22
22
|
it "push updates directly to the browser" do
|
23
23
|
Bait.should_receive(:broadcast).with(:build, :status, build.id, 'testing')
|
@@ -29,11 +29,11 @@ describe Bait::Tester do
|
|
29
29
|
|
30
30
|
context "build repo did not have a test script" do
|
31
31
|
before do
|
32
|
-
FileUtils.rm build.script
|
32
|
+
FileUtils.rm build.script("test")
|
33
33
|
tester.perform build.id
|
34
34
|
end
|
35
35
|
it "has errors in output" do
|
36
|
-
build.reload.output.should match /
|
36
|
+
build.reload.output.should match /was expected but is missing/
|
37
37
|
end
|
38
38
|
it "has a useful status" do
|
39
39
|
build.reload.status.should eq "script missing"
|
@@ -42,7 +42,7 @@ describe Bait::Tester do
|
|
42
42
|
|
43
43
|
context "has a test script" do
|
44
44
|
before do
|
45
|
-
write_script_with_status build.script, status
|
45
|
+
write_script_with_status build.script('test'), status
|
46
46
|
tester.perform build.id
|
47
47
|
end
|
48
48
|
context "successful" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bait
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keyvan Fatehi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-08-
|
11
|
+
date: 2013-08-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -251,30 +251,35 @@ files:
|
|
251
251
|
- README.md
|
252
252
|
- Rakefile
|
253
253
|
- VERSION
|
254
|
-
-
|
255
|
-
-
|
256
|
-
-
|
257
|
-
-
|
258
|
-
-
|
259
|
-
-
|
254
|
+
- app/css/build.scss
|
255
|
+
- app/css/main.scss
|
256
|
+
- app/js/bait.coffee
|
257
|
+
- app/js/build.coffee
|
258
|
+
- app/js/main.coffee
|
259
|
+
- app/js/manual_clone.coffee
|
260
260
|
- bait.gemspec
|
261
261
|
- bin/bait
|
262
262
|
- lib/bait.rb
|
263
263
|
- lib/bait/api.rb
|
264
264
|
- lib/bait/build.rb
|
265
|
+
- lib/bait/build_helper.rb
|
265
266
|
- lib/bait/cli.rb
|
266
267
|
- lib/bait/object.rb
|
268
|
+
- lib/bait/phase.rb
|
269
|
+
- lib/bait/public/css/application.css
|
270
|
+
- lib/bait/public/css/reset.css
|
267
271
|
- lib/bait/public/fonts/ubuntu.woff
|
268
|
-
- lib/bait/public/
|
269
|
-
- lib/bait/public/
|
270
|
-
- lib/bait/public/
|
272
|
+
- lib/bait/public/js/ansi2html.js
|
273
|
+
- lib/bait/public/js/application.js
|
274
|
+
- lib/bait/public/js/zepto.min.js
|
271
275
|
- lib/bait/pubsub.rb
|
272
276
|
- lib/bait/simple_query.rb
|
273
277
|
- lib/bait/tester.rb
|
274
278
|
- lib/bait/version.rb
|
275
279
|
- lib/bait/views/builds.haml
|
276
280
|
- lib/bait/views/layout.haml
|
277
|
-
- spec/lib/bait/
|
281
|
+
- spec/lib/bait/analyzer_spec.rb
|
282
|
+
- spec/lib/bait/app/api_spec.rb
|
278
283
|
- spec/lib/bait/build_spec.rb
|
279
284
|
- spec/lib/bait/pubsub_spec.rb
|
280
285
|
- spec/lib/bait/tester_spec.rb
|
@@ -306,7 +311,8 @@ signing_key:
|
|
306
311
|
specification_version: 4
|
307
312
|
summary: build and integration test service
|
308
313
|
test_files:
|
309
|
-
- spec/lib/bait/
|
314
|
+
- spec/lib/bait/analyzer_spec.rb
|
315
|
+
- spec/lib/bait/app/api_spec.rb
|
310
316
|
- spec/lib/bait/build_spec.rb
|
311
317
|
- spec/lib/bait/pubsub_spec.rb
|
312
318
|
- spec/lib/bait/tester_spec.rb
|