cijoe 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -49,6 +49,9 @@ put whatever you want in there.
49
49
  Tip: your repo's `HEAD` will point to the commit used to run the
50
50
  build. Pull any metadata you want out of that scro.
51
51
 
52
+ ** WARNING ** Do not run this against a git repo that has unpushed
53
+ commits, as this will do a hard reset against the github remote and
54
+ wipe out unpushed changes.
52
55
 
53
56
  Other Branches
54
57
  ----------------------
@@ -77,8 +80,7 @@ Campfire notification is included, because it's what we use. Want Joe
77
80
  notify your Campfire? Put this in your repo's `.git/config`:
78
81
 
79
82
  [campfire]
80
- user = your@campfire.email
81
- pass = passw0rd
83
+ token = abcd1234
82
84
  subdomain = whatever
83
85
  room = Awesomeness
84
86
  ssl = false
@@ -86,7 +88,7 @@ notify your Campfire? Put this in your repo's `.git/config`:
86
88
  Or do it the old fashion way:
87
89
 
88
90
  $ cd yourrepo
89
- $ git config --add campfire.user chris@ozmm.org
91
+ $ git config --add campfire.token abcd1234
90
92
  $ git config --add campfire.subdomain github
91
93
  etc.
92
94
 
@@ -147,6 +149,7 @@ Other CI Servers
147
149
 
148
150
  Need more features? More notifiers? Check out one of these bad boys:
149
151
 
