integrity-bob 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -27,7 +27,6 @@ desc "Run unit tests"
27
27
  task :test => SCMs.map { |scm| "test:#{scm}" } do
28
28
  ruby "test/bob_test.rb"
29
29
  ruby "test/test_test.rb"
30
- ruby "test/engine/threaded_test.rb"
31
30
  end
32
31
 
33
32
  SCMs.each { |scm|
data/bob.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "bob"
3
- s.version = "0.3.0"
3
+ s.version = "0.3.1"
4
4
  s.date = "2009-07-02"
5
5
 
6
6
  s.description = "Bob the Builder will build your code. Simple."
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
16
16
  s.rubygems_version = "1.3.1"
17
17
 
18
18
  s.add_dependency "addressable"
19
+ s.add_dependency "ninja"
19
20
 
20
21
  if s.respond_to?(:add_development_dependency)
21
22
  s.add_development_dependency "sr-mg"
@@ -31,11 +32,8 @@ README.rdoc
31
32
  Rakefile
32
33
  bob.gemspec
33
34
  lib/bob.rb
34
- lib/bob/buildable.rb
35
35
  lib/bob/builder.rb
36
- lib/bob/engine.rb
37
- lib/bob/engine/foreground.rb
38
- lib/bob/engine/threaded.rb
36
+ lib/bob/buildable.rb
39
37
  lib/bob/scm.rb
40
38
  lib/bob/scm/abstract.rb
41
39
  lib/bob/scm/git.rb
@@ -45,9 +43,7 @@ lib/bob/test/buildable_stub.rb
45
43
  lib/bob/test/scm/abstract.rb
46
44
  lib/bob/test/scm/git.rb
47
45
  lib/bob/test/scm/svn.rb
48
- lib/core_ext/object.rb
49
46
  test/bob_test.rb
50
- test/engine/threaded_test.rb
51
47
  test/helper.rb
52
48
  test/scm/git_test.rb
53
49
  test/scm/svn_test.rb
data/lib/bob.rb CHANGED
@@ -1,14 +1,14 @@
1
1
  require "fileutils"
2
+ require "pathname"
2
3
  require "yaml"
3
4
  require "logger"
4
5
  require "time"
6
+ require "ninja"
5
7
  require "addressable/uri"
6
8
 
7
9
  require "bob/buildable"
8
10
  require "bob/builder"
9
11
  require "bob/scm"
10
- require "bob/engine"
11
- require "core_ext/object"
12
12
 
13
13
  module Bob
14
14
  # Builds the specified <tt>buildable</tt>. This object must understand
@@ -20,14 +20,7 @@ module Bob
20
20
  # Directory where the code for the different buildables will be checked out.
21
21
  # Make sure the user running Bob is allowed to write to this directory.
22
22
  def self.directory
23
- @directory || "/tmp"
24
- end
25
-
26
- # What will you use to build in background. Must respond to <tt>call</tt> and
27
- # take a block which will be run "in background". The default is to run in
28
- # foreground.
29
- def self.engine
30
- @engine || Engine::Foreground
23
+ Pathname(@directory || "/tmp")
31
24
  end
32
25
 
33
26
  # What to log with (must implement ruby's Logger interface). Logs to STDOUT
@@ -37,6 +30,6 @@ module Bob
37
30
  end
38
31
 
39
32
  class << self
40
- attr_writer :directory, :engine, :logger
33
+ attr_writer :directory, :logger
41
34
  end
42
35
  end
data/lib/bob/buildable.rb CHANGED
@@ -7,7 +7,7 @@ module Bob
7
7
  end
8
8
 
9
9
  # What kind of repository this buildable represents. Must
10
- # return a Symbol (:git, :svn, etc.)
10
+ # return a String ("git", "svn", etc.)
11
11
  #
12
12
  # <b>You must implement this in the classes where you mixin this module</b>
13
13
  def scm
@@ -48,30 +48,26 @@ module Bob
48
48
  raise NotImplementedError
49
49
  end
50
50
 
51
- # Callback sent when a build starts. The first argument is a
52
- # string with whatever identifier is appropriate for a repository
53
- # of this kind. The second is a hash with information about the
54
- # commit.
55
- #
56
- # <tt>:author</tt>:: A string with the name/email of the committer
57
- # <tt>:message</tt>:: The commit message
58
- # <tt>:committed_at</tt>:: A Time object with the timestamp of the
59
- # commit
60
- #
61
- # <b>You must implement this in the classes where you mixin this module</b>
62
- def start_building(commit_id, commit_info)
63
- raise NotImplementedError
51
+ # Optional callback sent when the build starts. It can be used to calculate
52
+ # the build duration for example.
53
+ def start_building
64
54
  end
65
55
 
66
- # Callback sent after a build finishes. The first argument is a
67
- # string with whatever identifier is appropriate for a respository
68
- # of this kind. The second is a boolean which is true if the build
69
- # was successful or false if it failed. And the last one is a string
70
- # with the full output returned by the build process (STDOUT and
71
- # STDERR interleaved)
56
+ # Callback sent after a build finishes. The first argument is a hash with
57
+ # information about the commit.
58
+ #
59
+ # <tt>identifier</tt>:: A string with the commit identifier of the
60
+ # commit that was built
61
+ # <tt>author</tt>:: A string with the name/email of the committer
62
+ # <tt>message</tt>:: The commit message
63
+ # <tt>committed_at</tt>:: A Time object with the timestamp of the commit
64
+ #
65
+ # The second argument is a boolean indicating whether the build was
66
+ # successful. Finally, the last one is a string with the full output
67
+ # returned by the build process (STDOUT and STDERR interleaved)
72
68
  #
73
69
  # <b>You must implement this in the classes where you mixin this module</b>
74
- def finish_building(commit_id, build_status, build_output)
70
+ def finish_building(commit_info, build_status, build_output)
75
71
  raise NotImplementedError
76
72
  end
77
73
  end
data/lib/bob/builder.rb CHANGED
@@ -4,6 +4,8 @@ module Bob
4
4
  class Builder
5
5
  attr_reader :buildable
6
6
 
7
+ include Ninja
8
+
7
9
  # Instantiate the Builder, passing an object that understands
8
10
  # the <tt>Buildable</tt> interface.
9
11
  def initialize(buildable)
@@ -12,28 +14,24 @@ module Bob
12
14
 
13
15
  # This is where the magic happens:
14
16
  #
15
- # 1. Check out the repo to the appropriate commit.
16
- # 2. Notify the buildable that the build is starting.
17
- # 3. Run the build script on it in the background.
17
+ # 1. Notify the buildable that the build is starting.
18
+ # 2. Check out the repo to the appropriate commit.
19
+ # 3. Run the build script on it.
18
20
  # 4. Reports the build back to the buildable.
19
21
  def build
20
22
  Bob.logger.info "Building #{buildable.commit} of the #{buildable.scm} repo at #{buildable.uri}"
21
23
 
22
24
  in_background do
23
- scm.with_commit(commit) {
24
- buildable.start_building(commit, scm.info(commit))
25
- build_status, build_output = run_build_script
26
- buildable.finish_building(commit, build_status, build_output)
25
+ buildable.start_building if buildable.respond_to?(:start_building)
26
+
27
+ scm.with_commit(buildable.commit) { |commit_info|
28
+ buildable.finish_building(commit_info, *run_build_script)
27
29
  }
28
30
  end
29
31
  end
30
32
 
31
33
  private
32
34
 
33
- def commit
34
- @commit ||= buildable.commit == :head ? scm.head : buildable.commit
35
- end
36
-
37
35
  def run_build_script
38
36
  build_output = nil
39
37
 
@@ -45,15 +43,11 @@ module Bob
45
43
  end
46
44
 
47
45
  def build_script
48
- "(cd #{scm.directory_for(commit)} && #{buildable.build_script} 2>&1)"
46
+ "(cd #{scm.dir_for(buildable.commit)} && #{buildable.build_script} 2>&1)"
49
47
  end
50
48
 
51
49
  def scm
52
50
  @scm ||= SCM.new(buildable.scm, buildable.uri, buildable.branch)
53
51
  end
54
-
55
- def in_background(&block)
56
- Bob.engine.call(block)
57
- end
58
52
  end
59
53
  end
@@ -11,23 +11,27 @@ module Bob
11
11
  # Checkout the code at the specified <tt>commit</tt> and call the
12
12
  # passed block.
13
13
  def with_commit(commit)
14
- update_code(commit)
14
+ commit = resolve(commit)
15
15
  checkout(commit)
16
- yield
16
+ yield info(commit)
17
17
  end
18
18
 
19
19
  # Directory where the code will be checked out for the given
20
20
  # <tt>commit</tt>.
21
- def directory_for(commit)
22
- File.join(Bob.directory, "#{path}-#{commit}")
21
+ def dir_for(commit)
22
+ commit = resolve(commit)
23
+ Bob.directory.join(path, "-", commit)
23
24
  end
24
25
 
26
+ protected
27
+
25
28
  # Get some information about the specified <tt>commit</tt>.
26
29
  # Returns a hash with:
27
30
  #
28
- # [<tt>:author</tt>] Commit author's name and email
29
- # [<tt>:message</tt>] Commit message
30
- # [<tt>:committed_at</tt>] Commit date (as a <tt>Time</tt> object)
31
+ # [<tt>identifier</tt>] Commit identifier
32
+ # [<tt>author</tt>] Commit author's name and email
33
+ # [<tt>message</tt>] Commit message
34
+ # [<tt>committed_at</tt>] Commit date (as a <tt>Time</tt> object)
31
35
  def info(commit)
32
36
  raise NotImplementedError
33
37
  end
@@ -38,8 +42,6 @@ module Bob
38
42
  raise NotImplementedError
39
43
  end
40
44
 
41
- protected
42
-
43
45
  def run(command, directory=nil)
44
46
  command = "(#{directory ? "cd #{directory} && " : ""}#{command} &>/dev/null)"
45
47
  Bob.logger.debug(command)
@@ -52,6 +54,12 @@ module Bob
52
54
  gsub(/[ \-]+/i, '-'). # No more than one of the separator in a row.
53
55
  gsub(/^\-|\-$/i, '') # Remove leading/trailing separator.
54
56
  end
57
+
58
+ private
59
+
60
+ def resolve(commit)
61
+ commit == :head ? head : commit
62
+ end
55
63
  end
56
64
  end
57
65
  end
data/lib/bob/scm/git.rb CHANGED
@@ -1,19 +1,16 @@
1
1
  module Bob
2
2
  module SCM
3
3
  class Git < Abstract
4
- def initialize(uri, branch)
5
- super
6
-
7
- unless File.directory?(File.join(Bob.directory, "cache"))
8
- FileUtils.mkdir(File.join(Bob.directory, "cache"))
9
- end
10
- end
4
+ protected
11
5
 
12
6
  def info(commit)
13
- format = %Q(---%n:author: %an <%ae>%n:message: >-%n %s%n:committed_at: %ci%n)
14
- YAML.load(`cd #{directory_for(commit)} && git show -s --pretty=format:"#{format}" #{commit}`).tap { |info|
15
- info[:committed_at] = Time.parse(info[:committed_at])
16
- }
7
+ format = "---%nidentifier: %H%nauthor: %an \
8
+ <%ae>%nmessage: >-%n %s%ncommitted_at: %ci%n"
9
+
10
+ dump = YAML.load(`cd #{dir_for(commit)} && git show -s \
11
+ --pretty=format:"#{format}" #{commit}`)
12
+
13
+ dump.update("committed_at" => Time.parse(dump["committed_at"]))
17
14
  end
18
15
 
19
16
  def head
@@ -22,30 +19,15 @@ module Bob
22
19
 
23
20
  private
24
21
 
25
- def update_code(commit)
26
- unless File.directory?("#{cache_directory}/.git")
27
- run "git clone -n #{uri} #{cache_directory}"
28
- end
29
-
30
- run "git fetch origin", cache_directory
31
- run "git checkout origin/#{branch}", cache_directory
32
- end
33
-
34
22
  def checkout(commit)
35
- unless File.directory?("#{directory_for(commit)}/.git")
36
- run "git clone -ns #{cache_directory} #{directory_for(commit)}"
37
- end
38
-
39
- run "git fetch origin", directory_for(commit)
40
-
41
- # First checkout the branch just in case the commit_id
42
- # turns out to be HEAD or other non-sha identifier
43
- run "git checkout origin/#{branch}", directory_for(commit)
44
- run "git reset --hard #{commit}", directory_for(commit)
23
+ run "git clone #{uri} #{dir_for(commit)}" unless cloned?(commit)
24
+ run "git fetch origin", dir_for(commit)
25
+ run "git checkout origin/#{branch}", dir_for(commit)
26
+ run "git reset --hard #{commit}", dir_for(commit)
45
27
  end
46
28
 
47
- def cache_directory
48
- File.join(Bob.directory, "cache", path)
29
+ def cloned?(commit)
30
+ dir_for(commit).join(".git").directory?
49
31
  end
50
32
  end
51
33
  end
data/lib/bob/scm/svn.rb CHANGED
@@ -1,38 +1,36 @@
1
- require "bob/scm/abstract"
2
-
3
1
  module Bob
4
2
  module SCM
5
3
  class Svn < Abstract
4
+ protected
5
+
6
6
  def info(revision)
7
7
  dump = `svn log --non-interactive --revision #{revision} #{uri}`.split("\n")
8
8
  meta = dump[1].split(" | ")
9
9
 
10
- { :message => dump[3],
11
- :author => meta[1],
12
- :committed_at => Time.parse(meta[2]) }
10
+ { "identifier" => revision,
11
+ "message" => dump[3],
12
+ "author" => meta[1],
13
+ "committed_at" => Time.parse(meta[2]) }
13
14
  end
14
15
 
16
+
15
17
  def head
16
18
  `svn info #{uri}`.split("\n").detect { |l| l =~ /^Revision: (\d+)/ }
17
19
  $1.to_s
18
20
  end
19
21
 
20
- private
21
-
22
- def update_code(commit)
23
- initial_checkout(commit) unless checked_out?(commit)
24
- end
22
+ private
25
23
 
26
24
  def checkout(revision)
27
- run "svn up -q -r#{revision}", directory_for(revision)
28
- end
25
+ unless checked_out?(revision)
26
+ run "svn co -q #{uri} #{dir_for(revision)}"
27
+ end
29
28
 
30
- def initial_checkout(revision=nil)
31
- run "svn co -q #{uri} #{directory_for(revision)}"
29
+ run "svn up -q -r#{revision}", dir_for(revision)
32
30
  end
33
31
 
34
32
  def checked_out?(commit)
35
- File.directory?(directory_for(commit) + "/.svn")
33
+ dir_for(commit).join(".svn").directory?
36
34
  end
37
35
  end
38
36
  end
@@ -1,38 +1,40 @@
1
1
  module Bob
2
2
  module Test
3
- BuildableStub = Struct.new(:scm, :uri, :branch, :commit, :build_script) do
3
+ class BuildableStub
4
4
  include Bob::Buildable
5
5
 
6
6
  def self.for(repo, commit)
7
- scm = (Bob::Test::GitRepo === repo) ? :git : :svn
7
+ scm = (Bob::Test::GitRepo === repo) ? "git" : "svn"
8
8
  uri =
9
- if scm == :git
9
+ if scm == "git"
10
10
  repo.path
11
11
  else
12
12
  "file://#{SvnRepo.server_root}/#{repo.name}"
13
13
  end
14
- # move to repo
15
- branch = (scm == :git) ? "master" : ""
14
+ # TODO: move onto repo object?
15
+ branch = (scm == "git") ? "master" : ""
16
16
  build_script = "./test"
17
17
 
18
18
  new(scm, uri, branch, commit, build_script)
19
19
  end
20
20
 
21
- attr_reader :repo, :status, :output, :commit_info
21
+ attr_reader :scm, :uri, :branch, :commit, :build_script,
22
+ :repo, :status, :output, :commit_info
22
23
 
23
- def initialize(*args)
24
- super
24
+ def initialize(scm, uri, branch, commit, build_script)
25
+ @scm = scm.to_s
26
+ @uri = uri.to_s
27
+ @branch = branch
28
+ @commit = commit
29
+ @build_script = build_script
25
30
 
26
31
  @status = nil
27
32
  @output = ""
28
33
  @commit_info = {}
29
34
  end
30
35
 
31
- def start_building(commit_id, commit_info)
36
+ def finish_building(commit_info, status, output)
32
37
  @commit_info = commit_info
33
- end
34
-
35
- def finish_building(commit_id, status, output)
36
38
  @status = status ? :successful : :failed
37
39
  @output = output
38
40
  end
@@ -7,10 +7,6 @@ module Bob::Test
7
7
  @path = File.join(base_dir, @name.to_s)
8
8
  end
9
9
 
10
- def destroy
11
- FileUtils.rm_r path if File.directory?(path)
12
- end
13
-
14
10
  def add_commit(message, &action)
15
11
  Dir.chdir(path) do
16
12
  yield action
@@ -39,7 +35,7 @@ module Bob::Test
39
35
  end
40
36
 
41
37
  def head
42
- commits.last[:identifier]
38
+ commits.last["identifier"]
43
39
  end
44
40
 
45
41
  protected
@@ -19,8 +19,8 @@ module Bob::Test
19
19
  Dir.chdir(path) do
20
20
  commits = `git log --pretty=oneline`.collect { |l| l.split(" ").first }
21
21
  commits.inject([]) do |commits, sha1|
22
- format = "---%n:message: >-%n %s%n:timestamp: %ci%n" +
23
- ":identifier: %H%n:author: %n :name: %an%n :email: %ae%n"
22
+ format = "---%nmessage: >-%n %s%ntimestamp: %ci%n" +
23
+ "identifier: %H%nauthor: %n name: %an%n email: %ae%n"
24
24
  commits << YAML.load(`git show -s --pretty=format:"#{format}" #{sha1}`)
25
25
  end.reverse
26
26
  end
@@ -4,7 +4,7 @@ require "hpricot"
4
4
  module Bob::Test
5
5
  class SvnRepo < AbstractSCMRepo
6
6
  def self.server_root
7
- @root ||= File.join(Bob.directory, "svn")
7
+ @root ||= Bob.directory.join("svn")
8
8
  end
9
9
 
10
10
  attr_reader :remote
@@ -12,8 +12,8 @@ module Bob::Test
12
12
  def initialize(name, base_dir=Bob.directory)
13
13
  super
14
14
 
15
- @path = File.join(base_dir, "svn-#{name}")
16
- @remote = File.join(SvnRepo.server_root, name.to_s)
15
+ @path = base_dir.join("svn-#{name}")
16
+ @remote = SvnRepo.server_root.join(name.to_s)
17
17
  end
18
18
 
19
19
  def create
@@ -27,19 +27,14 @@ module Bob::Test
27
27
  end
28
28
  end
29
29
 
30
- def destroy
31
- FileUtils.rm_r(remote) if File.directory?(remote)
32
- super
33
- end
34
-
35
30
  def commits
36
31
  Dir.chdir(path) do
37
32
  doc = Hpricot::XML(`svn log --xml`)
38
33
 
39
34
  (doc/:log/:logentry).inject([]) { |commits, commit|
40
- commits << { :identifier => commit["revision"],
41
- :message => commit.at("msg").inner_html,
42
- :committed_at => Time.parse(commit.at("date").inner_html) }
35
+ commits << { "identifier" => commit["revision"],
36
+ "message" => commit.at("msg").inner_html,
37
+ "committed_at" => Time.parse(commit.at("date").inner_html) }
43
38
  }.reverse
44
39
  end
45
40
  end
@@ -58,7 +53,7 @@ module Bob::Test
58
53
 
59
54
  private
60
55
  def create_remote
61
- FileUtils.mkdir(SvnRepo.server_root)
56
+ SvnRepo.server_root.mkdir
62
57
 
63
58
  run "svnadmin create #{remote}"
64
59
 
data/test/bob_test.rb CHANGED
@@ -3,7 +3,8 @@ require File.dirname(__FILE__) + "/helper"
3
3
  class BobTest < Test::Unit::TestCase
4
4
  test "directory" do
5
5
  Bob.directory = "/foo/bar"
6
- assert_equal "/foo/bar", Bob.directory
6
+ assert_equal "/foo/bar", Bob.directory.to_s
7
+ assert_instance_of Pathname, Bob.directory
7
8
  end
8
9
 
9
10
  test "logger" do
@@ -12,11 +13,4 @@ class BobTest < Test::Unit::TestCase
12
13
 
13
14
  assert_same logger, Bob.logger
14
15
  end
15
-
16
- test "engine" do
17
- engine = Object.new
18
- Bob.engine = engine
19
-
20
- assert_same engine, Bob.engine
21
- end
22
16
  end
data/test/helper.rb CHANGED
@@ -22,10 +22,9 @@ class Test::Unit::TestCase
22
22
 
23
23
  def setup
24
24
  Bob.logger = Logger.new("/dev/null")
25
- Bob.engine = Bob::Engine::Foreground
26
- Bob.directory = File.expand_path(File.dirname(__FILE__) + "/../tmp")
25
+ Bob.directory = Pathname(__FILE__).dirname.join("..", "tmp").expand_path
27
26
 
28
- FileUtils.rm_rf(Bob.directory) if File.directory?(Bob.directory)
29
- FileUtils.mkdir_p(Bob.directory)
27
+ Bob.directory.rmtree if Bob.directory.directory?
28
+ Bob.directory.mkdir
30
29
  end
31
30
  end
data/test/scm/git_test.rb CHANGED
@@ -24,29 +24,31 @@ class BobGitTest < Test::Unit::TestCase
24
24
  test "with a successful build" do
25
25
  repo.add_successful_commit
26
26
 
27
- commit_id = repo.commits.last[:identifier]
27
+ commit_id = repo.commits.last["identifier"]
28
28
 
29
29
  buildable = BuildableStub.for(@repo, commit_id)
30
30
  buildable.build
31
31
 
32
32
  assert_equal :successful, buildable.status
33
33
  assert_equal "Running tests...\n", buildable.output
34
- assert_equal "This commit will work", buildable.commit_info[:message]
35
- assert buildable.commit_info[:committed_at].is_a?(Time)
34
+ assert_equal "This commit will work", buildable.commit_info["message"]
35
+ assert_equal commit_id, buildable.commit_info["identifier"]
36
+ assert buildable.commit_info["committed_at"].is_a?(Time)
36
37
  end
37
38
 
38
39
  test "with a failed build" do
39
40
  repo.add_failing_commit
40
41
 
41
- commit_id = repo.commits.last[:identifier]
42
+ commit_id = repo.commits.last["identifier"]
42
43
  buildable = BuildableStub.for(@repo, commit_id)
43
44
 
44
45
  buildable.build
45
46
 
46
47
  assert_equal :failed, buildable.status
47
48
  assert_equal "Running tests...\n", buildable.output
48
- assert_equal "This commit will fail", buildable.commit_info[:message]
49
- assert buildable.commit_info[:committed_at].is_a?(Time)
49
+ assert_equal "This commit will fail", buildable.commit_info["message"]
50
+ assert_equal commit_id, buildable.commit_info["identifier"]
51
+ assert buildable.commit_info["committed_at"].is_a?(Time)
50
52
  end
51
53
 
52
54
  test "can build the head of a repository" do
@@ -59,5 +61,6 @@ class BobGitTest < Test::Unit::TestCase
59
61
 
60
62
  assert_equal :successful, buildable.status
61
63
  assert_equal "Running tests...\n", buildable.output
64
+ assert_equal repo.head, buildable.commit_info["identifier"]
62
65
  end
63
66
  end
data/test/scm/svn_test.rb CHANGED
@@ -34,8 +34,9 @@ class BobSvnTest < Test::Unit::TestCase
34
34
 
35
35
  assert_equal :successful, buildable.status
36
36
  assert_equal "Running tests...\n", buildable.output
37
- assert_equal "This commit will work", buildable.commit_info[:message]
38
- assert buildable.commit_info[:committed_at].is_a?(Time)
37
+ assert_equal "This commit will work", buildable.commit_info["message"]
38
+ assert_equal "2", buildable.commit_info["identifier"]
39
+ assert buildable.commit_info["committed_at"].is_a?(Time)
39
40
  end
40
41
 
41
42
  test "with a failed build" do
@@ -46,8 +47,9 @@ class BobSvnTest < Test::Unit::TestCase
46
47
 
47
48
  assert_equal :failed, buildable.status
48
49
  assert_equal "Running tests...\n", buildable.output
49
- assert_equal "This commit will fail", buildable.commit_info[:message]
50
- assert buildable.commit_info[:committed_at].is_a?(Time)
50
+ assert_equal "This commit will fail", buildable.commit_info["message"]
51
+ assert_equal "2", buildable.commit_info["identifier"]
52
+ assert buildable.commit_info["committed_at"].is_a?(Time)
51
53
  end
52
54
 
53
55
  test "can build the head of a repository" do
@@ -59,5 +61,6 @@ class BobSvnTest < Test::Unit::TestCase
59
61
 
60
62
  assert_equal :successful, buildable.status
61
63
  assert_equal "Running tests...\n", buildable.output
64
+ assert_equal repo.head, buildable.commit_info["identifier"]
62
65
  end
63
66
  end
data/test/test_test.rb CHANGED
@@ -2,28 +2,27 @@ require File.dirname(__FILE__) + "/helper"
2
2
 
3
3
  class BobTestTest < Test::Unit::TestCase
4
4
  def assert_scm_repo(repo)
5
- repo.destroy
6
5
  repo.create
7
6
 
8
7
  assert_equal 1, repo.commits.size
9
- assert_equal "First commit", repo.commits.first[:message]
8
+ assert_equal "First commit", repo.commits.first["message"]
10
9
 
11
10
  repo.add_failing_commit
12
11
  assert_equal 2, repo.commits.size
13
- assert_equal "This commit will fail", repo.commits.last[:message]
14
- assert_equal repo.commits.last[:identifier], repo.head
12
+ assert_equal "This commit will fail", repo.commits.last["message"]
13
+ assert_equal repo.commits.last["identifier"], repo.head
15
14
  assert repo.short_head
16
15
 
17
16
  repo.add_successful_commit
18
17
  assert_equal 3, repo.commits.size
19
- assert_equal "This commit will work", repo.commits.last[:message]
20
- assert_equal repo.commits.last[:identifier], repo.head
18
+ assert_equal "This commit will work", repo.commits.last["message"]
19
+ assert_equal repo.commits.last["identifier"], repo.head
21
20
  end
22
21
 
23
22
  def test_buildable_stub
24
23
  b = BuildableStub.new(:git, "git://github.com/ry/node", "master", "HEAD", "make")
25
24
 
26
- assert_equal :git, b.scm
25
+ assert_equal "git", b.scm
27
26
  assert_equal "git://github.com/ry/node", b.uri
28
27
  assert_equal "master", b.branch
29
28
  assert_equal "HEAD", b.commit
@@ -37,12 +36,11 @@ class BobTestTest < Test::Unit::TestCase
37
36
 
38
37
  def test_buildable_git_repo
39
38
  repo = GitRepo.new(:test_repo)
40
- repo.destroy
41
39
  repo.create
42
40
 
43
41
  b = BuildableStub.for(repo, repo.head)
44
42
 
45
- assert_equal :git, b.scm
43
+ assert_equal "git", b.scm
46
44
  assert_equal "#{Bob.directory}/test_repo", b.uri
47
45
  assert_equal "master", b.branch
48
46
  assert_equal repo.head, b.commit
@@ -51,12 +49,11 @@ class BobTestTest < Test::Unit::TestCase
51
49
 
52
50
  def test_buildable_svn_repo
53
51
  repo = SvnRepo.new(:test_repo)
54
- repo.destroy
55
52
  repo.create
56
53
 
57
54
  b = BuildableStub.for(repo, repo.head)
58
55
 
59
- assert_equal :svn, b.scm
56
+ assert_equal "svn", b.scm
60
57
  assert_equal "", b.branch
61
58
  assert_equal repo.head, b.commit
62
59
  assert_equal "./test", b.build_script
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: integrity-bob
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Nicol\xC3\xA1s Sanguinetti"
@@ -23,6 +23,16 @@ dependencies:
23
23
  - !ruby/object:Gem::Version
24
24
  version: "0"
25
25
  version:
26
+ - !ruby/object:Gem::Dependency
27
+ name: ninja
28
+ type: :runtime
29
+ version_requirement:
30
+ version_requirements: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ version:
26
36
  - !ruby/object:Gem::Dependency
27
37
  name: sr-mg
28
38
  type: :development
@@ -78,11 +88,8 @@ files:
78
88
  - Rakefile
79
89
  - bob.gemspec
80
90
  - lib/bob.rb
81
- - lib/bob/buildable.rb
82
91
  - lib/bob/builder.rb
83
- - lib/bob/engine.rb
84
- - lib/bob/engine/foreground.rb
85
- - lib/bob/engine/threaded.rb
92
+ - lib/bob/buildable.rb
86
93
  - lib/bob/scm.rb
87
94
  - lib/bob/scm/abstract.rb
88
95
  - lib/bob/scm/git.rb
@@ -92,15 +99,14 @@ files:
92
99
  - lib/bob/test/scm/abstract.rb
93
100
  - lib/bob/test/scm/git.rb
94
101
  - lib/bob/test/scm/svn.rb
95
- - lib/core_ext/object.rb
96
102
  - test/bob_test.rb
97
- - test/engine/threaded_test.rb
98
103
  - test/helper.rb
99
104
  - test/scm/git_test.rb
100
105
  - test/scm/svn_test.rb
101
106
  - test/test_test.rb
102
107
  has_rdoc: true
103
108
  homepage: http://integrityapp.com
109
+ licenses:
104
110
  post_install_message:
105
111
  rdoc_options: []
106
112
 
@@ -121,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
121
127
  requirements: []
122
128
 
123
129
  rubyforge_project: integrity
124
- rubygems_version: 1.2.0
130
+ rubygems_version: 1.3.5
125
131
  signing_key:
126
132
  specification_version: 2
127
133
  summary: Bob builds!
data/lib/bob/engine.rb DELETED
@@ -1,9 +0,0 @@
1
- module Bob
2
- # Different engines to run code in background. An engine is any object
3
- # that responds to #call and takes a Proc object, which should be executed
4
- # "in the background". The different engines are:
5
- module Engine
6
- autoload :Foreground, "bob/engine/foreground"
7
- autoload :Threaded, "bob/engine/threaded"
8
- end
9
- end
@@ -1,6 +0,0 @@
1
- module Bob
2
- module Engine
3
- # Dummy engine that just runs in the foreground (useful for tests).
4
- Foreground = lambda {|b| b.call }
5
- end
6
- end
@@ -1,145 +0,0 @@
1
- require "thread"
2
-
3
- module Bob
4
- module Engine
5
- # A thread pool based build engine. This engine simply adds jobs to an
6
- # in-memory queue, and processes them as soon as possible.
7
- class Threaded
8
- # The optional pool size controls how many threads will be created.
9
- def initialize(pool_size = 2, logger = Bob.logger)
10
- @pool = ThreadPool.new(pool_size)
11
- @logger = logger
12
- end
13
-
14
- # Adds a job to the queue.
15
- def call(job)
16
- @pool << job
17
- end
18
-
19
- # The number of jobs currently in the queue.
20
- def njobs
21
- @pool.njobs
22
- end
23
-
24
- # This method will not return until #njobs returns 0.
25
- def wait!
26
- Thread.pass until @pool.njobs == 0
27
- end
28
-
29
- # Manage a pool of threads, allowing for spin up / spin down of the
30
- # contained threads.
31
- # Simply processes work added to it's queue via #push.
32
- # The default size for the pool is 2 threads.
33
- class ThreadPool
34
- # A thread safe single value for use as a counter.
35
- class Incrementor
36
- # The value passed in will be the initial value.
37
- def initialize(v = 0)
38
- @m = Mutex.new
39
- @v = v
40
- end
41
-
42
- # Add the given value to self, default 1.
43
- def inc(v = 1)
44
- sync { @v += v }
45
- end
46
-
47
- # Subtract the given value to self, default 1.
48
- def dec(v = 1)
49
- sync { @v -= v }
50
- end
51
-
52
- # Simply shows the value inspect for convenience.
53
- def inspect
54
- @v.inspect
55
- end
56
-
57
- # Extract the value.
58
- def to_i
59
- @v
60
- end
61
-
62
- private
63
-
64
- # Wrap the given block in a mutex.
65
- def sync(&b)
66
- @m.synchronize &b
67
- end
68
- end
69
-
70
- # The number of threads in the pool.
71
- attr_reader :size
72
-
73
- # The job queue.
74
- attr_reader :jobs
75
-
76
- # Set the size of the thread pool. Asynchronously run down threads
77
- # that are no longer required, and synchronously spawn new required
78
- # threads.
79
- def size=(other)
80
- @size = other
81
-
82
- if @workers.size > @size
83
- (@workers.size - @size).times do
84
- @workers.shift[:run] = false
85
- end
86
- else
87
- (@size - @workers.size).times do
88
- @workers << spawn
89
- end
90
- end
91
- end
92
-
93
- # Default pool size is 2 threads.
94
- def initialize(size = nil, logger = Bob.logger)
95
- size ||= 2
96
- @jobs = Queue.new
97
- @njobs = Incrementor.new
98
- @workers = Array.new(size) { spawn }
99
- @logger = logger
100
- end
101
-
102
- # Adds a job to the queue, the job can be any number of objects
103
- # responding to call, and/or a block.
104
- def add(*jobs, &blk)
105
- jobs = jobs + Array(blk)
106
-
107
- jobs.each do |job|
108
- @jobs << job
109
- @njobs.inc
110
- end
111
- end
112
-
113
- alias_method :push, :add
114
- alias_method :<<, :add
115
-
116
- # A peak at the number of jobs in the queue. N.B. May differ, but
117
- # should be more accurate than +jobs.size+.
118
- def njobs
119
- @njobs.to_i
120
- end
121
-
122
- private
123
-
124
- # Create a new thread and return it. The thread will run until the
125
- # thread-local value +:run+ is changed to false or nil.
126
- def spawn
127
- Thread.new do
128
- c = Thread.current
129
- c[:run] = true
130
-
131
- while c[:run]
132
- job = @jobs.pop
133
- begin
134
- job.call
135
- rescue Exception => e
136
- @logger.error("Exception occured during build of #{job.uri} commit #{job.commit}: #{e.message}")
137
- end
138
- @njobs.dec
139
- end
140
- end
141
- end
142
- end
143
- end
144
- end
145
- end
@@ -1,7 +0,0 @@
1
- class Object #:nodoc:
2
- # Add Object#tap for backwards compatibility
3
- def tap
4
- yield self
5
- self
6
- end unless method_defined?(:tap)
7
- end
@@ -1,34 +0,0 @@
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
- end
10
-
11
- test "with a successful threaded build" do
12
- old_engine = Bob.engine
13
-
14
- repo.add_successful_commit
15
- commit_id = repo.commits.last[:identifier]
16
- buildable = BuildableStub.for(@repo, commit_id)
17
-
18
- begin
19
- Thread.abort_on_exception = true
20
- Bob.engine = Bob::Engine::Threaded.new(5)
21
- buildable.build
22
- Bob.engine.wait!
23
-
24
- assert_equal :successful, buildable.status
25
- assert_equal "Running tests...\n", buildable.output
26
-
27
- commit = buildable.commit_info
28
- assert_equal "This commit will work", commit[:message]
29
- assert_equal Time.now.min, commit[:committed_at].min
30
- ensure
31
- Bob.engine = old_engine
32
- end
33
- end
34
- end