cijoe 0.2.0 → 0.3.0
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.markdown +12 -0
- data/Rakefile +1 -0
- data/bin/cijoe +5 -2
- data/examples/build-failed +22 -0
- data/examples/build-worked +22 -0
- data/lib/cijoe/build.rb +14 -1
- data/lib/cijoe/config.rb +9 -8
- data/lib/cijoe/public/screen.css +3 -2
- data/lib/cijoe/server.rb +14 -4
- data/lib/cijoe/version.rb +1 -1
- data/lib/cijoe/views/template.erb +6 -1
- data/lib/cijoe.rb +32 -4
- data/test/helper.rb +3 -0
- data/test/test_cijoe_server.rb +50 -0
- metadata +16 -2
data/README.markdown
CHANGED
@@ -83,6 +83,18 @@ Or do it the old fashion way:
|
|
83
83
|
etc.
|
84
84
|
|
85
85
|
|
86
|
+
Checkin' Status
|
87
|
+
---------------
|
88
|
+
|
89
|
+
Want to see how your build's doing without any of this fancy UI crap?
|
90
|
+
Ping Joe for the lowdown:
|
91
|
+
|
92
|
+
curl http://localhost:4567/ping
|
93
|
+
|
94
|
+
Joe will return `200 OK` if all is quiet on the Western Front. If
|
95
|
+
Joe's busy building or your last build failed, you'll get `412
|
96
|
+
PRECONDITION FAILED`.
|
97
|
+
|
86
98
|
Multiple Projects
|
87
99
|
-----------------
|
88
100
|
|
data/Rakefile
CHANGED
data/bin/cijoe
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
3
3
|
|
4
|
-
require 'cijoe'
|
5
4
|
require 'choice'
|
6
5
|
|
7
6
|
Choice.options do
|
@@ -46,4 +45,8 @@ Choice.options do
|
|
46
45
|
end
|
47
46
|
|
48
47
|
options = Choice.choices
|
49
|
-
|
48
|
+
$project_path = File.expand_path(Choice.rest[0])
|
49
|
+
|
50
|
+
require 'cijoe'
|
51
|
+
|
52
|
+
CIJoe::Server.start(options[:host], options[:port], $project_path)
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
#
|
3
|
+
# Put this file to $PROJECT/.git/hooks/ for email notifications.
|
4
|
+
#
|
5
|
+
# You should have mail command provided by mailutils package on Debian
|
6
|
+
# based systems.
|
7
|
+
#
|
8
|
+
# sudo apt-get install mailutils
|
9
|
+
#
|
10
|
+
# You should have mail server running
|
11
|
+
#
|
12
|
+
# Do not forget: chmod +x build-failed
|
13
|
+
#
|
14
|
+
echo "
|
15
|
+
Visit http://ci.example.org/ for details
|
16
|
+
|
17
|
+
Author: $AUTHOR
|
18
|
+
Message:
|
19
|
+
$MESSAGE
|
20
|
+
|
21
|
+
$OUTPUT
|
22
|
+
" | mail -s "[example.org] BUILD FAILED $SHA" --to first@gmail.com second@gmail.com
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
#
|
3
|
+
# Put this file to $PROJECT/.git/hooks/ for email notifications.
|
4
|
+
#
|
5
|
+
# You should have mail command provided by mailutils package on Debian
|
6
|
+
# based systems.
|
7
|
+
#
|
8
|
+
# sudo apt-get install mailutils
|
9
|
+
#
|
10
|
+
# You should have mail server running
|
11
|
+
#
|
12
|
+
# Do not forget: chmod +x build-worked
|
13
|
+
#
|
14
|
+
echo "
|
15
|
+
Visit http://ci.example.org/ for details
|
16
|
+
|
17
|
+
Author: $AUTHOR
|
18
|
+
Message:
|
19
|
+
$MESSAGE
|
20
|
+
|
21
|
+
" | mail -s "[example.org] build OK" --to first@gmail.com second@gmail.com
|
22
|
+
|
data/lib/cijoe/build.rb
CHANGED
@@ -20,8 +20,21 @@ class CIJoe
|
|
20
20
|
status == :worked
|
21
21
|
end
|
22
22
|
|
23
|
+
def building?
|
24
|
+
status == :building
|
25
|
+
end
|
26
|
+
|
27
|
+
def duration
|
28
|
+
return if building?
|
29
|
+
finished_at - started_at
|
30
|
+
end
|
31
|
+
|
23
32
|
def short_sha
|
24
|
-
|
33
|
+
if sha
|
34
|
+
sha[0,7]
|
35
|
+
else
|
36
|
+
"<unknown>"
|
37
|
+
end
|
25
38
|
end
|
26
39
|
|
27
40
|
def clean_output
|
data/lib/cijoe/config.rb
CHANGED
@@ -5,8 +5,9 @@ class CIJoe
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def initialize(command, parent = nil)
|
8
|
-
@command
|
9
|
-
@parent
|
8
|
+
@command = command
|
9
|
+
@parent = parent
|
10
|
+
@project_path = $project_path || File.join(File.dirname(__FILE__), '../../')
|
10
11
|
end
|
11
12
|
|
12
13
|
def method_missing(command, *args)
|
@@ -14,10 +15,10 @@ class CIJoe
|
|
14
15
|
end
|
15
16
|
|
16
17
|
def to_s
|
17
|
-
git_command = "git config #{config_string}"
|
18
|
+
git_command = "cd #{@project_path} && git config #{config_string}"
|
18
19
|
result = `#{git_command} 2>&1`.chomp
|
19
20
|
process_status = $?
|
20
|
-
|
21
|
+
|
21
22
|
if successful_command?(process_status) || config_command_with_empty_value?(result,process_status)
|
22
23
|
return result
|
23
24
|
else
|
@@ -28,15 +29,15 @@ class CIJoe
|
|
28
29
|
def config_string
|
29
30
|
@parent ? "#{@parent.config_string}.#{@command}" : @command
|
30
31
|
end
|
31
|
-
|
32
|
+
|
32
33
|
private
|
33
|
-
|
34
|
+
|
34
35
|
def successful_command?(process_status)
|
35
36
|
process_status.exitstatus.to_i == 0
|
36
37
|
end
|
37
|
-
|
38
|
+
|
38
39
|
def config_command_with_empty_value?(result, process_status)
|
39
40
|
process_status.exitstatus.to_i == 1 && result.empty?
|
40
|
-
end
|
41
|
+
end
|
41
42
|
end
|
42
43
|
end
|
data/lib/cijoe/public/screen.css
CHANGED
@@ -83,7 +83,8 @@ ul.posts {
|
|
83
83
|
line-height: 1.75em;
|
84
84
|
}
|
85
85
|
|
86
|
-
ul.posts .date
|
86
|
+
ul.posts .date,
|
87
|
+
ul.posts .duration {
|
87
88
|
color: #aaa;
|
88
89
|
font-family: Monaco, "Courier New", monospace;
|
89
90
|
font-size: 80%;
|
@@ -98,7 +99,7 @@ ul.posts {
|
|
98
99
|
.site {
|
99
100
|
font-size: 110%;
|
100
101
|
text-align: justify;
|
101
|
-
width:
|
102
|
+
width: 80%;
|
102
103
|
margin: 3em auto 2em auto;
|
103
104
|
line-height: 1.5em;
|
104
105
|
}
|
data/lib/cijoe/server.rb
CHANGED
@@ -3,6 +3,8 @@ require 'erb'
|
|
3
3
|
|
4
4
|
class CIJoe
|
5
5
|
class Server < Sinatra::Base
|
6
|
+
attr_reader :joe
|
7
|
+
|
6
8
|
dir = File.dirname(File.expand_path(__FILE__))
|
7
9
|
|
8
10
|
set :views, "#{dir}/views"
|
@@ -10,16 +12,24 @@ class CIJoe
|
|
10
12
|
set :static, true
|
11
13
|
set :lock, true
|
12
14
|
|
13
|
-
before {
|
15
|
+
before { joe.restore }
|
16
|
+
|
17
|
+
get '/ping' do
|
18
|
+
if joe.building? || !joe.last_build || !joe.last_build.worked?
|
19
|
+
halt 412, joe.last_build ? joe.last_build.sha : "building"
|
20
|
+
end
|
21
|
+
|
22
|
+
joe.last_build.sha
|
23
|
+
end
|
14
24
|
|
15
25
|
get '/?' do
|
16
|
-
erb(:template, {}, :joe =>
|
26
|
+
erb(:template, {}, :joe => joe)
|
17
27
|
end
|
18
28
|
|
19
29
|
post '/?' do
|
20
30
|
payload = params[:payload].to_s
|
21
|
-
if payload.empty? || payload.include?(
|
22
|
-
|
31
|
+
if payload.empty? || payload.include?(joe.git_branch)
|
32
|
+
joe.build
|
23
33
|
end
|
24
34
|
redirect request.path
|
25
35
|
end
|
data/lib/cijoe/version.rb
CHANGED
@@ -29,7 +29,12 @@
|
|
29
29
|
<% end %>
|
30
30
|
|
31
31
|
<% if joe.last_build %>
|
32
|
-
<li
|
32
|
+
<li>
|
33
|
+
<span class="date"><%= pretty_time(joe.last_build.finished_at) %></span> » Built <a href="<%= joe.url %>/commits/<%= joe.last_build.sha %>"><%= joe.last_build.short_sha %></a> <span class="<%= joe.last_build.status %>">(<%= joe.last_build.status %>)</span>
|
34
|
+
<% if joe.last_build.duration %>
|
35
|
+
in <span class="duration"><%= joe.last_build.duration %></span> seconds.
|
36
|
+
<% end %>
|
37
|
+
</li>
|
33
38
|
<% if joe.last_build.failed? %>
|
34
39
|
<li><pre class="terminal"><code><%=ansi_color_codes h(joe.last_build.output) %></code></pre></li>
|
35
40
|
<% end %>
|
data/lib/cijoe.rb
CHANGED
@@ -68,6 +68,7 @@ class CIJoe
|
|
68
68
|
@current_build.status = status
|
69
69
|
@current_build.output = output
|
70
70
|
@last_build = @current_build
|
71
|
+
|
71
72
|
@current_build = nil
|
72
73
|
write_build 'current', @current_build
|
73
74
|
write_build 'last', @last_build
|
@@ -83,6 +84,20 @@ class CIJoe
|
|
83
84
|
Thread.new { build! }
|
84
85
|
end
|
85
86
|
|
87
|
+
def open_pipe(cmd)
|
88
|
+
read, write = IO.pipe
|
89
|
+
|
90
|
+
pid = fork do
|
91
|
+
read.close
|
92
|
+
$stdout.reopen write
|
93
|
+
exec cmd
|
94
|
+
end
|
95
|
+
|
96
|
+
write.close
|
97
|
+
|
98
|
+
yield read, pid
|
99
|
+
end
|
100
|
+
|
86
101
|
# update git then run the build
|
87
102
|
def build!
|
88
103
|
build = @current_build
|
@@ -91,14 +106,21 @@ class CIJoe
|
|
91
106
|
build.sha = git_sha
|
92
107
|
write_build 'current', build
|
93
108
|
|
94
|
-
|
109
|
+
open_pipe("#{runner_command} 2>&1") do |pipe, pid|
|
110
|
+
puts "#{Time.now.to_i}: Building #{build.short_sha}: pid=#{pid}"
|
111
|
+
|
95
112
|
build.pid = pid
|
96
113
|
write_build 'current', build
|
97
114
|
output = pipe.read
|
98
115
|
end
|
99
116
|
|
100
|
-
|
117
|
+
Process.waitpid(build.pid)
|
118
|
+
status = $?.exitstatus.to_i
|
119
|
+
puts "#{Time.now.to_i}: Built #{build.short_sha}: status=#{status}"
|
120
|
+
|
121
|
+
status == 0 ? build_worked(output) : build_failed('', output)
|
101
122
|
rescue Object => e
|
123
|
+
puts "Exception building: #{e.message} (#{e.class})"
|
102
124
|
build_failed('', e.to_s)
|
103
125
|
end
|
104
126
|
|
@@ -147,8 +169,14 @@ class CIJoe
|
|
147
169
|
|
148
170
|
# restore current / last build state from disk.
|
149
171
|
def restore
|
150
|
-
@last_build
|
151
|
-
|
172
|
+
unless @last_build
|
173
|
+
@last_build = read_build('last')
|
174
|
+
end
|
175
|
+
|
176
|
+
unless @current_build
|
177
|
+
@current_build = read_build('current')
|
178
|
+
end
|
179
|
+
|
152
180
|
Process.kill(0, @current_build.pid) if @current_build && @current_build.pid
|
153
181
|
rescue Errno::ESRCH
|
154
182
|
# build pid isn't running anymore. assume previous
|
data/test/helper.rb
CHANGED
@@ -0,0 +1,50 @@
|
|
1
|
+
require "helper"
|
2
|
+
require "rack/test"
|
3
|
+
require "cijoe/server"
|
4
|
+
|
5
|
+
class TestCIJoeServer < Test::Unit::TestCase
|
6
|
+
include Rack::Test::Methods
|
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
|
+
end
|
17
|
+
|
18
|
+
def test_ping
|
19
|
+
app.joe.last_build = build :worked
|
20
|
+
assert !app.joe.building?, "have a last build, but not a current"
|
21
|
+
|
22
|
+
get "/ping"
|
23
|
+
assert_equal 200, last_response.status
|
24
|
+
assert_equal app.joe.last_build.sha, last_response.body
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_ping_building
|
28
|
+
app.joe.current_build = build :building
|
29
|
+
assert app.joe.building?, "buildin' a awsum project"
|
30
|
+
|
31
|
+
get "/ping"
|
32
|
+
assert_equal 412, last_response.status
|
33
|
+
assert_equal "building", last_response.body
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_ping_failed
|
37
|
+
app.joe.last_build = build :failed
|
38
|
+
|
39
|
+
get "/ping"
|
40
|
+
assert_equal 412, last_response.status
|
41
|
+
assert_equal app.joe.last_build.sha, last_response.body
|
42
|
+
end
|
43
|
+
|
44
|
+
# Create a new, fake build. All we care about is status.
|
45
|
+
|
46
|
+
def build status
|
47
|
+
CIJoe::Build.new "user", "project", Time.now, Time.now,
|
48
|
+
"deadbeef", status, "output", 1337
|
49
|
+
end
|
50
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cijoe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Wanstrath
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2010-02-28 00:00:00 -08:00
|
13
13
|
default_executable: cijoe
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -32,6 +32,16 @@ dependencies:
|
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: "0"
|
34
34
|
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rack-test
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
35
45
|
description: CI Joe is a simple Continuous Integration server.
|
36
46
|
email: chris@ozmm.org
|
37
47
|
executables:
|
@@ -48,6 +58,8 @@ files:
|
|
48
58
|
- Rakefile
|
49
59
|
- bin/cijoe
|
50
60
|
- deps.rip
|
61
|
+
- examples/build-failed
|
62
|
+
- examples/build-worked
|
51
63
|
- examples/cijoe.ru
|
52
64
|
- examples/cijoed
|
53
65
|
- lib/cijoe.rb
|
@@ -63,6 +75,7 @@ files:
|
|
63
75
|
- lib/cijoe/views/template.erb
|
64
76
|
- test/helper.rb
|
65
77
|
- test/test_cijoe.rb
|
78
|
+
- test/test_cijoe_server.rb
|
66
79
|
has_rdoc: true
|
67
80
|
homepage: http://github.com/defunkt/cijoe
|
68
81
|
licenses: []
|
@@ -94,3 +107,4 @@ summary: CI Joe is a simple Continuous Integration server.
|
|
94
107
|
test_files:
|
95
108
|
- test/helper.rb
|
96
109
|
- test/test_cijoe.rb
|
110
|
+
- test/test_cijoe_server.rb
|