152
+ * [Jenkins](http://jenkins-ci.org/)
150
153
  * [Cerberus](http://cerberus.rubyforge.org/)
151
154
  * [Integrity](http://integrityapp.com/)
152
155
  * [CruiseControl.rb](http://cruisecontrolrb.thoughtworks.com/)
@@ -154,6 +157,12 @@ Need more features? More notifiers? Check out one of these bad boys:
154
157
  * [Signal](http://www.github.com/dcrec1/signal)
155
158
 
156
159
 
160
+ Does GitHub use cijoe?
161
+ ---------------------------------
162
+
163
+ No. We use [Jenkins](http://jenkins-ci.org/).
164
+
165
+
157
166
  Screenshots
158
167
  ------------------
159
168
 
@@ -165,7 +174,4 @@ Screenshots
165
174
  Questions? Concerns?
166
175
  ---------------------------------
167
176
 
168
- [Issues](http://github.com/defunkt/cijoe/issues) or [the mailing list](http://groups.google.com/group/cijoe).
169
-
170
-
171
- ( Chris Wanstrath :: chris@ozmm.org )
177
+ [Issues](http://github.com/defunkt/cijoe/issues)
@@ -21,7 +21,7 @@ require 'cijoe/campfire'
21
21
  require 'cijoe/server'
22
22
 
23
23
  class CIJoe
24
- attr_reader :user, :project, :url, :current_build, :last_build
24
+ attr_reader :user, :project, :url, :current_build, :last_build, :campfire
25
25
 
26
26
  def initialize(project_path)
27
27
  @project_path = File.expand_path(project_path)
@@ -29,6 +29,8 @@ class CIJoe
29
29
  @user, @project = git_user_and_project
30
30
  @url = "http://github.com/#{@user}/#{@project}"
31
31
 
32
+ @campfire = CIJoe::Campfire.new(project_path)
33
+
32
34
  @last_build = nil
33
35
  @current_build = nil
34
36
 
@@ -77,7 +79,7 @@ class CIJoe
77
79
  @current_build = nil
78
80
  write_build 'current', @current_build
79
81
  write_build 'last', @last_build
80
- @last_build.notify if @last_build.respond_to? :notify
82
+ @campfire.notify(@last_build) if @campfire.valid?
81
83
 
82
84
  # another build waits
83
85
  if !repo_config.buildallfile.to_s.empty? && File.exist?(repo_config.buildallfile.to_s)
@@ -1,30 +1,26 @@
1
1
  class CIJoe
2
- module Campfire
3
- def self.activate(project_path)
2
+ class Campfire
3
+ attr_reader :project_path, :build
4
+
5
+ def initialize(project_path)
4
6
  @project_path = project_path
5
-
6
- if valid_config?
7
+ if valid?
7
8
  require 'tinder'
8
-
9
- CIJoe::Build.class_eval do
10
- include CIJoe::Campfire
11
- end
12
-
13
- puts "Loaded Campfire notifier"
9
+ puts "Loaded Campfire notifier for #{project_path}."
14
10
  elsif ENV['RACK_ENV'] != 'test'
15
- puts "Can't load Campfire notifier."
11
+ puts "Can't load Campfire notifier for #{project_path}."
16
12
  puts "Please add the following to your project's .git/config:"
17
13
  puts "[campfire]"
18
- puts "\ttoken = your_api_token"
14
+ puts "\ttoken = abcd1234"
19
15
  puts "\tsubdomain = whatever"
20
16
  puts "\troom = Awesomeness"
21
17
  puts "\tssl = false"
22
18
  end
23
19
  end
24
-
25
- def self.config
26
- campfire_config = Config.new('campfire', @project_path)
27
- @config ||= {
20
+
21
+ def campfire_config
22
+ campfire_config = Config.new('campfire', project_path)
23
+ @config = {
28
24
  :subdomain => campfire_config.subdomain.to_s,
29
25
  :token => campfire_config.token.to_s,
30
26
  :room => campfire_config.room.to_s,
@@ -32,22 +28,27 @@ class CIJoe
32
28
  }
33
29
  end
34
30
 
35
- def self.valid_config?
31
+ def valid?
36
32
  %w( subdomain token room ).all? do |key|
37
- !config[key.intern].empty?
33
+ !campfire_config[key.intern].empty?
38
34
  end
39
35
  end
40
36
 
41
- def notify
42
- room.speak "#{short_message}. #{commit.url}"
43
- room.paste full_message if failed?
44
- room.leave
37
+ def notify(build)
38
+ begin
39
+ @build = build
40
+ room.speak "#{short_message}. #{build.commit.url}"
41
+ room.paste full_message if build.failed?
42
+ room.leave
43
+ rescue
44
+ puts "Please check your campfire config for #{project_path}."
45
+ end
45
46
  end
46
47
 
47
48
  private
48
49
  def room
49
50
  @room ||= begin
50
- config = Campfire.config
51
+ config = campfire_config
51
52
  campfire = Tinder::Campfire.new(config[:subdomain],
52
53
  :token => config[:token],
53
54
  :ssl => config[:ssl] || false)
@@ -56,17 +57,17 @@ class CIJoe
56
57
  end
57
58
 
58
59
  def short_message
59
- "#{branch} at #{short_sha} of #{project} " +
60
- (worked? ? "passed" : "failed") + " (#{duration.to_i}s)"
60
+ "#{build.branch} at #{build.short_sha} of #{build.project} " +
61
+ (build.worked? ? "passed" : "failed") + " (#{build.duration.to_i}s)"
61
62
  end
62
63
 
63
64
  def full_message
64
65
  <<-EOM
65
- Commit Message: #{commit.message}
66
- Commit Date: #{commit.committed_at}
67
- Commit Author: #{commit.author}
66
+ Commit Message: #{build.commit.message}
67
+ Commit Date: #{build.commit.committed_at}
68
+ Commit Author: #{build.commit.author}
68
69
 
69
- #{clean_output}
70
+ #{build.clean_output}
70
71
  EOM
71
72
  end
72
73
  end
@@ -1,5 +1,6 @@
1
1
  require 'sinatra/base'
2
2
  require 'erb'
3
+ require 'json'
3
4
 
4
5
  class CIJoe
5
6
  class Server < Sinatra::Base
@@ -27,15 +28,15 @@ class CIJoe
27
28
  end
28
29
 
29
30
  post '/?' do
30
- payload = params[:payload].to_s
31
- if payload =~ /"ref":"(.+?)"/
32
- pushed_branch = $1.split('/').last
31
+ unless params[:rebuild]
32
+ payload = JSON.parse(params[:payload])
33
+ pushed_branch = payload["ref"].split('/').last
33
34
  end
34
-
35
- # Only build if we were given an explicit branch via `?branch=blah`,
36
- # no payload exists (we're probably testing), or the payload exists and
37
- # the "ref" property matches our specified build branch.
38
- if params[:branch] || payload.empty? || pushed_branch == joe.git_branch
35
+
36
+ # Only build if we were given an explicit branch via `?branch=blah`
37
+ # or the payload exists and the "ref" property matches our
38
+ # specified build branch.
39
+ if params[:branch] || params[:rebuild] || pushed_branch == joe.git_branch
39
40
  joe.build(params[:branch])
40
41
  end
41
42
 
@@ -79,8 +80,6 @@ class CIJoe
79
80
  super
80
81
  check_project
81
82
  @joe = CIJoe.new(options.project_path)
82
-
83
- CIJoe::Campfire.activate(options.project_path)
84
83
  end
85
84
 
86
85
  def self.start(host, port, project_path)
@@ -1,3 +1,3 @@
1
1
  class CIJoe
2
- Version = VERSION = "0.9.1"
2
+ Version = VERSION = "0.9.2"
3
3
  end
@@ -2,7 +2,15 @@
2
2
  <% if joe.last_build %>
3
3
  {"name":"<%= joe.project %>",
4
4
  "url":"<%= joe.url %>",
5
- "color":"<%= joe.last_build.status.to_s == "failed" ? 'red' : 'blue' %>"
5
+ "color":"<%= joe.last_build.status.to_s == "failed" ? 'red' : 'blue' %>",
6
+ "status":"<%= joe.last_build.status %>",
7
+ "started_at":"<%= pretty_time(joe.last_build.started_at) %>",
8
+ "finished_at":"<%= pretty_time(joe.last_build.finished_at) %>",
9
+ "duration":"<%= joe.last_build.duration if joe.last_build.duration %>",
10
+ "sha":"<%= joe.last_build.sha %>",
11
+ "short_sha":"<%= joe.last_build.short_sha %>",
12
+ "commit_url":"<%= joe.last_build.commit.url if joe.last_build.commit %>",
13
+ "branch":"<%= joe.last_build.branch %>"
6
14
  }
7
15
  <% end %>
8
16
  ]}
@@ -25,7 +25,7 @@
25
25
  <% end %>
26
26
  </li>
27
27
  <% else %>
28
- <li><form method="POST"><input type="submit" value="Build"/></form></li>
28
+ <li><form method="POST"><input type="hidden", name="rebuild" value="true"><input type="submit" value="Build"/></form></li>
29
29
  <% end %>
30
30
 
31
31
  <% if joe.last_build %>
@@ -0,0 +1,52 @@
1
+ {
2
+ "after": "416cb2f7105e7f989bc223d1a975b93a6491b276",
3
+ "before": "0ae4da1eea2d191b33ebfbd5db48e3c1f91953ad",
4
+ "commits": [
5
+ {
6
+ "added": [
7
+
8
+ ],
9
+ "author": {
10
+ "email": "joshua.owens@gmail.com",
11
+ "name": "Josh Owens",
12
+ "username": "queso"
13
+ },
14
+ "id": "09293a1703b3bdb36aba70d38abd5e44396c50a5",
15
+ "message": "Update README",
16
+ "modified": [
17
+ "README.textile"
18
+ ],
19
+ "removed": [
20
+
21
+ ],
22
+ "timestamp": "2011-02-07T15:27:35-08:00",
23
+ "url": "https:\/\/github.com\/fourbeansoup\/broth\/commit\/09293a1703b3bdb36aba70d38abd5e44396c50a5"
24
+ }
25
+ ],
26
+ "compare": "https:\/\/github.com\/fourbeansoup\/broth\/compare\/0ae4da1...416cb2f",
27
+ "forced": false,
28
+ "ref": "refs\/heads\/master",
29
+ "repository": {
30
+ "created_at": "2009\/12\/05 10:44:57 -0800",
31
+ "description": "FourBeanSoup's Broth Application, a tasty starting point for every app",
32
+ "fork": true,
33
+ "forks": 4,
34
+ "has_downloads": true,
35
+ "has_issues": true,
36
+ "has_wiki": true,
37
+ "homepage": "",
38
+ "language": "JavaScript",
39
+ "name": "broth",
40
+ "open_issues": 2,
41
+ "organization": "fourbeansoup",
42
+ "owner": {
43
+ "email": "josh+scm@fourbeansoup.com",
44
+ "name": "fourbeansoup"
45
+ },
46
+ "private": false,
47
+ "pushed_at": "2011\/02\/07 17:17:00 -0800",
48
+ "size": 604,
49
+ "url": "https:\/\/github.com\/fourbeansoup\/broth",
50
+ "watchers": 10
51
+ }
52
+ }
@@ -10,5 +10,37 @@ require 'cijoe'
10
10
  CIJoe::Server.set :project_path, "."
11
11
  CIJoe::Server.set :environment, "test"
12
12
 
13
+ TMP_DIR = '/tmp/cijoe_test'
14
+
15
+ def tmp_dir
16
+ TMP_DIR
17
+ end
18
+
19
+ def setup_git_info(options = {})
20
+ @tmp_dirs ||= []
21
+ @tmp_dirs += [options[:tmp_dir]]
22
+ create_tmpdir!(options[:tmp_dir])
23
+ dir = options[:tmp_dir] || tmp_dir
24
+ `cd #{dir} && git init`
25
+ options[:config].each do |key, value|
26
+ `cd #{dir} && git config --add #{key} "#{value}"`
27
+ end
28
+ end
29
+
30
+ def teardown_git_info
31
+ remove_tmpdir!
32
+ @tmp_dirs.each do |dir|
33
+ remove_tmpdir!(dir)
34
+ end
35
+ end
36
+
37
+ def remove_tmpdir!(passed_dir = nil)
38
+ FileUtils.rm_rf(passed_dir || tmp_dir)
39
+ end
40
+
41
+ def create_tmpdir!(passed_dir = nil)
42
+ FileUtils.mkdir_p(passed_dir || tmp_dir)
43
+ end
44
+
13
45
  class Test::Unit::TestCase
14
46
  end
@@ -0,0 +1,48 @@
1
+ require "helper"
2
+ require "cijoe"
3
+ require "fakefs/safe"
4
+
5
+
6
+ class TestCampfire < Test::Unit::TestCase
7
+
8
+ class ::CIJoe
9
+ attr_writer :current_build, :last_build
10
+ end
11
+
12
+ attr_accessor :app
13
+
14
+ def setup
15
+ @app = CIJoe::Server.new
16
+ joe = @app.joe
17
+
18
+ # make Build#restore a no-op so we don't overwrite our current/last
19
+ # build attributes set from tests.
20
+ def joe.restore
21
+ end
22
+
23
+ # make CIJoe#build! and CIJoe#git_update a no-op so we don't overwrite our local changes
24
+ # or local commits nor should we run tests.
25
+ def joe.build!
26
+ end
27
+ end
28
+
29
+ def teardown
30
+ teardown_git_info
31
+ end
32
+
33
+ def test_campfire_pulls_campfire_config_from_git_config
34
+ setup_git_info(:config => {"campfire.subdomain" => "github", "remote.origin.url" => "https://github.com/defunkt/cijoe.git"})
35
+ cf = CIJoe::Campfire.new(tmp_dir)
36
+ assert_equal "github", cf.campfire_config[:subdomain]
37
+ end
38
+
39
+ def test_campfire_pulls_campfire_config_from_its_own_git_config
40
+ setup_git_info(:config => {"campfire.subdomain" => "github"})
41
+ setup_git_info(:config => {"campfire.subdomain" => "37signals"}, :tmp_dir => "/tmp/cijoe_test_37signals")
42
+ cf1 = CIJoe::Campfire.new(tmp_dir)
43
+ cf2 = CIJoe::Campfire.new("/tmp/cijoe_test_37signals")
44
+ assert_equal "github", cf1.campfire_config[:subdomain]
45
+ assert_equal "37signals", cf2.campfire_config[:subdomain]
46
+ end
47
+
48
+ end
@@ -13,11 +13,17 @@ class TestCIJoeServer < Test::Unit::TestCase
13
13
 
14
14
  def setup
15
15
  @app = CIJoe::Server.new
16
+ joe = @app.joe
17
+
16
18
  # make Build#restore a no-op so we don't overwrite our current/last
17
19
  # build attributes set from tests.
18
- joe = @app.joe
19
20
  def joe.restore
20
21
  end
22
+
23
+ # make CIJoe#build! and CIJoe#git_update a no-op so we don't overwrite our local changes
24
+ # or local commits nor should we run tests.
25
+ def joe.build!
26
+ end
21
27
  end
22
28
 
23
29
  def test_ping
@@ -64,6 +70,30 @@ class TestCIJoeServer < Test::Unit::TestCase
64
70
  assert_equal current_build, app.joe.current_build
65
71
  end
66
72
 
73
+ def test_post_with_json_works
74
+ post '/', :payload => File.read("#{Dir.pwd}/test/fixtures/payload.json")
75
+ assert app.joe.building?
76
+ assert_equal 302, last_response.status
77
+ end
78
+
79
+ def test_post_does_not_build_on_branch_mismatch
80
+ post "/", :payload => {"ref" => "refs/heads/dont_build"}.to_json
81
+ assert !app.joe.building?
82
+ assert_equal 302, last_response.status
83
+ end
84
+
85
+ def test_post_does_build_on_branch_match
86
+ post "/", :payload => {"ref" => "refs/heads/master"}.to_json
87
+ assert app.joe.building?
88
+ assert_equal 302, last_response.status
89
+ end
90
+
91
+ def test_post_does_build_when_build_button_is_used
92
+ post "/", :rebuild => true
93
+ assert app.joe.building?
94
+ assert_equal 302, last_response.status
95
+ end
96
+
67
97
  def test_jsonp_should_return_plain_json_without_param
68
98
  app.joe.last_build = build :failed
69
99
  get "/api/json"
@@ -74,7 +104,6 @@ class TestCIJoeServer < Test::Unit::TestCase
74
104
  def test_jsonp_should_return_jsonp_with_param
75
105
  app.joe.last_build = build :failed
76
106
  get "/api/json?jsonp=fooberz"
77
- puts last_response.inspect
78
107
  assert_equal 200, last_response.status
79
108
  assert_equal 'application/json', last_response.content_type
80
109
  assert_match /^fooberz\(/, last_response.body
metadata CHANGED
@@ -1,21 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cijoe
3
3
  version: !ruby/object:Gem::Version
4
- hash: 57
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 9
9
- - 1
10
- version: 0.9.1
4
+ prerelease:
5
+ version: 0.9.2
11
6
  platform: ruby
12
7
  authors:
13
8
  - Chris Wanstrath
9
+ - Josh Owens
14
10
  autorequire:
15
11
  bindir: bin
16
12
  cert_chain: []
17
13
 
18
- date: 2011-02-08 00:00:00 -08:00
14
+ date: 2011-04-19 00:00:00 -04:00
19
15
  default_executable:
20
16
  dependencies:
21
17
  - !ruby/object:Gem::Dependency
@@ -26,9 +22,6 @@ dependencies:
26
22
  requirements:
27
23
  - - ">="
28
24
  - !ruby/object:Gem::Version
29
- hash: 3
30
- segments:
31
- - 0
32
25
  version: "0"
33
26
  type: :runtime
34
27
  version_requirements: *id001
@@ -40,26 +33,42 @@ dependencies:
40
33
  requirements:
41
34
  - - ">="
42
35
  - !ruby/object:Gem::Version
43
- hash: 3
44
- segments:
45
- - 0
46
36
  version: "0"
47
37
  type: :runtime
48
38
  version_requirements: *id002
49
39
  - !ruby/object:Gem::Dependency
50
- name: rack-test
40
+ name: json
51
41
  prerelease: false
52
42
  requirement: &id003 !ruby/object:Gem::Requirement
53
43
  none: false
54
44
  requirements:
55
45
  - - ">="
56
46
  - !ruby/object:Gem::Version
57
- hash: 3
58
- segments:
59
- - 0
60
47
  version: "0"
61
- type: :development
48
+ type: :runtime
62
49
  version_requirements: *id003
50
+ - !ruby/object:Gem::Dependency
51
+ name: tinder
52
+ prerelease: false
53
+ requirement: &id004 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: 1.4.0
59
+ type: :runtime
60
+ version_requirements: *id004
61
+ - !ruby/object:Gem::Dependency
62
+ name: rack-test
63
+ prerelease: false
64
+ requirement: &id005 !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "0"
70
+ type: :development
71
+ version_requirements: *id005
63
72
  description: " cijoe is a sinatra-based continuous integration server. It's like an\n old rusty pickup truck: it might be smelly and gross, but it gets the\n job done.\n"
64
73
  email: chris@ozmm.org
65
74
  executables:
@@ -85,7 +94,9 @@ files:
85
94
  - lib/cijoe/views/template.erb
86
95
  - lib/cijoe.rb
87
96
  - bin/cijoe
97
+ - test/fixtures/payload.json
88
98
  - test/helper.rb
99
+ - test/test_campfire.rb
89
100
  - test/test_cijoe.rb
90
101
  - test/test_cijoe_server.rb
91
102
  has_rdoc: true
@@ -102,23 +113,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
102
113
  requirements:
103
114
  - - ">="
104
115
  - !ruby/object:Gem::Version
105
- hash: 3
106
- segments:
107
- - 0
108
116
  version: "0"
109
117
  required_rubygems_version: !ruby/object:Gem::Requirement
110
118
  none: false
111
119
  requirements:
112
120
  - - ">="
113
121
  - !ruby/object:Gem::Version
114
- hash: 3
115
- segments:
116
- - 0
117
122
  version: "0"
118
123
  requirements: []
119
124
 
120
125
  rubyforge_project:
121
- rubygems_version: 1.3.7
126
+ rubygems_version: 1.6.2
122
127
  signing_key:
123
128
  specification_version: 3
124
129
  summary: cijoe builds your builds.