ciquantum 0.0.16 → 0.0.17
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/ciquantum +1 -0
- data/lib/ciquantum.rb +1 -0
- data/lib/ciquantum/build.rb +4 -4
- data/lib/ciquantum/commit.rb +6 -3
- data/lib/ciquantum/config.rb +4 -0
- data/lib/ciquantum/core.rb +39 -55
- data/lib/ciquantum/git.rb +64 -0
- data/lib/ciquantum/server.rb +13 -4
- data/lib/ciquantum/unfuddle.rb +13 -9
- data/lib/ciquantum/unfuddle/changeset.rb +1 -1
- data/lib/ciquantum/version.rb +1 -1
- data/lib/ciquantum/views/build.erb +1 -1
- data/lib/ciquantum/views/json.erb +2 -2
- data/lib/ciquantum/views/mailer/html.erb +1 -1
- data/lib/ciquantum/views/template.erb +18 -13
- metadata +3 -2
data/bin/ciquantum
CHANGED
data/lib/ciquantum.rb
CHANGED
data/lib/ciquantum/build.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
|
3
3
|
module CIQuantum
|
4
|
-
class Build < Struct.new(:project_path, :
|
4
|
+
class Build < Struct.new(:project_path, :started_at, :finished_at, :sha, :status, :output, :pid, :branch)
|
5
5
|
def initialize(*args)
|
6
6
|
super
|
7
7
|
self.started_at ||= Time.now
|
@@ -30,7 +30,7 @@ module CIQuantum
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def id
|
33
|
-
|
33
|
+
finished_at.to_i.to_s
|
34
34
|
end
|
35
35
|
|
36
36
|
def short_sha
|
@@ -52,7 +52,7 @@ module CIQuantum
|
|
52
52
|
|
53
53
|
def commit
|
54
54
|
return if sha.nil?
|
55
|
-
@commit ||= Commit.new(sha,
|
55
|
+
@commit ||= Commit.new(sha, project_path)
|
56
56
|
end
|
57
57
|
|
58
58
|
def test_results
|
@@ -68,7 +68,7 @@ module CIQuantum
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def dump file
|
71
|
-
config = [
|
71
|
+
config = [started_at, finished_at, sha, status, output, pid, branch]
|
72
72
|
data = YAML.dump(config)
|
73
73
|
File.open(file, 'wb') { |io| io.write(data) }
|
74
74
|
end
|
data/lib/ciquantum/commit.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
module CIQuantum
|
2
|
-
class Commit < Struct.new(:sha, :
|
3
|
-
|
4
|
-
|
2
|
+
class Commit < Struct.new(:sha, :project_path)
|
3
|
+
|
4
|
+
attr_reader :url
|
5
|
+
|
6
|
+
def get_url! adapter
|
7
|
+
@url = adapter.commit_url self
|
5
8
|
end
|
6
9
|
|
7
10
|
def author
|
data/lib/ciquantum/config.rb
CHANGED
data/lib/ciquantum/core.rb
CHANGED
@@ -2,24 +2,26 @@ require 'fileutils'
|
|
2
2
|
|
3
3
|
module CIQuantum
|
4
4
|
class Core
|
5
|
-
attr_reader :
|
6
|
-
attr_reader :project
|
5
|
+
attr_reader :adapter
|
7
6
|
attr_reader :url
|
8
7
|
attr_reader :current_build
|
9
8
|
attr_reader :last_build
|
10
9
|
attr_reader :projectname
|
11
10
|
attr_reader :coverage_path
|
11
|
+
attr_reader :git
|
12
|
+
attr_reader :is_building
|
12
13
|
attr_accessor :shared_path
|
13
14
|
|
14
|
-
HistoryLimit =
|
15
|
+
HistoryLimit = 20
|
15
16
|
|
16
17
|
def initialize(project_path)
|
18
|
+
@is_building = false
|
17
19
|
@project_path = File.expand_path(project_path)
|
20
|
+
@adapter = Unfuddle.from_config(repo_config)
|
18
21
|
|
19
|
-
@user, @project = git_user_and_project
|
20
|
-
@url = project_url
|
21
22
|
@projectname = repo_config.projectname.to_s
|
22
23
|
@coverage_path = repo_config.coveragepath.to_s
|
24
|
+
@git = Git.new(@project_path)
|
23
25
|
|
24
26
|
@last_build = nil
|
25
27
|
@current_build = nil
|
@@ -28,23 +30,26 @@ module CIQuantum
|
|
28
30
|
trap("INT") { stop }
|
29
31
|
end
|
30
32
|
|
31
|
-
# is a build running?
|
32
33
|
def building?
|
33
34
|
!!@current_build
|
34
35
|
end
|
35
36
|
|
36
|
-
# the pid of the running child process
|
37
37
|
def pid
|
38
38
|
building? and current_build.pid
|
39
39
|
end
|
40
40
|
|
41
|
-
# kill the child and exit
|
42
41
|
def stop
|
43
|
-
|
42
|
+
stop_build
|
44
43
|
exit!
|
45
44
|
end
|
46
45
|
|
47
|
-
|
46
|
+
def stop_build
|
47
|
+
@is_building = false
|
48
|
+
Process.kill(9, @current_build.pid) if @current_build && @current_build.pid
|
49
|
+
write_build 'current', nil
|
50
|
+
@current_build = nil
|
51
|
+
end
|
52
|
+
|
48
53
|
def build_failed(output, error)
|
49
54
|
finish_build :failed, "#{error}\n\n#{output}"
|
50
55
|
run_hook "build-failed"
|
@@ -66,23 +71,28 @@ module CIQuantum
|
|
66
71
|
write_last_build
|
67
72
|
run_hook "postbuild"
|
68
73
|
save_coverage_for_build @last_build
|
74
|
+
@is_building = false
|
69
75
|
|
70
76
|
build(@queue.next_branch_to_build) if @queue.waiting?
|
71
77
|
end
|
72
78
|
|
73
79
|
def build(branch=nil)
|
80
|
+
branch ||= tracked_branch
|
81
|
+
puts "Preparing branch build with param:#{branch}"
|
74
82
|
if building?
|
75
83
|
@queue.append_unless_already_exists(branch)
|
76
|
-
# leave anyway because a current build runs
|
77
84
|
return
|
78
85
|
end
|
79
|
-
|
86
|
+
|
87
|
+
@is_building = true
|
88
|
+
@current_build = Build.new(@project_path)
|
80
89
|
write_current_build
|
81
90
|
|
82
91
|
Thread.new {
|
83
92
|
build!(branch)
|
84
93
|
}
|
85
94
|
|
95
|
+
@current_build = read_current_build
|
86
96
|
end
|
87
97
|
|
88
98
|
def open_pipe(cmd)
|
@@ -99,14 +109,13 @@ module CIQuantum
|
|
99
109
|
yield read, pid
|
100
110
|
end
|
101
111
|
|
102
|
-
|
103
|
-
def build!(branch=nil)
|
104
|
-
@git_branch = branch
|
112
|
+
def build!(branch)
|
105
113
|
build = @current_build
|
106
|
-
|
114
|
+
update_tracked_branch branch
|
115
|
+
@current_build = read_current_build
|
107
116
|
output = ''
|
108
|
-
build.sha =
|
109
|
-
build.branch =
|
117
|
+
build.sha = @git.sha
|
118
|
+
build.branch = @git.branch
|
110
119
|
write_build 'current', build
|
111
120
|
run_hook "prebuild"
|
112
121
|
|
@@ -135,26 +144,13 @@ module CIQuantum
|
|
135
144
|
runner == '' ? "rake -s --color test:units" : runner
|
136
145
|
end
|
137
146
|
|
138
|
-
def git_update
|
139
|
-
`cd #{@project_path} && git fetch origin && git reset --hard origin/#{git_branch} && git submodule update --init`
|
140
|
-
run_hook "after-reset"
|
141
|
-
end
|
142
|
-
|
143
|
-
def git_user_and_project
|
144
|
-
config = repo_config.send Unfuddle.name
|
145
|
-
Unfuddle.git_user_and_project config
|
146
|
-
end
|
147
|
-
|
148
|
-
def project_url
|
149
|
-
Unfuddle.project_url @user, @project
|
150
|
-
end
|
151
|
-
|
152
147
|
# massage our repo
|
153
148
|
def run_hook(hook)
|
154
149
|
file = path_in_project(".git/hooks/#{hook}")
|
155
150
|
if File.exists?(file) && File.executable?(file)
|
156
151
|
data =
|
157
152
|
if @last_build && @last_build.commit
|
153
|
+
@last_build.commit.get_url! @adapter
|
158
154
|
{
|
159
155
|
"MESSAGE" => @last_build.commit.message,
|
160
156
|
"AUTHOR" => @last_build.commit.author,
|
@@ -178,7 +174,6 @@ module CIQuantum
|
|
178
174
|
end
|
179
175
|
end
|
180
176
|
|
181
|
-
# restore current / last build state from disk.
|
182
177
|
def restore
|
183
178
|
@last_build = read_last_build
|
184
179
|
@current_build = read_current_build
|
@@ -217,27 +212,16 @@ module CIQuantum
|
|
217
212
|
Config.ciquantum(@project_path)
|
218
213
|
end
|
219
214
|
|
220
|
-
def
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
branches = `cd #{@project_path} && git branch -r`.split("\n")
|
226
|
-
branches.collect{|s| s =~ /(?:\s|^)origin\/(?!HEAD)(\w+)(?:\s|$)/ ? $1.strip : nil}.compact
|
215
|
+
def update_tracked_branch branch
|
216
|
+
new_branch = branch.strip
|
217
|
+
repo_config.branch.set new_branch
|
218
|
+
@tracked_branch = new_branch
|
219
|
+
@git.checkout new_branch
|
227
220
|
end
|
228
221
|
|
229
|
-
def
|
230
|
-
return @git_branch if @git_branch
|
222
|
+
def tracked_branch
|
231
223
|
branch = repo_config.branch.to_s
|
232
|
-
@
|
233
|
-
end
|
234
|
-
|
235
|
-
def is_current_git_branch? branch
|
236
|
-
return branch.eql? git_branch
|
237
|
-
end
|
238
|
-
|
239
|
-
def git_sha
|
240
|
-
`cd #{@project_path} && git rev-parse origin/#{git_branch}`.chomp
|
224
|
+
@tracked_branch ||= (branch.empty? ? "master" : branch.strip)
|
241
225
|
end
|
242
226
|
|
243
227
|
def read_build(name)
|
@@ -261,8 +245,8 @@ module CIQuantum
|
|
261
245
|
old_builds.each do |build_file|
|
262
246
|
build = read_build(build_file)
|
263
247
|
active_builds << build
|
264
|
-
if build.status == :worked
|
265
|
-
|
248
|
+
if build.status == :worked || active_builds.size >= HistoryLimit
|
249
|
+
remove_elder_builds build
|
266
250
|
break
|
267
251
|
end
|
268
252
|
end
|
@@ -287,7 +271,7 @@ module CIQuantum
|
|
287
271
|
|
288
272
|
def write_build(name, build)
|
289
273
|
filename = path_in_project(".git/builds/#{name}")
|
290
|
-
|
274
|
+
FileUtils.mkdir_p path_in_project('.git/builds')
|
291
275
|
if build
|
292
276
|
build.dump filename
|
293
277
|
elsif File.exist?(filename)
|
@@ -295,7 +279,7 @@ module CIQuantum
|
|
295
279
|
end
|
296
280
|
end
|
297
281
|
|
298
|
-
def
|
282
|
+
def remove_elder_builds limit_build
|
299
283
|
old_builds.each do |build_file|
|
300
284
|
build = read_build(build_file)
|
301
285
|
if build.finished_at < limit_build.finished_at
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module CIQuantum
|
2
|
+
class Git < Struct.new(:path)
|
3
|
+
|
4
|
+
def exec command
|
5
|
+
puts "Executing git command: #{command}"
|
6
|
+
res = `#{command}`
|
7
|
+
puts "Result for git command:\n#{res}"
|
8
|
+
res
|
9
|
+
end
|
10
|
+
|
11
|
+
def sha
|
12
|
+
exec("cd #{path} && git rev-parse origin/#{branch}").chomp
|
13
|
+
end
|
14
|
+
|
15
|
+
def update
|
16
|
+
fetch
|
17
|
+
exec("cd #{path} && git reset --hard origin/#{branch} && git submodule update --init")
|
18
|
+
end
|
19
|
+
|
20
|
+
def branches
|
21
|
+
branches_to_list `cd #{path} && git branch -r`
|
22
|
+
end
|
23
|
+
|
24
|
+
def fetch
|
25
|
+
exec("cd #{path} && git fetch origin")
|
26
|
+
end
|
27
|
+
|
28
|
+
def branch
|
29
|
+
if !@branch && exec("cd #{path} && git branch 2>/dev/null | grep -e '\*' ") =~ /^\*\s(\w+)/
|
30
|
+
@branch = $1.strip
|
31
|
+
end
|
32
|
+
@branch
|
33
|
+
end
|
34
|
+
|
35
|
+
def is_current_branch? other_branch
|
36
|
+
return branch.eql? other_branch
|
37
|
+
end
|
38
|
+
|
39
|
+
def checkout other_branch
|
40
|
+
unless is_current_branch?(other_branch)
|
41
|
+
fetch
|
42
|
+
exec("cd #{path} && git checkout #{other_branch}") if branches.include?(other_branch)
|
43
|
+
@branch = nil
|
44
|
+
end
|
45
|
+
update
|
46
|
+
end
|
47
|
+
|
48
|
+
def branches_with_commit commit_sha
|
49
|
+
fetch
|
50
|
+
branches_to_list exec("cd #{path} && git branch -r --contains #{commit_sha}")
|
51
|
+
end
|
52
|
+
|
53
|
+
def current_branch_contains_commit? commit_sha
|
54
|
+
branches_with_commit(commit_sha).include?(branch)
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
def branches_to_list branch_output
|
59
|
+
raw_branches = branch_output.split("\n")
|
60
|
+
raw_branches.collect{|s| s =~ /^\s*(?:origin\/)?(\w+)\s*$/ ? $1.strip : nil}.compact.uniq
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
data/lib/ciquantum/server.rb
CHANGED
@@ -53,13 +53,20 @@ module CIQuantum
|
|
53
53
|
end
|
54
54
|
|
55
55
|
post '/build' do
|
56
|
-
|
56
|
+
puts "Building!"
|
57
|
+
quantum.build
|
57
58
|
redirect '/'
|
58
59
|
end
|
59
60
|
|
60
61
|
post '/switch_branch' do
|
61
|
-
|
62
|
-
quantum.build params[:branch]
|
62
|
+
puts "Switching branch! params: #{params.inspect}"
|
63
|
+
quantum.build params[:branch].strip
|
64
|
+
redirect '/'
|
65
|
+
end
|
66
|
+
|
67
|
+
post '/cancel_build' do
|
68
|
+
puts "Stop build!"
|
69
|
+
quantum.stop_build
|
63
70
|
redirect '/'
|
64
71
|
end
|
65
72
|
|
@@ -78,7 +85,9 @@ module CIQuantum
|
|
78
85
|
begin
|
79
86
|
xml = request.body.read
|
80
87
|
changeset = Unfuddle::Changeset.new(xml)
|
81
|
-
quantum.
|
88
|
+
if quantum.git.current_branch_contains_commit? changeset.commit
|
89
|
+
quantum.build
|
90
|
+
end
|
82
91
|
rescue Unfuddle::ChangesetError => e
|
83
92
|
logger.error "[error] Changeset error: #{e.inspect}, Content: #{xml.inspect}"
|
84
93
|
halt 400, "Changeset Error: #{e.message}"
|
data/lib/ciquantum/unfuddle.rb
CHANGED
@@ -1,20 +1,24 @@
|
|
1
1
|
module CIQuantum
|
2
|
-
|
2
|
+
class Unfuddle < Struct.new(:config)
|
3
3
|
|
4
|
-
def self.
|
5
|
-
|
4
|
+
def self.config_name
|
5
|
+
'unfuddle'
|
6
6
|
end
|
7
7
|
|
8
|
-
def self.
|
9
|
-
|
8
|
+
def self.from_config config
|
9
|
+
self.new config[config_name]
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
|
12
|
+
def commit_url commit
|
13
|
+
"http://#{config.user}.unfuddle.com/a#/repositories/#{config.project}/commit?commit=#{commit.sha}"
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
17
|
-
"https://#{user}.unfuddle.com/a#/repositories/#{project}/browse"
|
16
|
+
def url
|
17
|
+
"https://#{config.user}.unfuddle.com/a#/repositories/#{config.project}/browse"
|
18
|
+
end
|
19
|
+
|
20
|
+
def [] command
|
21
|
+
return @config[command]
|
18
22
|
end
|
19
23
|
|
20
24
|
end
|
data/lib/ciquantum/version.rb
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
<% end %>
|
13
13
|
<div class="results">
|
14
14
|
<h4 class="result">Test results: <%= build.test_results %></h4>
|
15
|
-
<a href="<%= quantum.coverage_for_build(build) %>">Show coverage</a> |
|
15
|
+
<a href="<%= quantum.coverage_for_build(build) %>">Show coverage</a> |
|
16
16
|
<a href="#" onclick="toggleVisibility('<%= build.id %>')">Show output</a>
|
17
17
|
<div id="<%= build.id %>" style="display:none">
|
18
18
|
<pre class="terminal"><code><%= ansi_color_codes h(build.output) %></code></pre>
|
@@ -3,7 +3,7 @@
|
|
3
3
|
<% if quantum.last_build %>
|
4
4
|
{
|
5
5
|
"name":"<%= quantum.projectname || quantum.project %>",
|
6
|
-
"url":"<%= quantum.url %>",
|
6
|
+
"url":"<%= quantum.adapter.url %>",
|
7
7
|
"color":"<%= quantum.last_build.status.to_s == "failed" ? 'red' : 'blue' %>",
|
8
8
|
"status":"<%= quantum.last_build.status %>",
|
9
9
|
"started_at":"<%= pretty_time(quantum.last_build.started_at) %>",
|
@@ -11,7 +11,7 @@
|
|
11
11
|
"duration":"<%= quantum.last_build.duration if quantum.last_build.duration %>",
|
12
12
|
"sha":"<%= quantum.last_build.sha %>",
|
13
13
|
"short_sha":"<%= quantum.last_build.short_sha %>",
|
14
|
-
"commit_url":"<%= quantum.last_build.commit
|
14
|
+
"commit_url":"<%= quantum.adapter_commit_url(quantum.last_build.commit) if quantum.last_build.commit %>",
|
15
15
|
"branch":"<%= quantum.last_build.branch %>"
|
16
16
|
}
|
17
17
|
<% end %>
|
@@ -15,28 +15,32 @@
|
|
15
15
|
<div id="home">
|
16
16
|
<h1><a href="<%= quantum.url %>"><%= quantum.projectname %></a></h1>
|
17
17
|
<ul class="posts">
|
18
|
-
<% if quantum.
|
18
|
+
<% if quantum.is_building %>
|
19
19
|
<li>
|
20
|
-
<span class="date"><%= pretty_time(quantum.current_build
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
20
|
+
<span class="date"><%= pretty_time(quantum.current_build ? quantum.current_build.started_at : Time.now) %></span> »
|
21
|
+
Current branch: <%= quantum.git.branch %>.
|
22
|
+
<% if quantum.current_build %>
|
23
|
+
Building <%= quantum.current_build.branch %> at <a href="<%= quantum.current_build.commit.url %>"><%= quantum.current_build.short_sha %></a> <small>(pid: <%= quantum.pid %>)</small>
|
24
|
+
<% else %>
|
25
|
+
Build starting...
|
26
|
+
<% end %>
|
27
|
+
<form method="POST" action="/cancel_build">
|
28
|
+
<input type="submit" name="cancel" value="Cancel"/>
|
29
|
+
</form>
|
26
30
|
</li>
|
27
31
|
<% else %>
|
28
32
|
<li>
|
29
33
|
<form method="POST" action="/build">
|
30
|
-
<span class="branch">Current branch: <%= quantum.
|
31
|
-
<input type="submit" name="
|
34
|
+
<span class="branch">Current branch: <%= quantum.git.branch %></span>
|
35
|
+
<input type="submit" name="build" value="Build"/>
|
32
36
|
</form>
|
33
37
|
</li>
|
34
38
|
<li>
|
35
39
|
<% if can_change_branch %>
|
36
40
|
<form method="POST" action="/switch_branch">
|
37
41
|
<select name="branch">
|
38
|
-
<% for @branch in quantum.
|
39
|
-
<option value="<%= @branch %>" <%= 'selected="selected"' if quantum.
|
42
|
+
<% for @branch in quantum.git.branches %>
|
43
|
+
<option value="<%= @branch %>" <%= 'selected="selected"' if quantum.git.is_current_branch?(@branch.strip) %>>"<%= @branch %>"</option>
|
40
44
|
<% end %>
|
41
45
|
</select>
|
42
46
|
<input type="submit" name="switch" value="Switch branch and build"/>
|
@@ -45,8 +49,9 @@
|
|
45
49
|
</li>
|
46
50
|
<% end %>
|
47
51
|
|
48
|
-
<%
|
49
|
-
|
52
|
+
<% builds = quantum.active_builds %>
|
53
|
+
<% if ! builds.empty?%>
|
54
|
+
<% for @build in builds %>
|
50
55
|
<ul><%= erb(:build, {}, :quantum => quantum, :build => @build) %></ul>
|
51
56
|
<% end %>
|
52
57
|
<% end %>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ciquantum
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.17
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2012-06-
|
14
|
+
date: 2012-06-22 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -197,6 +197,7 @@ files:
|
|
197
197
|
- lib/ciquantum/commit.rb
|
198
198
|
- lib/ciquantum/config.rb
|
199
199
|
- lib/ciquantum/core.rb
|
200
|
+
- lib/ciquantum/git.rb
|
200
201
|
- lib/ciquantum/public/javascript.js
|
201
202
|
- lib/ciquantum/public/screen.css
|
202
203
|
- lib/ciquantum/queue.rb
|