bobette 0.0.3

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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2009 Simon Rozet <simon@rozet.name>
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,17 @@
1
+ # Bobette — Bob's sister
2
+
3
+ Bobette is a [Rack][] app that will turn the payload specified
4
+ via the `bobette.payload` Rack env key into a buildable object
5
+ and then builds it using [Bob][].
6
+
7
+ You probably don't care about this, though; check out [Integrity][]
8
+ for a full fledged automated CI server or the test suite if you do.
9
+
10
+ ## Acknowledgement
11
+
12
+ Thanks a lot to [Tim Carey-Smith](http://github.com/halorgium) for
13
+ all his very useful feedbacks.
14
+
15
+ [Rack]: http://rack.rubyforge.org
16
+ [Bob]: http://github.com/integrity/bob
17
+ [Integrity]: http://github.com/integrity/integrity
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "rake/testtask"
2
+
3
+ Rake::TestTask.new(:default) do |t|
4
+ t.test_files = FileList["test/*_test.rb"]
5
+ end
6
+
7
+ begin
8
+ require "mg"
9
+ MG.new("bobette.gemspec")
10
+ rescue LoadError
11
+ end
@@ -0,0 +1,25 @@
1
+ require "integrity"
2
+ require "bobette"
3
+ require "bobette/github"
4
+
5
+ class Integrity::Project
6
+ def self.new(payload)
7
+ # Auto-create!
8
+ first_or_create(:kind => payload["kind"],
9
+ :uri => payload["uri"],
10
+ :branch => payload["master"]
11
+ )
12
+ end
13
+ end
14
+
15
+ map "/github" do
16
+ use Bobette::GitHub
17
+ run Bobette.new(Integrity::Project)
18
+ end
19
+
20
+ Integrity.new(:database_uri => "sqlite3:integrity.db")
21
+ DataMapper.auto_migrate!
22
+
23
+ map "/" do
24
+ run Integrity::App
25
+ end
@@ -0,0 +1,33 @@
1
+ require "json"
2
+
3
+ module Bobette
4
+ class GitHub
5
+ def initialize(app, &block)
6
+ @app = app
7
+ @head = block || Proc.new { false }
8
+ end
9
+
10
+ def call(env)
11
+ payload = Rack::Request.new(env).POST["payload"] || ""
12
+ payload = JSON.parse(payload)
13
+ payload["scm"] = "git"
14
+ payload["uri"] = uri(payload.delete("repository"))
15
+ payload["branch"] = payload.delete("ref").split("/").last
16
+ if (head = payload.delete("after")) && @head.call
17
+ payload["commits"] = [{"id" => head}]
18
+ end
19
+
20
+ @app.call(env.update("bobette.payload" => payload))
21
+ rescue JSON::JSONError
22
+ Rack::Response.new("Unparsable payload", 400).finish
23
+ end
24
+
25
+ def uri(repository)
26
+ if repository["private"]
27
+ "git@github.com:#{URI(repository["url"]).path[1..-1]}"
28
+ else
29
+ URI(repository["url"]).tap { |u| u.scheme = "git" }.to_s
30
+ end
31
+ end
32
+ end
33
+ end
data/lib/bobette.rb ADDED
@@ -0,0 +1,28 @@
1
+ require "bob"
2
+
3
+ module Bobette
4
+ def self.new(buildable)
5
+ App.new(buildable)
6
+ end
7
+
8
+ class App
9
+ attr_reader :buildable
10
+
11
+ def initialize(buildable)
12
+ @buildable = buildable
13
+ end
14
+
15
+ def call(env)
16
+ payload = env["bobette.payload"]
17
+ commits = payload["commits"].collect { |c| c["id"] }
18
+ buildable = @buildable.call(payload)
19
+
20
+ if buildable.respond_to?(:build)
21
+ buildable.build(commits)
22
+ [200, {"Content-Type" => "text/plain"}, ["OK"]]
23
+ else
24
+ [412, {"Content-Type" => "text/plain"}, ["Precondition Failed"]]
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,68 @@
1
+ require File.dirname(__FILE__) + "/helper"
2
+
3
+ require "bobette/github"
4
+
5
+ class BobetteGitHubTest < Bobette::TestCase
6
+ def app
7
+ Rack::Builder.new {
8
+ use Bobette::GitHub do
9
+ $head
10
+ end
11
+ use Rack::Lint
12
+ run lambda { |env|
13
+ Rack::Response.new(env["bobette.payload"].to_json, 200).finish
14
+ }
15
+ }
16
+ end
17
+
18
+ def setup
19
+ $head = false
20
+ end
21
+
22
+ def payload(repo, commits=[], is_private=false, branch="master")
23
+ { "ref" => "refs/heads/#{branch}",
24
+ "after" => commits.last["id"],
25
+ "commits" => commits,
26
+ "repository" => {"url" => "http://github.com/#{repo}",
27
+ "private" => is_private } }
28
+ end
29
+
30
+ def test_transform_payload
31
+ commits = %w(b926de8 737bf26 8ba250e 78bb2de).map { |c| {"id" => c} }
32
+
33
+ post("/", :payload =>
34
+ payload("integrity/bob", commits).to_json) { |response|
35
+
36
+ assert response.ok?
37
+ assert_equal(
38
+ { "uri" => "git://github.com/integrity/bob",
39
+ "scm" => "git",
40
+ "branch" => "master",
41
+ "commits" => commits }, JSON.parse(response.body))
42
+ }
43
+
44
+ post("/", :payload =>
45
+ payload("integrity/bob", commits, true).to_json) { |response|
46
+
47
+ assert response.ok?
48
+ assert_equal "git@github.com:integrity/bob", JSON.parse(response.body)["uri"]
49
+ }
50
+ end
51
+
52
+ def test_head_commit
53
+ $head = true
54
+ commits = %w(b926de8 737bf26 8ba250e 78bb2de).map { |c| {"id" => c} }
55
+
56
+ post("/", :payload =>
57
+ payload("integrity/bob", commits).to_json) { |response|
58
+
59
+ assert response.ok?
60
+ assert_equal [commits.last], JSON.parse(response.body)["commits"]
61
+ }
62
+ end
63
+
64
+ def test_invalid_payload
65
+ assert post("/").client_error?
66
+ assert post("/", {}, "bobette.payload" => "</3").client_error?
67
+ end
68
+ end
@@ -0,0 +1,74 @@
1
+ require File.dirname(__FILE__) + "/helper"
2
+
3
+ class BobetteTest < Bobette::TestCase
4
+ def app
5
+ @app ||= Rack::Builder.new {
6
+ use Rack::Lint
7
+ run Bobette.new(BuildableStub)
8
+ }
9
+ end
10
+
11
+ def payload(repo, branch="master")
12
+ { "branch" => branch,
13
+ "commits" => repo.commits.map { |c| {"id" => c[:identifier]} },
14
+ "uri" => repo.path,
15
+ "scm" => "git" }
16
+ end
17
+
18
+ def setup
19
+ Bob.logger = Logger.new("/dev/null")
20
+ Bob.directory = "/tmp/bobette-builds"
21
+
22
+ BuildableStub.no_buildable = false
23
+
24
+ @repo = GitRepo.new(:my_test_project)
25
+ @repo.create
26
+ 3.times { |i|
27
+ i.odd? ? @repo.add_successful_commit : @repo.add_failing_commit
28
+ }
29
+
30
+ @metadata = {}
31
+ @builds = {}
32
+
33
+ Beacon.watch(:start) { |commit_id, commit_info|
34
+ @metadata[commit_id] = commit_info
35
+ }
36
+
37
+ Beacon.watch(:finish) { |commit_id, status, output|
38
+ @builds[commit_id] = [status ? :successful : :failed, output]
39
+ }
40
+ end
41
+
42
+ def teardown
43
+ FileUtils.rm_rf(Bob.directory)
44
+ end
45
+
46
+ def test_valid_payload
47
+ assert post("/", {}, "bobette.payload" => payload(@repo)).ok?
48
+
49
+ assert_equal 4, @metadata.count
50
+ assert_equal 4, @builds.count
51
+
52
+ commit = @repo.head
53
+
54
+ assert_equal :failed, @builds[commit].first
55
+ assert_equal "Running tests...\n", @builds[commit].last
56
+ assert_equal "This commit will fail", @metadata[commit][:message]
57
+ end
58
+
59
+ def test_invalid_payload
60
+ # TODO
61
+ assert_raise(NoMethodError) { assert post("/") }
62
+ assert_raise(NoMethodError) { post("/", {}, "bobette.payload" => "</3") }
63
+ end
64
+
65
+ def test_no_buildable
66
+ BuildableStub.no_buildable = true
67
+
68
+ payload = payload(@repo).update("branch" => "unknown")
69
+
70
+ post("/", {}, "bobette.payload" => payload) { |response|
71
+ assert_equal 412, response.status
72
+ }
73
+ end
74
+ end
@@ -0,0 +1,26 @@
1
+ module Bobette::TestHelper
2
+ class BuildableStub < Bob::Test::BuildableStub
3
+ class << self
4
+ attr_accessor :no_buildable
5
+ end
6
+
7
+ def self.call(payload)
8
+ return nil if no_buildable
9
+
10
+ scm = payload["scm"]
11
+ uri = payload["uri"]
12
+ branch = payload["branch"]
13
+ build_script = "./test"
14
+
15
+ new(scm, uri, branch, build_script)
16
+ end
17
+
18
+ def start_building(commit_id, commit_info)
19
+ Beacon.fire(:start, commit_id, commit_info)
20
+ end
21
+
22
+ def finish_building(commit_id, status, output)
23
+ Beacon.fire(:finish, commit_id, status, output)
24
+ end
25
+ end
26
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,30 @@
1
+ require "test/unit"
2
+ require "rack/test"
3
+ require "beacon"
4
+ require "bob/test"
5
+
6
+ begin
7
+ require "ruby-debug"
8
+ require "redgreen"
9
+ rescue LoadError
10
+ end
11
+
12
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + "/../lib"),
13
+ File.expand_path(File.dirname(__FILE__))
14
+
15
+ require "bobette"
16
+
17
+ class Test::Unit::TestSuite
18
+ def empty?
19
+ false
20
+ end
21
+ end
22
+
23
+ require "helper/buildable_stub"
24
+
25
+ class Bobette::TestCase < Test::Unit::TestCase
26
+ include Rack::Test::Methods
27
+ include Bob::Test
28
+ include Bobette::TestHelper
29
+ end
30
+
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bobette
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - "Nicol\xC3\xA1s Sanguinetti"
8
+ - Simon Rozet
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-07-02 00:00:00 +02:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: bob
18
+ type: :runtime
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ version:
26
+ - !ruby/object:Gem::Dependency
27
+ name: rack
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:
36
+ - !ruby/object:Gem::Dependency
37
+ name: rack-test
38
+ type: :development
39
+ version_requirement:
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: "0"
45
+ version:
46
+ - !ruby/object:Gem::Dependency
47
+ name: json
48
+ type: :development
49
+ version_requirement:
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ - !ruby/object:Gem::Dependency
57
+ name: beacon
58
+ type: :development
59
+ version_requirement:
60
+ version_requirements: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ - !ruby/object:Gem::Dependency
67
+ name: bob-test
68
+ type: :development
69
+ version_requirement:
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ version:
76
+ description: Bob's sister
77
+ email: info@integrityapp.com
78
+ executables: []
79
+
80
+ extensions: []
81
+
82
+ extra_rdoc_files: []
83
+
84
+ files:
85
+ - LICENSE
86
+ - README.md
87
+ - Rakefile
88
+ - examples/integrity.ru
89
+ - lib/bobette.rb
90
+ - lib/bobette/github.rb
91
+ - test/bobette_github_test.rb
92
+ - test/bobette_test.rb
93
+ - test/helper.rb
94
+ - test/helper/buildable_stub.rb
95
+ has_rdoc: true
96
+ homepage: http://integrityapp.com
97
+ licenses: []
98
+
99
+ post_install_message:
100
+ rdoc_options: []
101
+
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: "0"
109
+ version:
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: "0"
115
+ version:
116
+ requirements: []
117
+
118
+ rubyforge_project: integrity
119
+ rubygems_version: 1.3.3
120
+ signing_key:
121
+ specification_version: 3
122
+ summary: Bob's sister
123
+ test_files: []
124
+