bait 0.2.0
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.
- checksums.yaml +7 -0
- data/.bait/test.sh +7 -0
- data/.gitignore +20 -0
- data/DEVELOP +5 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +106 -0
- data/Guardfile +7 -0
- data/LICENSE +20 -0
- data/README.md +121 -0
- data/Rakefile +6 -0
- data/bait.gemspec +35 -0
- data/bin/bait +5 -0
- data/config/boot.rb +8 -0
- data/lib/bait.rb +38 -0
- data/lib/bait/api.rb +43 -0
- data/lib/bait/build.rb +50 -0
- data/lib/bait/public/css/styles.css +11 -0
- data/lib/bait/simple_query.rb +30 -0
- data/lib/bait/tester.rb +73 -0
- data/lib/bait/version.rb +3 -0
- data/lib/bait/views/builds.haml +31 -0
- data/lib/bait/views/layout.haml +11 -0
- data/spec/lib/bait/api_spec.rb +111 -0
- data/spec/lib/bait/build_spec.rb +65 -0
- data/spec/lib/bait/tester_spec.rb +88 -0
- data/spec/lib/bait_spec.rb +7 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/script_maker.rb +14 -0
- metadata +260 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4a26df53b8594473bd65a349db9746a2f58eae3b
|
4
|
+
data.tar.gz: 3b2c21ed9b86815ea4cbc542f9ab38548f02132a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a2a12d75d3bd4b57a843ae680e99d4add6c736721889d087353c97402389339a5a3034f397702ddc83cc3d714c7e164bd4cdac35468c1e990c58dfdcb1829183
|
7
|
+
data.tar.gz: e8ac8c6fe4f7e52101224a059fed668923a77daf9acbea3f8349f74c32141788056b9fb6baaeb4cd8e79626509fc232dcfbec9acad7a59f6f95372f3a2a97c29
|
data/.bait/test.sh
ADDED
data/.gitignore
ADDED
data/DEVELOP
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
bait (0.1.1)
|
5
|
+
git
|
6
|
+
haml
|
7
|
+
moneta
|
8
|
+
sinatra
|
9
|
+
thin
|
10
|
+
toystore
|
11
|
+
|
12
|
+
GEM
|
13
|
+
remote: https://rubygems.org/
|
14
|
+
specs:
|
15
|
+
activemodel (3.2.14)
|
16
|
+
activesupport (= 3.2.14)
|
17
|
+
builder (~> 3.0.0)
|
18
|
+
activesupport (3.2.14)
|
19
|
+
i18n (~> 0.6, >= 0.6.4)
|
20
|
+
multi_json (~> 1.0)
|
21
|
+
adapter (0.7.0)
|
22
|
+
builder (3.0.4)
|
23
|
+
coderay (1.0.9)
|
24
|
+
daemons (1.1.9)
|
25
|
+
diff-lcs (1.2.4)
|
26
|
+
eventmachine (1.0.3)
|
27
|
+
ffi (1.9.0)
|
28
|
+
formatador (0.2.4)
|
29
|
+
git (1.2.5)
|
30
|
+
guard (1.8.1)
|
31
|
+
formatador (>= 0.2.4)
|
32
|
+
listen (>= 1.0.0)
|
33
|
+
lumberjack (>= 1.0.2)
|
34
|
+
pry (>= 0.9.10)
|
35
|
+
thor (>= 0.14.6)
|
36
|
+
guard-rspec (3.0.2)
|
37
|
+
guard (>= 1.8)
|
38
|
+
rspec (~> 2.13)
|
39
|
+
haml (4.0.2)
|
40
|
+
tilt
|
41
|
+
i18n (0.6.4)
|
42
|
+
listen (1.2.2)
|
43
|
+
rb-fsevent (>= 0.9.3)
|
44
|
+
rb-inotify (>= 0.9)
|
45
|
+
rb-kqueue (>= 0.2)
|
46
|
+
lumberjack (1.0.4)
|
47
|
+
method_source (0.8.1)
|
48
|
+
moneta (0.7.19)
|
49
|
+
multi_json (1.7.7)
|
50
|
+
pry (0.9.12.2)
|
51
|
+
coderay (~> 1.0.5)
|
52
|
+
method_source (~> 0.8)
|
53
|
+
slop (~> 3.4)
|
54
|
+
rack (1.5.2)
|
55
|
+
rack-protection (1.5.0)
|
56
|
+
rack
|
57
|
+
rack-test (0.6.2)
|
58
|
+
rack (>= 1.0)
|
59
|
+
rake (10.1.0)
|
60
|
+
rb-fsevent (0.9.3)
|
61
|
+
rb-inotify (0.9.0)
|
62
|
+
ffi (>= 0.5.0)
|
63
|
+
rb-kqueue (0.2.0)
|
64
|
+
ffi (>= 0.5.0)
|
65
|
+
rspec (2.14.1)
|
66
|
+
rspec-core (~> 2.14.0)
|
67
|
+
rspec-expectations (~> 2.14.0)
|
68
|
+
rspec-mocks (~> 2.14.0)
|
69
|
+
rspec-core (2.14.4)
|
70
|
+
rspec-expectations (2.14.0)
|
71
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
72
|
+
rspec-mocks (2.14.1)
|
73
|
+
simple_uuid (0.3.0)
|
74
|
+
simplecov (0.7.1)
|
75
|
+
multi_json (~> 1.0)
|
76
|
+
simplecov-html (~> 0.7.1)
|
77
|
+
simplecov-html (0.7.1)
|
78
|
+
sinatra (1.4.3)
|
79
|
+
rack (~> 1.4)
|
80
|
+
rack-protection (~> 1.4)
|
81
|
+
tilt (~> 1.3, >= 1.3.4)
|
82
|
+
slop (3.4.6)
|
83
|
+
thin (1.5.1)
|
84
|
+
daemons (>= 1.0.9)
|
85
|
+
eventmachine (>= 0.12.6)
|
86
|
+
rack (>= 1.0.0)
|
87
|
+
thor (0.18.1)
|
88
|
+
tilt (1.4.1)
|
89
|
+
toystore (0.13.2)
|
90
|
+
activemodel (~> 3.0)
|
91
|
+
activesupport (~> 3.0)
|
92
|
+
adapter (~> 0.7.0)
|
93
|
+
simple_uuid (~> 0.2)
|
94
|
+
|
95
|
+
PLATFORMS
|
96
|
+
ruby
|
97
|
+
|
98
|
+
DEPENDENCIES
|
99
|
+
bait!
|
100
|
+
bundler (~> 1.3)
|
101
|
+
guard-rspec
|
102
|
+
pry
|
103
|
+
rack-test
|
104
|
+
rake
|
105
|
+
rspec
|
106
|
+
simplecov
|
data/Guardfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Keyvan Fatehi
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
Bait
|
2
|
+
====
|
3
|
+
|
4
|
+
`bait` is a build and integration tester
|
5
|
+
|
6
|
+
# Backstory
|
7
|
+
|
8
|
+
https://github.com/DFTi/Scribbeo-motion already is designed in such a way that it vendors our existing iOS (completely written in Objective-C) application https://github.com/DFTi/Critique
|
9
|
+
|
10
|
+
This gave us a Ruby(Motion) environment where UIAutomator is available using MacBacon (like rspec)
|
11
|
+
|
12
|
+
As a Ruby on Rails developer, this was invaluable... But the iOS developers we hired disliked it and did not maintain the RubyMotion stuff.
|
13
|
+
|
14
|
+
Fast forward a year or so later and the app is complex, has no test suite, and our QA testers can barely keep up.
|
15
|
+
|
16
|
+
Scribbeo-motion proved that this works, and so bait is a service I'm envisioning for as the first stop between Github and the rest of my continuous integration pipeline.
|
17
|
+
|
18
|
+
# Architectural Overview
|
19
|
+
|
20
|
+
```
|
21
|
+
Github POST bait:80/
|
22
|
+
______________________ \./
|
23
|
+
| Mac OS X 10.8 | |
|
24
|
+
| w/ RubyMotion | |
|
25
|
+
| ---------------- +---------+----------------+
|
26
|
+
| +---+---+ |
|
27
|
+
| | API |----[haml]------- you
|
28
|
+
| +---+---+ |
|
29
|
+
| | |
|
30
|
+
| +---------+--+ |
|
31
|
+
| |Bait::Build | |
|
32
|
+
| +---+-----+--+ |
|
33
|
+
| \|/ /|\ |
|
34
|
+
| \|/ /|\ |
|
35
|
+
| \[build]\ |
|
36
|
+
| \|/ /|\ |
|
37
|
+
| \|/ /|\ |
|
38
|
+
| +------------+ |
|
39
|
+
| [.bait/test.sh]------|Bait::Tester| |
|
40
|
+
| +------------+ |
|
41
|
+
| |
|
42
|
+
+-----------------------------------------------+
|
43
|
+
|
44
|
+
Bait::Build -- Persistent ToyStore
|
45
|
+
|
46
|
+
Bait::Tester -- Runs your tests and updates build accordingly
|
47
|
+
```
|
48
|
+
|
49
|
+
*Created with [JavE](http://www.jave.de/)*
|
50
|
+
|
51
|
+
# Functional Overview
|
52
|
+
|
53
|
+
## Github Webhook Support
|
54
|
+
|
55
|
+
bait provides a Sinatra endpoint for the github push event webhook.
|
56
|
+
|
57
|
+
When the repo is cloned, an bait executes a file relative to your
|
58
|
+
project. This file must exist in order to use bait: `.bait/test.sh`
|
59
|
+
|
60
|
+
## .bait/test.sh
|
61
|
+
|
62
|
+
In this file you will run your test suite. **Be sure to make it
|
63
|
+
executable `chmod a+x .bait/test.sh`**
|
64
|
+
|
65
|
+
This file should output whatever you want to STDOUT/STDERR and return
|
66
|
+
the correct exit value.
|
67
|
+
|
68
|
+
### Examples
|
69
|
+
|
70
|
+
#### Ruby / Rails Example (RSpec)
|
71
|
+
|
72
|
+
##### [project root]/.bait/test.sh
|
73
|
+
```bash
|
74
|
+
#!/bin/bash
|
75
|
+
bait_dir=$(dirname $0)
|
76
|
+
project_dir="$bait_dir/.."
|
77
|
+
cd $project_dir
|
78
|
+
|
79
|
+
echo "bundling"
|
80
|
+
bundle install > /dev/null 2>&1
|
81
|
+
bundle exec rspec spec
|
82
|
+
```
|
83
|
+
|
84
|
+
#### RubyMotion Example
|
85
|
+
|
86
|
+
##### [project root]/.bait/test.sh
|
87
|
+
```bash
|
88
|
+
#!/bin/bash
|
89
|
+
bait_dir=$(dirname $0)
|
90
|
+
project_dir="$bait_dir/.."
|
91
|
+
cd $project_dir
|
92
|
+
|
93
|
+
export BUNDLE_GEMFILE=$project_dir/Gemfile
|
94
|
+
|
95
|
+
echo "bundling"
|
96
|
+
bundle install > /dev/null 2>&1
|
97
|
+
bundle exec motion-specwrap
|
98
|
+
```
|
99
|
+
|
100
|
+
There is a bug in RubyMotion where the exit value isn't reported
|
101
|
+
properly, that's why we are using
|
102
|
+
[motion-specwrap](https://github.com/mdks/motion-specwrap) to run the
|
103
|
+
tests and report the correct exit value
|
104
|
+
|
105
|
+
## Objective-C ?
|
106
|
+
|
107
|
+
So you can see how bait will run any test suite via arbitrary bash
|
108
|
+
scripts upon a Github hook.
|
109
|
+
|
110
|
+
But how exactly will it help add a ruby test suite to an Obj-C app?
|
111
|
+
|
112
|
+
Watch this spot for some examples soon; essentially we'll be doing this
|
113
|
+
in Ruby using bait::Wrap::ObjC or some such :)
|
114
|
+
|
115
|
+
# Future
|
116
|
+
|
117
|
+
## Static Code Analysis
|
118
|
+
|
119
|
+
Integrate [metric-fu](http://metric-fu.rubyforge.org/) for ruby apps and [OCLint](http://oclint.org/) for objective-c apps. Report these in Redis.
|
120
|
+
|
121
|
+
|
data/Rakefile
ADDED
data/bait.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'bait/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "bait"
|
8
|
+
spec.version = Bait::VERSION
|
9
|
+
spec.authors = ["Keyvan Fatehi"]
|
10
|
+
spec.email = ["keyvan@digitalfilmtree.com"]
|
11
|
+
spec.description = %q{build and integration test service}
|
12
|
+
spec.summary = %q{build and integration test service}
|
13
|
+
spec.homepage = "https://github.com/keyvanfatehi/bait"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "guard-rspec"
|
25
|
+
spec.add_development_dependency "pry"
|
26
|
+
spec.add_development_dependency 'rack-test'
|
27
|
+
spec.add_development_dependency 'simplecov'
|
28
|
+
|
29
|
+
spec.add_runtime_dependency "sinatra"
|
30
|
+
spec.add_runtime_dependency "moneta"
|
31
|
+
spec.add_runtime_dependency "toystore"
|
32
|
+
spec.add_runtime_dependency "git"
|
33
|
+
spec.add_runtime_dependency "haml"
|
34
|
+
spec.add_runtime_dependency "thin"
|
35
|
+
end
|
data/bin/bait
ADDED
data/config/boot.rb
ADDED
data/lib/bait.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require "bait/version"
|
2
|
+
require 'moneta'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module Bait
|
6
|
+
def self.storage_dir
|
7
|
+
path = File.join("#{self.home}", "#{self.env}")
|
8
|
+
FileUtils.mkdir_p path
|
9
|
+
path
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.db_dir
|
13
|
+
db_dir = File.join self.storage_dir, "databases"
|
14
|
+
FileUtils.mkdir_p db_dir
|
15
|
+
db_dir
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.db_file name
|
19
|
+
yaml_file = File.join self.db_dir, "#{name}.yaml"
|
20
|
+
FileUtils.touch yaml_file
|
21
|
+
yaml_file
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.store
|
25
|
+
@store ||= begin
|
26
|
+
Moneta.new :YAML, :file => db_file("main")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.env
|
31
|
+
ENV['RACK_ENV'] ||= 'production'
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.home
|
35
|
+
File.join Etc.getpwuid.dir, '.bait'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
data/lib/bait/api.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
require 'haml'
|
3
|
+
require 'json'
|
4
|
+
require 'bait/build'
|
5
|
+
|
6
|
+
module Bait
|
7
|
+
class Api < Sinatra::Base
|
8
|
+
set :port, 8417
|
9
|
+
|
10
|
+
get '/' do
|
11
|
+
redirect '/build'
|
12
|
+
end
|
13
|
+
|
14
|
+
post '/' do
|
15
|
+
if params && params["payload"]
|
16
|
+
push = JSON.parse(params["payload"])
|
17
|
+
Build.create({
|
18
|
+
name: push["repository"]["name"],
|
19
|
+
clone_url: push["repository"]["url"],
|
20
|
+
owner_name: push["repository"]["owner"]["name"],
|
21
|
+
owner_email: push["repository"]["owner"]["email"],
|
22
|
+
ref: push["ref"]
|
23
|
+
}).test_later
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
get '/build' do
|
28
|
+
@builds = Bait::Build.all
|
29
|
+
haml :builds
|
30
|
+
end
|
31
|
+
|
32
|
+
post '/build/create' do
|
33
|
+
build = Build.create(clone_url:params["clone_url"], name:'test')
|
34
|
+
build.test_later
|
35
|
+
redirect '/build'
|
36
|
+
end
|
37
|
+
|
38
|
+
get '/build/remove/:id' do
|
39
|
+
Build.destroy params["id"]
|
40
|
+
redirect '/build'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/bait/build.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'bait'
|
2
|
+
require 'moneta'
|
3
|
+
require "toystore"
|
4
|
+
require 'bait/simple_query'
|
5
|
+
require 'bait/tester'
|
6
|
+
|
7
|
+
module Bait
|
8
|
+
class Build
|
9
|
+
include Toy::Store
|
10
|
+
extend Bait::SimpleQuery
|
11
|
+
|
12
|
+
@@db_file = Bait.db_file('builds')
|
13
|
+
adapter :memory, Moneta.new(:YAML, :file => @@db_file)
|
14
|
+
|
15
|
+
attribute :ref, String
|
16
|
+
attribute :owner_name, String
|
17
|
+
attribute :owner_email, String
|
18
|
+
attribute :name, String
|
19
|
+
attribute :clone_url, String
|
20
|
+
attribute :passed, Boolean
|
21
|
+
attribute :output, String, default: ""
|
22
|
+
attribute :tested, Boolean, default: false
|
23
|
+
|
24
|
+
validates_presence_of :name
|
25
|
+
validates_presence_of :clone_url
|
26
|
+
|
27
|
+
def tester
|
28
|
+
@tester ||= Bait::Tester.new(self)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_later
|
32
|
+
self.tested = false
|
33
|
+
self.save
|
34
|
+
unless Bait.env == "test"
|
35
|
+
fork do
|
36
|
+
self.tester.clone!
|
37
|
+
self.tester.test!
|
38
|
+
end
|
39
|
+
end
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
after_destroy :remove_sandbox
|
44
|
+
|
45
|
+
def remove_sandbox
|
46
|
+
tester.cleanup!
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
/*
|
2
|
+
YUI 3.11.0 (build d549e5c)
|
3
|
+
Copyright 2013 Yahoo! Inc. All rights reserved.
|
4
|
+
Licensed under the BSD License.
|
5
|
+
http://yuilibrary.com/license/
|
6
|
+
*/
|
7
|
+
|
8
|
+
html{color:#000;background:#FFF}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal}ol,ul{list-style:none}caption,th{text-align:left}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}q:before,q:after{content:''}abbr,acronym{border:0;font-variant:normal}sup{vertical-align:text-top}sub{vertical-align:text-bottom}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit}input,textarea,select{*font-size:100%}legend{color:#000}#yui3-css-stamp.cssreset{display:none}
|
9
|
+
|
10
|
+
|
11
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Bait
|
2
|
+
module SimpleQuery
|
3
|
+
def self.extended(base)
|
4
|
+
base.after_create do
|
5
|
+
id_list = self.class.ids
|
6
|
+
id_list << self.id
|
7
|
+
self.class.ids = id_list
|
8
|
+
end
|
9
|
+
base.after_destroy do
|
10
|
+
self.class.ids = self.class.ids.reject{|id| id == self.id}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
def ids
|
14
|
+
Bait.store.raw["build_ids"] ||= []
|
15
|
+
end
|
16
|
+
|
17
|
+
def ids=(new_ids)
|
18
|
+
Bait.store.raw["build_ids"] = new_ids
|
19
|
+
end
|
20
|
+
|
21
|
+
def all
|
22
|
+
ids.map{|id| self.read(id)}
|
23
|
+
end
|
24
|
+
|
25
|
+
def last
|
26
|
+
self.read(self.ids.last)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
data/lib/bait/tester.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'bait'
|
2
|
+
require 'bait/build'
|
3
|
+
require 'git'
|
4
|
+
require 'pty'
|
5
|
+
|
6
|
+
module Bait
|
7
|
+
class Tester
|
8
|
+
attr_reader :passed
|
9
|
+
|
10
|
+
def initialize build
|
11
|
+
@build = build
|
12
|
+
end
|
13
|
+
|
14
|
+
def bait_dir
|
15
|
+
File.join(clone_path, ".bait")
|
16
|
+
end
|
17
|
+
|
18
|
+
def script
|
19
|
+
File.join(bait_dir, "test.sh")
|
20
|
+
end
|
21
|
+
|
22
|
+
def test!
|
23
|
+
begin
|
24
|
+
begin
|
25
|
+
PTY.spawn(script) do |r, w, pid|
|
26
|
+
r.each { |line| @build.output << line }
|
27
|
+
@build.passed = PTY.check(pid).exitstatus == 0
|
28
|
+
end
|
29
|
+
rescue PTY::ChildExited => e
|
30
|
+
@build.output << e
|
31
|
+
@build.passed = false
|
32
|
+
end
|
33
|
+
@build.tested = true
|
34
|
+
rescue Errno::ENOENT => ex
|
35
|
+
@build.output << "A test script was expected but missing.\nError: #{ex.message}"
|
36
|
+
ensure
|
37
|
+
@build.save
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def clone_path
|
42
|
+
File.join(sandbox_directory, @build.name)
|
43
|
+
end
|
44
|
+
|
45
|
+
def clone!
|
46
|
+
unless cloned?
|
47
|
+
begin
|
48
|
+
Git.clone(@build.clone_url, @build.name, :path => sandbox_directory)
|
49
|
+
rescue => ex
|
50
|
+
msg = "Failed to clone #{@build.clone_url}"
|
51
|
+
puts msg
|
52
|
+
@build.stderr = "#{msg}\n\n#{ex.message}\n\n#{ex.backtrace}"
|
53
|
+
@build.save
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def cloned?
|
59
|
+
Dir.exists? File.join(clone_path, ".git/")
|
60
|
+
end
|
61
|
+
|
62
|
+
def cleanup!
|
63
|
+
FileUtils.rm_rf sandbox_directory
|
64
|
+
end
|
65
|
+
|
66
|
+
def sandbox_directory
|
67
|
+
@sandbox_directory ||= begin
|
68
|
+
dir = File.join Bait.storage_dir, "build_tester", @build.id
|
69
|
+
FileUtils.mkdir_p(dir) && dir
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/bait/version.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
Listing Builds
|
2
|
+
%ul
|
3
|
+
- @builds.each do |build|
|
4
|
+
%li
|
5
|
+
%hr
|
6
|
+
.name= build.name
|
7
|
+
%a.clone_url{href:build.clone_url}= build.clone_url
|
8
|
+
.ref= build.ref
|
9
|
+
.status
|
10
|
+
Status:
|
11
|
+
- if build.tested?
|
12
|
+
= build.passed? ? "Passed!" : "Failed!"
|
13
|
+
- else
|
14
|
+
Queued
|
15
|
+
.output
|
16
|
+
Output:
|
17
|
+
%pre= build.output
|
18
|
+
.actions
|
19
|
+
%a{href:"/build/remove/#{build.id}"} Remove
|
20
|
+
|
21
|
+
%hr
|
22
|
+
|
23
|
+
.manual_clone
|
24
|
+
To clone manually without waiting for a post-receive hook, enter the following and hit submit
|
25
|
+
%form{ :action => "/build/create", :method => "post"}
|
26
|
+
%fieldset
|
27
|
+
%ol
|
28
|
+
%li
|
29
|
+
%label{:for => "clone_url"} clone_url:
|
30
|
+
%input{:type => "text", :name => "clone_url", :class => "text"}
|
31
|
+
%input{:type => "submit", :value => "Go", :class => "button"}
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bait/api'
|
3
|
+
require 'bait/build'
|
4
|
+
|
5
|
+
describe "Sinatra App" do
|
6
|
+
let(:app) { Bait::Api }
|
7
|
+
subject { last_response }
|
8
|
+
|
9
|
+
describe "github post-receive hook" do
|
10
|
+
let(:github_json) do
|
11
|
+
<<-GITHUB_JSON
|
12
|
+
{
|
13
|
+
"before": "5aef35982fb2d34e9d9d4502f6ede1072793222d",
|
14
|
+
"repository": {
|
15
|
+
"url": "http://github.com/defunkt/github",
|
16
|
+
"name": "github",
|
17
|
+
"owner": {
|
18
|
+
"email": "chris@ozmm.org",
|
19
|
+
"name": "defunkt"
|
20
|
+
}
|
21
|
+
},
|
22
|
+
"commits": {
|
23
|
+
"41a212ee83ca127e3c8cf465891ab7216a705f59": {
|
24
|
+
"url": "http://github.com/defunkt/github/commit/41a212ee83ca127e3c8cf465891ab7216a705f59",
|
25
|
+
"author": {
|
26
|
+
"email": "chris@ozmm.org",
|
27
|
+
"name": "Chris Wanstrath"
|
28
|
+
},
|
29
|
+
"message": "okay i give in",
|
30
|
+
"timestamp": "2008-02-15T14:57:17-08:00"
|
31
|
+
},
|
32
|
+
"de8251ff97ee194a289832576287d6f8ad74e3d0": {
|
33
|
+
"url": "http://github.com/defunkt/github/commit/de8251ff97ee194a289832576287d6f8ad74e3d0",
|
34
|
+
"author": {
|
35
|
+
"email": "chris@ozmm.org",
|
36
|
+
"name": "Chris Wanstrath"
|
37
|
+
},
|
38
|
+
"message": "update pricing a tad",
|
39
|
+
"timestamp": "2008-02-15T14:36:34-08:00"
|
40
|
+
}
|
41
|
+
},
|
42
|
+
"after": "de8251ff97ee194a289832576287d6f8ad74e3d0",
|
43
|
+
"ref": "refs/heads/master"
|
44
|
+
}
|
45
|
+
GITHUB_JSON
|
46
|
+
end
|
47
|
+
|
48
|
+
let (:build) { Bait::Build.last }
|
49
|
+
|
50
|
+
describe "POST /" do
|
51
|
+
before do
|
52
|
+
post '/', payload: github_json
|
53
|
+
end
|
54
|
+
|
55
|
+
it { should be_ok }
|
56
|
+
|
57
|
+
it "creates a build" do
|
58
|
+
build.name.should eq "github"
|
59
|
+
build.owner_name.should eq "defunkt"
|
60
|
+
build.owner_email.should eq "chris@ozmm.org"
|
61
|
+
build.ref.should eq "refs/heads/master"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "will be tested later based on a flag" do
|
65
|
+
build.should_not be_tested
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "GET /" do
|
70
|
+
before { get '/' }
|
71
|
+
it { should be_redirect }
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "GET /build" do
|
75
|
+
before do
|
76
|
+
Bait::Build.create(name: "quickfox", clone_url:'...')
|
77
|
+
Bait::Build.create(name: "slowsloth", clone_url:'...')
|
78
|
+
get '/build'
|
79
|
+
end
|
80
|
+
|
81
|
+
it { should be_ok }
|
82
|
+
|
83
|
+
it "shows the builds" do
|
84
|
+
subject.body.should match /quickfox/
|
85
|
+
subject.body.should match /slowsloth/
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "POST /build/create" do
|
90
|
+
let(:test_url){ "http://github.com/defunkt/github" }
|
91
|
+
it "can create a build manually" do
|
92
|
+
post '/build/create', {clone_url:test_url}
|
93
|
+
build.clone_url.should eq test_url
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "GET /build/remove/#" do
|
98
|
+
before do
|
99
|
+
@build = Bait::Build.create(name: "quickfox", clone_url:'...')
|
100
|
+
@sandbox = @build.tester.sandbox_directory
|
101
|
+
end
|
102
|
+
it "removes the build from store and its files from the filesystem" do
|
103
|
+
Bait::Build.ids.should have(1).item
|
104
|
+
get "/build/remove/#{@build.id}"
|
105
|
+
expect{@build.reload}.to raise_error Toy::NotFound
|
106
|
+
Bait::Build.ids.should be_empty
|
107
|
+
Pathname.new(@sandbox).should_not exist
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bait/build'
|
3
|
+
|
4
|
+
describe Bait::Build do
|
5
|
+
subject { Bait::Build }
|
6
|
+
|
7
|
+
describe ".all" do
|
8
|
+
context "with nothing in the store" do
|
9
|
+
specify { subject.all.should be_empty }
|
10
|
+
end
|
11
|
+
|
12
|
+
context "with builds in the store" do
|
13
|
+
before do
|
14
|
+
subject.create(name: "foo", clone_url:'...')
|
15
|
+
subject.create(name: "bar", clone_url:'...')
|
16
|
+
end
|
17
|
+
|
18
|
+
specify { subject.all.should have(2).items }
|
19
|
+
|
20
|
+
it "returns the builds with data" do
|
21
|
+
subject.all[0].name.should eq "foo"
|
22
|
+
subject.all[1].name.should eq "bar"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe ".last" do
|
28
|
+
context "with nothing in the store" do
|
29
|
+
specify { subject.last.should be_nil }
|
30
|
+
end
|
31
|
+
context "with builds in the store" do
|
32
|
+
before do
|
33
|
+
subject.create(name: "fud", clone_url:'...')
|
34
|
+
@build = subject.create(name: "baz", clone_url:'...')
|
35
|
+
end
|
36
|
+
it "returns the last created build" do
|
37
|
+
subject.last.name.should eq "baz"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
let (:build) { Bait::Build.create(name: "app", clone_url:'...') }
|
43
|
+
|
44
|
+
describe "#tester" do
|
45
|
+
specify { build.tester.should be_a Bait::Tester }
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "#passed" do
|
49
|
+
it "starts as nil" do
|
50
|
+
build.passed.should be_nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "removal" do
|
55
|
+
before do
|
56
|
+
@build = build
|
57
|
+
end
|
58
|
+
|
59
|
+
it "is removed from build ids" do
|
60
|
+
Bait::Build.ids.should have(1).item
|
61
|
+
@build.destroy
|
62
|
+
Bait::Build.ids.should be_empty
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bait/tester'
|
3
|
+
|
4
|
+
describe Bait::Tester do
|
5
|
+
let(:repo_path) do
|
6
|
+
path = File.join(File.dirname(__FILE__), '..', '..', '..')
|
7
|
+
File.expand_path(path)
|
8
|
+
end
|
9
|
+
let(:build) { Bait::Build.create(name: "bait", clone_url:repo_path) }
|
10
|
+
let(:tester) { build.tester }
|
11
|
+
|
12
|
+
describe "#sandbox_directory" do
|
13
|
+
it "creates a directory on disk" do
|
14
|
+
Dir.exists?(tester.sandbox_directory).should be_true
|
15
|
+
end
|
16
|
+
|
17
|
+
it "is beneath Bait storage directory" do
|
18
|
+
tester.sandbox_directory.should match Bait.storage_dir
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#cloned?" do
|
23
|
+
specify { tester.should_not be_cloned }
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#clone!" do
|
27
|
+
before { tester.clone! }
|
28
|
+
specify { tester.should be_cloned }
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#test!" do
|
32
|
+
shared_examples_for "a test run" do
|
33
|
+
it "saves output into the build" do
|
34
|
+
build.output.should match "this is a test script"
|
35
|
+
end
|
36
|
+
it "is marked as tested" do
|
37
|
+
build.should be_tested
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
before do
|
42
|
+
tester.clone!
|
43
|
+
end
|
44
|
+
|
45
|
+
subject { build.reload }
|
46
|
+
|
47
|
+
context "does not have a test script" do
|
48
|
+
before do
|
49
|
+
FileUtils.rm tester.script
|
50
|
+
tester.test!
|
51
|
+
end
|
52
|
+
it { should_not be_tested }
|
53
|
+
it "has Bait errors in output" do
|
54
|
+
subject.output.should match /script was expected but missing/
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "has a test script" do
|
59
|
+
context "successful" do
|
60
|
+
before do
|
61
|
+
write_script_with_status tester.script, 0
|
62
|
+
tester.test!
|
63
|
+
end
|
64
|
+
it { should be_passed }
|
65
|
+
it_behaves_like "a test run"
|
66
|
+
end
|
67
|
+
context 'failure' do
|
68
|
+
before do
|
69
|
+
write_script_with_status tester.script, 1
|
70
|
+
tester.test!
|
71
|
+
end
|
72
|
+
it { should_not be_passed }
|
73
|
+
it_behaves_like "a test run"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "cleanup!" do
|
79
|
+
before do
|
80
|
+
tester.clone!
|
81
|
+
end
|
82
|
+
it "removes the entire sandbox" do
|
83
|
+
Dir.exists?(tester.sandbox_directory).should be_true
|
84
|
+
tester.cleanup!
|
85
|
+
Dir.exists?(tester.sandbox_directory).should be_false
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
ENV['RACK_ENV'] = "test"
|
2
|
+
require 'simplecov'
|
3
|
+
SimpleCov.start
|
4
|
+
|
5
|
+
require 'bait'
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
def clear_storage
|
9
|
+
FileUtils.rm_rf Bait.storage_dir
|
10
|
+
end
|
11
|
+
|
12
|
+
def clear_db
|
13
|
+
Dir.glob(File.join(Bait.db_dir, "*")).map do |f|
|
14
|
+
File.open(f, 'w')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
require 'support/script_maker'
|
19
|
+
require 'rack/test'
|
20
|
+
|
21
|
+
RSpec.configure do |config|
|
22
|
+
config.before(:suite) { clear_storage }
|
23
|
+
config.before(:each) { clear_db }
|
24
|
+
config.include Bait::SpecHelpers::ScriptMaker
|
25
|
+
config.include Rack::Test::Methods
|
26
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Bait
|
2
|
+
module SpecHelpers
|
3
|
+
module ScriptMaker
|
4
|
+
def write_script_with_status script, status
|
5
|
+
File.open(script, "w") do |f|
|
6
|
+
f.puts "#!/usr/bin/env bash"
|
7
|
+
f.puts "echo this is a test script"
|
8
|
+
f.puts "exit #{status.to_i}"
|
9
|
+
end
|
10
|
+
File.chmod(0755, script)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,260 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bait
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Keyvan Fatehi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-07-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: guard-rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rack-test
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: simplecov
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: sinatra
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: moneta
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: toystore
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - '>='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - '>='
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: git
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - '>='
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :runtime
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - '>='
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: haml
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :runtime
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - '>='
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: thin
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - '>='
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :runtime
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - '>='
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
description: build and integration test service
|
196
|
+
email:
|
197
|
+
- keyvan@digitalfilmtree.com
|
198
|
+
executables:
|
199
|
+
- bait
|
200
|
+
extensions: []
|
201
|
+
extra_rdoc_files: []
|
202
|
+
files:
|
203
|
+
- .bait/test.sh
|
204
|
+
- .gitignore
|
205
|
+
- DEVELOP
|
206
|
+
- Gemfile
|
207
|
+
- Gemfile.lock
|
208
|
+
- Guardfile
|
209
|
+
- LICENSE
|
210
|
+
- README.md
|
211
|
+
- Rakefile
|
212
|
+
- bait.gemspec
|
213
|
+
- bin/bait
|
214
|
+
- config/boot.rb
|
215
|
+
- lib/bait.rb
|
216
|
+
- lib/bait/api.rb
|
217
|
+
- lib/bait/build.rb
|
218
|
+
- lib/bait/public/css/styles.css
|
219
|
+
- lib/bait/simple_query.rb
|
220
|
+
- lib/bait/tester.rb
|
221
|
+
- lib/bait/version.rb
|
222
|
+
- lib/bait/views/builds.haml
|
223
|
+
- lib/bait/views/layout.haml
|
224
|
+
- spec/lib/bait/api_spec.rb
|
225
|
+
- spec/lib/bait/build_spec.rb
|
226
|
+
- spec/lib/bait/tester_spec.rb
|
227
|
+
- spec/lib/bait_spec.rb
|
228
|
+
- spec/spec_helper.rb
|
229
|
+
- spec/support/script_maker.rb
|
230
|
+
homepage: https://github.com/keyvanfatehi/bait
|
231
|
+
licenses:
|
232
|
+
- MIT
|
233
|
+
metadata: {}
|
234
|
+
post_install_message:
|
235
|
+
rdoc_options: []
|
236
|
+
require_paths:
|
237
|
+
- lib
|
238
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
239
|
+
requirements:
|
240
|
+
- - '>='
|
241
|
+
- !ruby/object:Gem::Version
|
242
|
+
version: '0'
|
243
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
244
|
+
requirements:
|
245
|
+
- - '>='
|
246
|
+
- !ruby/object:Gem::Version
|
247
|
+
version: '0'
|
248
|
+
requirements: []
|
249
|
+
rubyforge_project:
|
250
|
+
rubygems_version: 2.0.3
|
251
|
+
signing_key:
|
252
|
+
specification_version: 4
|
253
|
+
summary: build and integration test service
|
254
|
+
test_files:
|
255
|
+
- spec/lib/bait/api_spec.rb
|
256
|
+
- spec/lib/bait/build_spec.rb
|
257
|
+
- spec/lib/bait/tester_spec.rb
|
258
|
+
- spec/lib/bait_spec.rb
|
259
|
+
- spec/spec_helper.rb
|
260
|
+
- spec/support/script_maker.rb
|