bob-the-builder 0.1 → 0.1.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/README.rdoc +11 -39
- data/Rakefile +1 -1
- data/bob-the-builder.gemspec +11 -3
- data/lib/bob.rb +1 -0
- data/lib/bob/background_engines/threaded.rb +108 -0
- data/lib/bob/buildable.rb +70 -0
- data/lib/bob/scm/abstract.rb +2 -2
- data/lib/bob/scm/git.rb +1 -7
- data/lib/bob/scm/svn.rb +46 -0
- data/test/background_engine/threaded_test.rb +36 -0
- data/test/helper.rb +5 -4
- data/test/helper/abstract_scm_helper.rb +50 -0
- data/test/helper/buildable_stub.rb +2 -0
- data/test/helper/git_helper.rb +1 -1
- data/test/helper/svn_helper.rb +68 -0
- data/test/scm/git_test.rb +59 -0
- data/test/scm/svn_test.rb +57 -0
- metadata +15 -5
data/README.rdoc
CHANGED
@@ -1,52 +1,24 @@
|
|
1
1
|
= Bob the Builder
|
2
2
|
|
3
|
-
Given a Buildable object with
|
4
|
-
|
5
|
-
* <tt>buildable.kind</tt>
|
6
|
-
|
7
|
-
Should return a Symbol with whatever kind of repository the buildable's code is
|
8
|
-
in (:git, :svn, etc).
|
9
|
-
|
10
|
-
* <tt>buildable.uri</tt>
|
11
|
-
|
12
|
-
Returns a string like "git://github.com/integrity/bob.git", pointing to the code
|
13
|
-
repository.
|
14
|
-
|
15
|
-
* <tt>buildable.branch</tt>
|
16
|
-
|
17
|
-
What branch of the repository should we build?
|
18
|
-
|
19
|
-
* <tt>buildable.build_script</tt>
|
20
|
-
|
21
|
-
Returns a string containing the build script to be run when "building".
|
22
|
-
|
23
|
-
* <tt>buildable.start_building(commit_id)</tt>
|
24
|
-
|
25
|
-
`commit_id` is a String that contains whatever is appropriate for the repo type,
|
26
|
-
so it would be a SHA1 hash for git repos, or a numeric id for svn, etc. This is a
|
27
|
-
callback so the buildable can determine how long it takes to build. It doesn't
|
28
|
-
need to return anything.
|
29
|
-
|
30
|
-
* <tt>buildable.finish_building(commit_id, build_status, build_output)</tt>
|
31
|
-
|
32
|
-
Callback for when the build finishes. It doesn't need to return anything. It will
|
33
|
-
receive a string with the commit identifier, a boolean for the build exit status
|
34
|
-
(true for successful builds, false fore failed ones) and a string with the build
|
35
|
-
output (both STDOUT and STDERR).
|
3
|
+
Given a Buildable object with a determined API (described in it's documentation),
|
4
|
+
Bob will, when called like:
|
36
5
|
|
37
|
-
|
6
|
+
Bob.build(buildable, commit_id) # or Bob.build(buildable, [commit_id, commit_id, ...])
|
38
7
|
|
39
|
-
Bob
|
8
|
+
or from your buildable (if you are using the Bob::Buildable mixin provided) as:
|
40
9
|
|
41
|
-
|
10
|
+
buildable.build(commit_id) # or buildable.build([commit_id, commit_id, ...])
|
42
11
|
|
43
12
|
1. Checkout the buildable on the specified commit
|
44
|
-
2. Call <tt>
|
45
|
-
3. Run the script provided in <tt>build_script</tt> in the buildable.
|
46
|
-
4. When the build process finishes, it will call <tt>finish_building</tt> with
|
13
|
+
2. Call <tt>Buildable#start_building</tt>
|
14
|
+
3. Run the script provided in <tt>Buildable#build_script</tt> in the buildable.
|
15
|
+
4. When the build process finishes, it will call <tt>Buildable#finish_building</tt> with
|
47
16
|
the commit_id, the build status (true if the script returns a status code
|
48
17
|
of 0, false otherwise), and a string with the build output (both STDOUT and STDERR).
|
49
18
|
|
19
|
+
If you pass an array of commits, the steps 1-4 will be repeated for each commit provided,
|
20
|
+
in order.
|
21
|
+
|
50
22
|
== Do I need this?
|
51
23
|
|
52
24
|
Probably not. Check out integrity[http://integrityapp.com] for a full fledged
|
data/Rakefile
CHANGED
data/bob-the-builder.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "bob-the-builder"
|
3
|
-
s.version = "0.1"
|
4
|
-
s.date = "2009-05-
|
3
|
+
s.version = "0.1.1"
|
4
|
+
s.date = "2009-05-08"
|
5
5
|
|
6
6
|
s.description = "Bob the Builder will build your code. Simple."
|
7
7
|
s.summary = "Bob builds!"
|
@@ -33,14 +33,22 @@ bob-the-builder.gemspec
|
|
33
33
|
lib/bob.rb
|
34
34
|
lib/bob/background_engines.rb
|
35
35
|
lib/bob/background_engines/foreground.rb
|
36
|
+
lib/bob/background_engines/threaded.rb
|
36
37
|
lib/bob/builder.rb
|
38
|
+
lib/bob/buildable.rb
|
37
39
|
lib/bob/scm.rb
|
38
40
|
lib/bob/scm/abstract.rb
|
39
41
|
lib/bob/scm/git.rb
|
42
|
+
lib/bob/scm/svn.rb
|
40
43
|
lib/core_ext/object.rb
|
44
|
+
test/background_engine/threaded_test.rb
|
41
45
|
test/bob_test.rb
|
42
46
|
test/helper.rb
|
43
|
-
test/helper/
|
47
|
+
test/helper/abstract_scm_helper.rb
|
44
48
|
test/helper/buildable_stub.rb
|
49
|
+
test/helper/git_helper.rb
|
50
|
+
test/helper/svn_helper.rb
|
51
|
+
test/scm/git_test.rb
|
52
|
+
test/scm/svn_test.rb
|
45
53
|
]
|
46
54
|
end
|
data/lib/bob.rb
CHANGED
@@ -0,0 +1,108 @@
|
|
1
|
+
require "thread"
|
2
|
+
|
3
|
+
module Bob
|
4
|
+
module BackgroundEngines
|
5
|
+
class Threaded
|
6
|
+
|
7
|
+
def initialize(pool_size = 2)
|
8
|
+
@pool = ThreadPool.new(pool_size)
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(job)
|
12
|
+
@pool << job
|
13
|
+
end
|
14
|
+
|
15
|
+
def njobs
|
16
|
+
@pool.njobs
|
17
|
+
end
|
18
|
+
|
19
|
+
def wait!
|
20
|
+
Thread.pass until @pool.njobs == 0
|
21
|
+
end
|
22
|
+
|
23
|
+
class ThreadPool
|
24
|
+
class Incrementor
|
25
|
+
def initialize(v = 0)
|
26
|
+
@m = Mutex.new
|
27
|
+
@v = v
|
28
|
+
end
|
29
|
+
|
30
|
+
def inc(v = 1)
|
31
|
+
sync { @v += v }
|
32
|
+
end
|
33
|
+
|
34
|
+
def dec(v = 1)
|
35
|
+
sync { @v -= v }
|
36
|
+
end
|
37
|
+
|
38
|
+
def inspect
|
39
|
+
@v.inspect
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_i
|
43
|
+
@v
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def sync(&b)
|
49
|
+
@m.synchronize &b
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
attr_reader :size, :jobs
|
54
|
+
|
55
|
+
def size=(other)
|
56
|
+
@size = other
|
57
|
+
|
58
|
+
if @workers.size > @size
|
59
|
+
(@workers.size - @size).times do
|
60
|
+
@workers.shift[:run] = false
|
61
|
+
end
|
62
|
+
else
|
63
|
+
(@size - @workers.size).times do
|
64
|
+
@workers << spawn
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def initialize(size = nil)
|
70
|
+
size ||= 2
|
71
|
+
@jobs = Queue.new
|
72
|
+
@njobs = Incrementor.new
|
73
|
+
@workers = Array.new(size) { spawn }
|
74
|
+
end
|
75
|
+
|
76
|
+
def add(*jobs, &blk)
|
77
|
+
jobs = jobs + Array(blk)
|
78
|
+
|
79
|
+
jobs.each do |job|
|
80
|
+
@jobs << job
|
81
|
+
@njobs.inc
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
alias_method :push, :add
|
86
|
+
alias_method :<<, :add
|
87
|
+
|
88
|
+
def njobs
|
89
|
+
@njobs.to_i
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def spawn
|
95
|
+
Thread.new do
|
96
|
+
c = Thread.current
|
97
|
+
c[:run] = true
|
98
|
+
|
99
|
+
while c[:run]
|
100
|
+
@jobs.pop.call
|
101
|
+
@njobs.dec
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Bob
|
2
|
+
# Mixin to add to your classes.
|
3
|
+
module Buildable
|
4
|
+
# Builds the list of commits you pass. You must provide an
|
5
|
+
# enumerable with commit identifiers appropriate to the
|
6
|
+
# repository the code is in (SHAs if git, rev numbers if svn,
|
7
|
+
# etc), or a single string with a commit id.
|
8
|
+
def build(commits)
|
9
|
+
Bob.build(self, commits)
|
10
|
+
end
|
11
|
+
|
12
|
+
# What kind of repository this buildable represents. Must
|
13
|
+
# return a Symbol (:git, :svn, etc.)
|
14
|
+
#
|
15
|
+
# <b>You must implement this in the classes where you mixin this module</b>
|
16
|
+
def kind
|
17
|
+
raise NotImplementedError
|
18
|
+
end
|
19
|
+
|
20
|
+
# Full URI to the repository to clone/checkout.
|
21
|
+
#
|
22
|
+
# <b>You must implement this in the classes where you mixin this module</b>
|
23
|
+
def uri
|
24
|
+
raise NotImplementedError
|
25
|
+
end
|
26
|
+
|
27
|
+
# Branch of the code you want to watch in order to build.
|
28
|
+
#
|
29
|
+
# <b>You must implement this in the classes where you mixin this module</b>
|
30
|
+
def branch
|
31
|
+
raise NotImplementedError
|
32
|
+
end
|
33
|
+
|
34
|
+
# Script that will be run in the buildable's checked out code,
|
35
|
+
# if it returns a status code of 0 it will be considered a
|
36
|
+
# successfull build. Else it will be considered a failed build.
|
37
|
+
#
|
38
|
+
# <b>You must implement this in the classes where you mixin this module</b>
|
39
|
+
def build_script
|
40
|
+
raise NotImplementedError
|
41
|
+
end
|
42
|
+
|
43
|
+
# Callback sent when a build starts. The first argument is a
|
44
|
+
# string with whatever identifier is appropriate for a repository
|
45
|
+
# of this kind. The second is a hash with information about the
|
46
|
+
# commit.
|
47
|
+
#
|
48
|
+
# <tt>:author</tt>:: A string with the name/email of the committer
|
49
|
+
# <tt>:message</tt>:: The commit message
|
50
|
+
# <tt>:committed_at</tt>:: A Time object with the timestamp of the
|
51
|
+
# commit
|
52
|
+
#
|
53
|
+
# <b>You must implement this in the classes where you mixin this module</b>
|
54
|
+
def start_building(commit_id, commit_info)
|
55
|
+
raise NotImplementedError
|
56
|
+
end
|
57
|
+
|
58
|
+
# Callback sent after a build finishes. The first argument is a
|
59
|
+
# string with whatever identifier is appropriate for a respository
|
60
|
+
# of this kind. The second is a boolean which is true if the build
|
61
|
+
# was successful or false if it failed. And the last one is a string
|
62
|
+
# with the full output returned by the build process (STDOUT and
|
63
|
+
# STDERR interleaved)
|
64
|
+
#
|
65
|
+
# <b>You must implement this in the classes where you mixin this module</b>
|
66
|
+
def finish_building(commit_id, build_status, build_output)
|
67
|
+
raise NotImplementedError
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/bob/scm/abstract.rb
CHANGED
@@ -35,8 +35,8 @@ module Bob
|
|
35
35
|
|
36
36
|
protected
|
37
37
|
|
38
|
-
def run(command)
|
39
|
-
command = "(cd #{working_dir} && #{command} &>/dev/null)"
|
38
|
+
def run(command, cd_into_working_dir=true)
|
39
|
+
command = "(#{cd_into_working_dir ? "cd #{working_dir} && " : ""}#{command} &>/dev/null)"
|
40
40
|
Bob.logger.debug command
|
41
41
|
system(command) || raise(CantRunCommand, "Couldn't run SCM command `#{command}`")
|
42
42
|
end
|
data/lib/bob/scm/git.rb
CHANGED
@@ -29,10 +29,8 @@ module Bob
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def clone
|
32
|
-
git "clone #{uri} #{working_dir}"
|
33
|
-
rescue CantRunCommand
|
34
32
|
FileUtils.rm_r working_dir
|
35
|
-
|
33
|
+
run "git clone #{uri} #{working_dir}", false
|
36
34
|
end
|
37
35
|
|
38
36
|
def fetch
|
@@ -45,10 +43,6 @@ module Bob
|
|
45
43
|
git "reset --hard #{commit_id}"
|
46
44
|
end
|
47
45
|
|
48
|
-
def reset(commit_id)
|
49
|
-
git "reset --hard #{commit_id}"
|
50
|
-
end
|
51
|
-
|
52
46
|
def git(command)
|
53
47
|
run "git #{command}"
|
54
48
|
end
|
data/lib/bob/scm/svn.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require "bob/scm/abstract"
|
2
|
+
|
3
|
+
module Bob
|
4
|
+
module SCM
|
5
|
+
class Svn < Abstract
|
6
|
+
def info(revision)
|
7
|
+
dump = %x[svn log --non-interactive --revision #{revision} #{uri}].split("\n")
|
8
|
+
meta = dump[1].split(" | ")
|
9
|
+
|
10
|
+
{ :message => dump[3],
|
11
|
+
:author => meta[1],
|
12
|
+
:committed_at => Time.parse(meta[2]) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def with_commit(commit_id)
|
16
|
+
update_code
|
17
|
+
checkout(commit_id)
|
18
|
+
yield
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def path_from_uri
|
24
|
+
"svn-#{uri.path[1..-1]}"
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def update_code
|
30
|
+
initial_checkout unless checked_out?
|
31
|
+
end
|
32
|
+
|
33
|
+
def checkout(revision)
|
34
|
+
run("svn up -q -r#{revision}")
|
35
|
+
end
|
36
|
+
|
37
|
+
def initial_checkout(revision=nil)
|
38
|
+
run("svn co -q #{uri} #{working_dir}")
|
39
|
+
end
|
40
|
+
|
41
|
+
def checked_out?
|
42
|
+
File.directory?(working_dir + "/.svn")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../helper"
|
2
|
+
|
3
|
+
class ThreadedBobTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
super
|
6
|
+
|
7
|
+
@repo = GitRepo.new(:test_repo)
|
8
|
+
@repo.create
|
9
|
+
|
10
|
+
@buildable = GitBuildableStub.new(@repo)
|
11
|
+
end
|
12
|
+
|
13
|
+
test "with a successful threaded build" do
|
14
|
+
old_engine = Bob.engine
|
15
|
+
|
16
|
+
repo.add_successful_commit
|
17
|
+
commit_id = repo.commits.first[:identifier]
|
18
|
+
|
19
|
+
begin
|
20
|
+
Thread.abort_on_exception = true
|
21
|
+
Bob.engine = Bob::BackgroundEngines::Threaded.new(5)
|
22
|
+
Bob.build(buildable, commit_id)
|
23
|
+
Bob.engine.wait!
|
24
|
+
|
25
|
+
status, output = buildable.builds[commit_id]
|
26
|
+
assert_equal :successful, status
|
27
|
+
assert_equal "Running tests...\n", output
|
28
|
+
|
29
|
+
commit = buildable.metadata[commit_id]
|
30
|
+
assert_equal "This commit will work", commit[:message]
|
31
|
+
assert_equal Time.now.min, commit[:committed_at].min
|
32
|
+
ensure
|
33
|
+
Bob.engine = old_engine
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/test/helper.rb
CHANGED
@@ -16,9 +16,6 @@ require "git_helper"
|
|
16
16
|
require "svn_helper"
|
17
17
|
require "buildable_stub"
|
18
18
|
|
19
|
-
Bob.logger = Logger.new("/dev/null")
|
20
|
-
Bob.engine = Bob::BackgroundEngines::Foreground
|
21
|
-
Bob.directory = File.expand_path(File.dirname(__FILE__) + "/../tmp")
|
22
19
|
|
23
20
|
class Test::Unit::TestCase
|
24
21
|
include Bob
|
@@ -27,6 +24,10 @@ class Test::Unit::TestCase
|
|
27
24
|
attr_reader :repo, :buildable
|
28
25
|
|
29
26
|
def setup
|
30
|
-
|
27
|
+
Bob.logger = Logger.new("/dev/null")
|
28
|
+
Bob.engine = Bob::BackgroundEngines::Foreground
|
29
|
+
Bob.directory = File.expand_path(File.dirname(__FILE__) + "/../tmp")
|
30
|
+
|
31
|
+
FileUtils.rm_rf(Bob.directory) if File.directory?(Bob.directory)
|
31
32
|
end
|
32
33
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module TestHelper
|
2
|
+
class AbstractSCMRepo
|
3
|
+
attr_reader :path, :name
|
4
|
+
|
5
|
+
def initialize(name, base_dir=Bob.directory)
|
6
|
+
@name = name
|
7
|
+
@path = File.join(base_dir, @name.to_s)
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_commit(message, &action)
|
11
|
+
Dir.chdir(@path) do
|
12
|
+
yield action
|
13
|
+
commit(message)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_failing_commit
|
18
|
+
add_commit "This commit will fail" do
|
19
|
+
system "echo '#{build_script(false)}' > test"
|
20
|
+
system "chmod +x test"
|
21
|
+
add "test &>/dev/null"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_successful_commit
|
26
|
+
add_commit "This commit will work" do
|
27
|
+
system "echo '#{build_script(true)}' > test"
|
28
|
+
system "chmod +x test"
|
29
|
+
add "test"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
def add(file)
|
35
|
+
raise NotImplementedError
|
36
|
+
end
|
37
|
+
|
38
|
+
def commit(message)
|
39
|
+
raise NotImplementedError
|
40
|
+
end
|
41
|
+
|
42
|
+
def build_script(successful=true)
|
43
|
+
<<-script
|
44
|
+
#!/bin/sh
|
45
|
+
echo "Running tests..."
|
46
|
+
exit #{successful ? 0 : 1}
|
47
|
+
script
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/test/helper/git_helper.rb
CHANGED
@@ -17,7 +17,7 @@ module TestHelper
|
|
17
17
|
|
18
18
|
def commits
|
19
19
|
Dir.chdir(@path) do
|
20
|
-
commits = `git log --pretty=oneline`.collect { |l| l.split(" ").first }
|
20
|
+
commits = `git log --pretty=oneline`.each_line.collect { |l| l.split(" ").first }
|
21
21
|
commits.inject([]) do |commits, sha1|
|
22
22
|
format = "---%n:message: >-%n %s%n:timestamp: %ci%n" +
|
23
23
|
":identifier: %H%n:author: %n :name: %an%n :email: %ae%n"
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/abstract_scm_helper"
|
2
|
+
|
3
|
+
module TestHelper
|
4
|
+
class SvnRepo < AbstractSCMRepo
|
5
|
+
def self.server_root
|
6
|
+
@root ||= File.join(Bob.directory, "svn")
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :remote
|
10
|
+
|
11
|
+
def initialize(name, base_dir=Bob.directory)
|
12
|
+
super
|
13
|
+
|
14
|
+
@path = File.join(base_dir, "svn-#{name}")
|
15
|
+
@remote = File.join(SvnRepo.server_root, name.to_s)
|
16
|
+
end
|
17
|
+
|
18
|
+
def create
|
19
|
+
create_remote
|
20
|
+
|
21
|
+
system "svn checkout file://#{remote} #{path} &>/dev/null"
|
22
|
+
|
23
|
+
add_commit("First commit") do
|
24
|
+
system "echo 'just a test repo' >> README"
|
25
|
+
add "README"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def commits
|
30
|
+
Dir.chdir(path) do
|
31
|
+
doc = Hpricot::XML(`svn log --xml`)
|
32
|
+
|
33
|
+
(doc/:log/:logentry).inject([]) { |commits, commit|
|
34
|
+
commits << { :identifier => commit["revision"],
|
35
|
+
:message => commit.at("msg").inner_html,
|
36
|
+
:committed_at => Time.parse(commit.at("date").inner_html) }
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def head
|
42
|
+
commits.first[:identifier]
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
def add(file)
|
47
|
+
system "svn add #{file} &>/dev/null"
|
48
|
+
end
|
49
|
+
|
50
|
+
def commit(message)
|
51
|
+
system %Q{svn commit -m "#{message}" &>/dev/null}
|
52
|
+
system "svn up &>/dev/null"
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
def create_remote
|
57
|
+
FileUtils.mkdir_p(SvnRepo.server_root)
|
58
|
+
|
59
|
+
system "svnadmin create #{remote} &>/dev/null"
|
60
|
+
|
61
|
+
File.open(File.join(remote, "conf", "svnserve.conf"), "w") { |f|
|
62
|
+
f.puts "[general]"
|
63
|
+
f.puts "anon-access = write"
|
64
|
+
f.puts "auth-access = write"
|
65
|
+
}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../helper"
|
2
|
+
|
3
|
+
class BobGitTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
super
|
6
|
+
|
7
|
+
@repo = GitRepo.new(:test_repo)
|
8
|
+
@repo.create
|
9
|
+
|
10
|
+
@buildable = GitBuildableStub.new(@repo)
|
11
|
+
end
|
12
|
+
|
13
|
+
test "with a successful build" do
|
14
|
+
repo.add_successful_commit
|
15
|
+
|
16
|
+
commit_id = repo.commits.first[:identifier]
|
17
|
+
|
18
|
+
buildable.build(commit_id)
|
19
|
+
|
20
|
+
status, output = buildable.builds[commit_id]
|
21
|
+
assert_equal :successful, status
|
22
|
+
assert_equal "Running tests...\n", output
|
23
|
+
|
24
|
+
assert_equal 1, buildable.metadata.length
|
25
|
+
|
26
|
+
commit = buildable.metadata[commit_id]
|
27
|
+
assert_equal "This commit will work", commit[:message]
|
28
|
+
assert commit[:committed_at].is_a?(Time)
|
29
|
+
end
|
30
|
+
|
31
|
+
test "with a failed build" do
|
32
|
+
repo.add_failing_commit
|
33
|
+
|
34
|
+
commit_id = repo.commits.first[:identifier]
|
35
|
+
|
36
|
+
buildable.build(commit_id)
|
37
|
+
|
38
|
+
status, output = buildable.builds[commit_id]
|
39
|
+
assert_equal :failed, status
|
40
|
+
assert_equal "Running tests...\n", output
|
41
|
+
|
42
|
+
assert_equal 1, buildable.metadata.length
|
43
|
+
|
44
|
+
commit = buildable.metadata[commit_id]
|
45
|
+
assert_equal "This commit will fail", commit[:message]
|
46
|
+
assert commit[:committed_at].is_a?(Time)
|
47
|
+
end
|
48
|
+
|
49
|
+
test "with multiple commits" do
|
50
|
+
2.times { repo.add_failing_commit }
|
51
|
+
commits = repo.commits.collect { |c| c[:identifier] }
|
52
|
+
|
53
|
+
buildable.build(commits)
|
54
|
+
|
55
|
+
assert_equal 2, commits.length
|
56
|
+
assert_equal 2, buildable.metadata.length
|
57
|
+
assert_equal 2, buildable.builds.length
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../helper"
|
2
|
+
|
3
|
+
class BobSvnTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
super
|
6
|
+
|
7
|
+
@repo = SvnRepo.new(:test_repo)
|
8
|
+
@repo.create
|
9
|
+
|
10
|
+
@buildable = SvnBuildableStub.new(@repo)
|
11
|
+
end
|
12
|
+
|
13
|
+
test "with a successful build" do
|
14
|
+
repo.add_successful_commit
|
15
|
+
|
16
|
+
buildable.build("2")
|
17
|
+
|
18
|
+
assert_equal 1, buildable.metadata.length
|
19
|
+
|
20
|
+
status, output = buildable.builds["2"]
|
21
|
+
assert_equal :successful, status
|
22
|
+
assert_equal "Running tests...\n", output
|
23
|
+
|
24
|
+
assert_equal 1, buildable.metadata.length
|
25
|
+
|
26
|
+
commit = buildable.metadata["2"]
|
27
|
+
assert commit[:committed_at].is_a?(Time)
|
28
|
+
assert_equal "This commit will work", commit[:message]
|
29
|
+
end
|
30
|
+
|
31
|
+
test "with a failed build" do
|
32
|
+
repo.add_failing_commit
|
33
|
+
commit_id = repo.commits.first[:identifier]
|
34
|
+
|
35
|
+
buildable.build(commit_id)
|
36
|
+
|
37
|
+
status, output = buildable.builds[commit_id]
|
38
|
+
assert_equal :failed, status
|
39
|
+
assert_equal "Running tests...\n", output
|
40
|
+
|
41
|
+
assert_equal 1, buildable.metadata.length
|
42
|
+
|
43
|
+
commit = buildable.metadata[commit_id]
|
44
|
+
assert commit[:committed_at].is_a?(Time)
|
45
|
+
assert_equal "This commit will fail", commit[:message]
|
46
|
+
end
|
47
|
+
|
48
|
+
test "with multiple commits" do
|
49
|
+
repo.add_successful_commit
|
50
|
+
2.times { repo.add_failing_commit }
|
51
|
+
|
52
|
+
buildable.build(repo.commits.collect { |c| c[:identifier] })
|
53
|
+
|
54
|
+
assert_equal 3, buildable.metadata.length
|
55
|
+
assert_equal 3, buildable.builds.length
|
56
|
+
end
|
57
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bob-the-builder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Nicol\xC3\xA1s Sanguinetti"
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2009-05-
|
13
|
+
date: 2009-05-08 00:00:00 -03:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -80,17 +80,27 @@ files:
|
|
80
80
|
- lib/bob.rb
|
81
81
|
- lib/bob/background_engines.rb
|
82
82
|
- lib/bob/background_engines/foreground.rb
|
83
|
+
- lib/bob/background_engines/threaded.rb
|
83
84
|
- lib/bob/builder.rb
|
85
|
+
- lib/bob/buildable.rb
|
84
86
|
- lib/bob/scm.rb
|
85
87
|
- lib/bob/scm/abstract.rb
|
86
88
|
- lib/bob/scm/git.rb
|
89
|
+
- lib/bob/scm/svn.rb
|
87
90
|
- lib/core_ext/object.rb
|
91
|
+
- test/background_engine/threaded_test.rb
|
88
92
|
- test/bob_test.rb
|
89
93
|
- test/helper.rb
|
90
|
-
- test/helper/
|
94
|
+
- test/helper/abstract_scm_helper.rb
|
91
95
|
- test/helper/buildable_stub.rb
|
96
|
+
- test/helper/git_helper.rb
|
97
|
+
- test/helper/svn_helper.rb
|
98
|
+
- test/scm/git_test.rb
|
99
|
+
- test/scm/svn_test.rb
|
92
100
|
has_rdoc: true
|
93
101
|
homepage: http://integrityapp.com
|
102
|
+
licenses: []
|
103
|
+
|
94
104
|
post_install_message:
|
95
105
|
rdoc_options: []
|
96
106
|
|
@@ -111,9 +121,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
121
|
requirements: []
|
112
122
|
|
113
123
|
rubyforge_project: bob-the-builder
|
114
|
-
rubygems_version: 1.3.
|
124
|
+
rubygems_version: 1.3.3
|
115
125
|
signing_key:
|
116
|
-
specification_version:
|
126
|
+
specification_version: 3
|
117
127
|
summary: Bob builds!
|
118
128
|
test_files: []
|
119
129
|
|