bobette 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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
+