ciquantum 0.0.16 → 0.0.17

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.
@@ -43,6 +43,7 @@ Choice.options do
43
43
  exit
44
44
  end
45
45
  end
46
+
46
47
  end
47
48
 
48
49
  options = Choice.choices
@@ -5,6 +5,7 @@ require 'ciquantum/unfuddle'
5
5
  require 'ciquantum/unfuddle/changeset'
6
6
  require 'ciquantum/utils/mailer'
7
7
  require 'ciquantum/utils/coverage_merger'
8
+ require 'ciquantum/git'
8
9
  require 'ciquantum/commit'
9
10
  require 'ciquantum/build'
10
11
  require 'ciquantum/server'
@@ -1,7 +1,7 @@
1
1
  require 'yaml'
2
2
 
3
3
  module CIQuantum
4
- class Build < Struct.new(:project_path, :user, :project, :started_at, :finished_at, :sha, :status, :output, :pid, :branch)
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
- "#{sha}-#{finished_at.to_i}"
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, user, project, project_path)
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 = [user, project, started_at, finished_at, sha, status, output, pid, branch]
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
@@ -1,7 +1,10 @@
1
1
  module CIQuantum
2
- class Commit < Struct.new(:sha, :user, :project, :project_path)
3
- def url
4
- Unfuddle.commit_url self
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
@@ -11,6 +11,10 @@ module CIQuantum
11
11
  end
12
12
 
13
13
  def method_missing(command, *args)
14
+ self[command]
15
+ end
16
+
17
+ def [](command)
14
18
  Config.new(command, @project_path, self)
15
19
  end
16
20
 
@@ -2,24 +2,26 @@ require 'fileutils'
2
2
 
3
3
  module CIQuantum
4
4
  class Core
5
- attr_reader :user
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 = 10
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
- Process.kill(9, pid) if pid
42
+ stop_build
44
43
  exit!
45
44
  end
46
45
 
47
- # build callbacks
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
- @current_build = Build.new(@project_path, @user, @project)
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
- # update git then run the build
103
- def build!(branch=nil)
104
- @git_branch = branch
112
+ def build!(branch)
105
113
  build = @current_build
106
- git_update
114
+ update_tracked_branch branch
115
+ @current_build = read_current_build
107
116
  output = ''
108
- build.sha = git_sha
109
- build.branch = git_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 swith_branch branch
221
- repo_config.branch.set branch if git_branches.include? branch
222
- end
223
-
224
- def git_branches
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 git_branch
230
- return @git_branch if @git_branch
222
+ def tracked_branch
231
223
  branch = repo_config.branch.to_s
232
- @git_branch = (branch == '' ? "master" : branch)
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
- remove_builds_from build
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
- Dir.mkdir path_in_project('.git/builds') unless File.directory?(path_in_project('.git/builds'))
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 remove_builds_from limit_build
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
@@ -53,13 +53,20 @@ module CIQuantum
53
53
  end
54
54
 
55
55
  post '/build' do
56
- quantum.build quantum.git_branch
56
+ puts "Building!"
57
+ quantum.build
57
58
  redirect '/'
58
59
  end
59
60
 
60
61
  post '/switch_branch' do
61
- quantum.swith_branch params[:branch]
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.build quantum.repo_config.branch
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}"
@@ -1,20 +1,24 @@
1
1
  module CIQuantum
2
- module Unfuddle
2
+ class Unfuddle < Struct.new(:config)
3
3
 
4
- def self.name
5
- "unfuddle"
4
+ def self.config_name
5
+ 'unfuddle'
6
6
  end
7
7
 
8
- def self.commit_url commit
9
- "http://#{commit.user}.unfuddle.com/a#/repositories/#{commit.project}/commit?commit=#{commit.sha}"
8
+ def self.from_config config
9
+ self.new config[config_name]
10
10
  end
11
11
 
12
- def self.git_user_and_project config
13
- [ config.user, config.project ]
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 self.project_url user, project
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
@@ -1,7 +1,7 @@
1
1
  require 'active_support/core_ext'
2
2
 
3
3
  module CIQuantum
4
- module Unfuddle
4
+ class Unfuddle
5
5
  class ChangesetError < StandardError ; end
6
6
 
7
7
  class Changeset
@@ -1,3 +1,3 @@
1
1
  module CIQuantum
2
- Version = VERSION = "0.0.16"
2
+ Version = VERSION = "0.0.17"
3
3
  end
@@ -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.url if 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 %>
@@ -4,7 +4,7 @@
4
4
  <style type="text/css">
5
5
 
6
6
  .title {
7
- font-size: 120%;
7
+ font-size: 120%;
8
8
  font-family: Verdana, Arial, Helvetica, sans-serif;
9
9
  border: 1px solid black;
10
10
  margin: 10px 20px;
@@ -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.current_build %>
18
+ <% if quantum.is_building %>
19
19
  <li>
20
- <span class="date"><%= pretty_time(quantum.current_build.started_at) if quantum.current_build %></span> &raquo;
21
- <% if quantum.current_build.sha %>
22
- Building <%= quantum.current_build.branch %> at <a href="<%= quantum.current_build.commit.url %>"><%= quantum.current_build.short_sha %></a> <small>(pid: <%= quantum.pid %>)</small>
23
- <% else %>
24
- Build starting...
25
- <% end %>
20
+ <span class="date"><%= pretty_time(quantum.current_build ? quantum.current_build.started_at : Time.now) %></span> &raquo;
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.git_branch %></span>
31
- <input type="submit" name="switch" value="Build"/>
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.git_branches %>
39
- <option value="<%= @branch %>" <%= 'selected="selected"' if quantum.is_current_git_branch?(@branch) %>>"<%= @branch %>"</option>
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
- <% if ! quantum.active_builds.empty?%>
49
- <% for @build in quantum.active_builds %>
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.16
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-06 00:00:00.000000000 Z
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