ciquantum 0.0.3 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -24,12 +24,12 @@ At current moment gem uses Unfuddle adapter, and must be configured for proper w
24
24
  Expected options:
25
25
  -----------------
26
26
 
27
- git config --add ciquantum.runner "command to do on build"
28
- git config --add ciquantum.branch branch_name
29
- git config --add ciquantum.buildqueue true
30
- git config --add ciquantum.projectname project_name_to_show
31
- git config --add ciquantum.coverage_path relative_path_to_coverage_report
32
-
33
- *Unfuddle (default) adapter:*
34
- git config --add ciquantum.unfuddle.project unfuddle_user_name
35
- git config --add ciquantum.unfuddle.user unfuddle_project_id
27
+ git config --add ciquantum.runner "command to do on build"
28
+ git config --add ciquantum.branch branch_name
29
+ git config --add ciquantum.buildqueue true
30
+ git config --add ciquantum.projectname project_name_to_show
31
+ git config --add ciquantum.coverage_path relative_path_to_coverage_report
32
+
33
+ Unfuddle (default) adapter:
34
+ git config --add ciquantum.unfuddle.project unfuddle_user_name
35
+ git config --add ciquantum.unfuddle.user unfuddle_project_id
@@ -18,7 +18,7 @@ Choice.options do
18
18
  end
19
19
 
20
20
  option :port do
21
- d = 4567
21
+ d = 5555
22
22
  short '-p'
23
23
  long '--port=PORT'
24
24
  desc "The port to listen on (default #{d})"
@@ -24,6 +24,8 @@ Gem::Specification.new do |gem|
24
24
  gem.add_runtime_dependency 'tinder', '>= 1.4.0'
25
25
  gem.add_runtime_dependency 'sinatra'
26
26
  gem.add_runtime_dependency 'choice'
27
+ gem.add_runtime_dependency 'pony'
28
+ gem.add_runtime_dependency 'sq_auth', '>= 0.0.21'
27
29
  gem.add_development_dependency 'rack-test'
28
30
  gem.add_development_dependency 'mocha'
29
31
 
File without changes
File without changes
@@ -1,228 +1,16 @@
1
1
 
2
2
  require 'ciquantum/version'
3
3
  require 'ciquantum/config'
4
- require 'ciquantum/adapter'
4
+ require 'ciquantum/unfuddle'
5
+ require 'ciquantum/unfuddle/changeset'
5
6
  require 'ciquantum/commit'
6
7
  require 'ciquantum/build'
7
8
  require 'ciquantum/server'
8
9
  require 'ciquantum/queue'
10
+ require 'ciquantum/core'
9
11
 
10
-
11
- class CIQuantum
12
- attr_reader :user
13
- attr_reader :project
14
- attr_reader :url
15
- attr_reader :current_build
16
- attr_reader :last_build
17
- attr_reader :campfire
18
- attr_reader :projectname
19
- attr_reader :coverage_path
20
-
21
- def initialize(project_path)
22
- @project_path = File.expand_path(project_path)
23
-
24
- @user, @project = git_user_and_project
25
- @url = project_url
26
- @projectname = repo_config.projectname.to_s
27
- @coverage_path = repo_config.coveragepath.to_s
28
-
29
- @last_build = nil
30
- @current_build = nil
31
- @queue = Queue.new(!repo_config.buildqueue.to_s.empty?, true)
32
-
33
- trap("INT") { stop }
34
- end
35
-
36
- # is a build running?
37
- def building?
38
- !!@current_build
39
- end
40
-
41
- # the pid of the running child process
42
- def pid
43
- building? and current_build.pid
44
- end
45
-
46
- # kill the child and exit
47
- def stop
48
- Process.kill(9, pid) if pid
49
- exit!
50
- end
51
-
52
- # build callbacks
53
- def build_failed(output, error)
54
- finish_build :failed, "#{error}\n\n#{output}"
55
- run_hook "build-failed"
56
- end
57
-
58
- def build_worked(output)
59
- finish_build :worked, output
60
- run_hook "build-worked"
61
- end
62
-
63
- def finish_build(status, output)
64
- @current_build.finished_at = Time.now
65
- @current_build.status = status
66
- @current_build.output = output
67
- @last_build = @current_build
68
-
69
- @current_build = nil
70
- write_build 'current', @current_build
71
- write_build 'last', @last_build
72
-
73
- build(@queue.next_branch_to_build) if @queue.waiting?
74
- end
75
-
76
- # run the build but make sure only one is running
77
- # at a time (if new one comes in we will park it)
78
- def build(branch=nil)
79
- if building?
80
- @queue.append_unless_already_exists(branch)
81
- # leave anyway because a current build runs
82
- return
83
- end
84
- @current_build = Build.new(@project_path, @user, @project)
85
- write_build 'current', @current_build
86
- Thread.new { build!(branch) }
87
- end
88
-
89
- def open_pipe(cmd)
90
- read, write = IO.pipe
91
-
92
- pid = fork do
93
- read.close
94
- $stdout.reopen write
95
- exec cmd
96
- end
97
-
98
- write.close
99
-
100
- yield read, pid
101
- end
102
-
103
- # update git then run the build
104
- def build!(branch=nil)
105
- @git_branch = branch
106
- build = @current_build
107
- output = ''
108
- git_update
109
- build.sha = git_sha
110
- build.branch = git_branch
111
- write_build 'current', build
112
-
113
- open_pipe("cd #{@project_path} && #{runner_command} 2>&1") do |pipe, pid|
114
- puts "#{Time.now.to_i}: Building #{build.branch} at #{build.short_sha}: pid=#{pid}"
115
-
116
- build.pid = pid
117
- write_build 'current', build
118
- output = pipe.read
119
- end
120
-
121
- Process.waitpid(build.pid, 1)
122
- status = $?.exitstatus.to_i
123
- @current_build = build
124
- puts "#{Time.now.to_i}: Built #{build.short_sha}: status=#{status}"
125
-
126
- status == 0 ? build_worked(output) : build_failed('', output)
127
- rescue Object => e
128
- puts "Exception building: #{e.message} (#{e.class})"
129
- build_failed('', e.to_s)
130
- end
131
-
132
- # shellin' out
133
- def runner_command
134
- runner = repo_config.runner.to_s
135
- runner == '' ? "rake -s test:units" : runner
136
- end
137
-
138
- def git_sha
139
- `cd #{@project_path} && git rev-parse origin/#{git_branch}`.chomp
140
- end
141
-
142
- def git_update
143
- `cd #{@project_path} && git fetch origin && git reset --hard origin/#{git_branch}`
144
- run_hook "after-reset"
145
- end
146
-
147
- def git_user_and_project
148
- adapter_config = repo_config.send Adapter.default_adapter.name
149
- Adapter.default_adapter.git_user_and_project adapter_config
150
- end
151
-
152
- def project_url
153
- Adapter.default_adapter.project_url @user, @project
154
- end
155
-
156
- def git_branches
157
- branches = `cd #{@project_path} && git branch -r`.split("\n")
158
- branches.collect{|s| s =~ /(?:\s|^)origin\/(?!HEAD)(\w+)(?:\s|$)/ ? $1.strip : nil}.compact
159
- end
160
-
161
- def git_branch
162
- return @git_branch if @git_branch
163
- branch = repo_config.branch.to_s
164
- @git_branch = branch == '' ? "master" : branch
165
- end
166
-
167
- # massage our repo
168
- def run_hook(hook)
169
- if File.exists?(file=path_in_project(".git/hooks/#{hook}")) && File.executable?(file)
170
- data =
171
- if @last_build && @last_build.commit
172
- {
173
- "MESSAGE" => @last_build.commit.message,
174
- "AUTHOR" => @last_build.commit.author,
175
- "SHA" => @last_build.commit.sha,
176
- "OUTPUT" => @last_build.env_output
177
- }
178
- else
179
- {}
180
- end
181
-
182
- orig_ENV = ENV.to_hash
183
- ENV.clear
184
- data.each{ |k, v| ENV[k] = v }
185
- output = `cd #{@project_path} && #{file}`
186
-
187
- ENV.clear
188
- orig_ENV.to_hash.each{ |k, v| ENV[k] = v}
189
- output
190
- end
191
- end
192
-
193
- # restore current / last build state from disk.
194
- def restore
195
- @last_build = read_build('last')
196
- @current_build = read_build('current')
197
-
198
- Process.kill(0, @current_build.pid) if @current_build && @current_build.pid
199
- rescue Errno::ESRCH
200
- # build pid isn't running anymore. assume previous
201
- # server died and reset.
202
- @current_build = nil
203
- end
204
-
205
- def path_in_project(path)
206
- File.join(@project_path, path)
207
- end
208
-
209
- # write build info for build to file.
210
- def write_build(name, build)
211
- filename = path_in_project(".git/builds/#{name}")
212
- Dir.mkdir path_in_project('.git/builds') unless File.directory?(path_in_project('.git/builds'))
213
- if build
214
- build.dump filename
215
- elsif File.exist?(filename)
216
- File.unlink filename
217
- end
218
- end
219
-
220
- def repo_config
221
- Config.ciquantum(@project_path)
222
- end
223
-
224
- # load build info from file.
225
- def read_build(name)
226
- Build.load(path_in_project(".git/builds/#{name}"), @project_path)
12
+ module CIQuantum
13
+ def self.new *args
14
+ CIQuantum::Core.new *args
227
15
  end
228
16
  end
@@ -1,6 +1,6 @@
1
1
  require 'yaml'
2
2
 
3
- class CIQuantum
3
+ module CIQuantum
4
4
  class Build < Struct.new(:project_path, :user, :project, :started_at, :finished_at, :sha, :status, :output, :pid, :branch)
5
5
  def initialize(*args)
6
6
  super
@@ -51,13 +51,14 @@ class CIQuantum
51
51
  @commit ||= Commit.new(sha, user, project, project_path)
52
52
  end
53
53
 
54
- def dump(file)
54
+ def dump file
55
55
  config = [user, project, started_at, finished_at, sha, status, output, pid, branch]
56
56
  data = YAML.dump(config)
57
57
  File.open(file, 'wb') { |io| io.write(data) }
58
58
  end
59
59
 
60
- def self.load(file, project_path)
60
+ def self.load file, project_path
61
+ puts "Loading build from file: #{file}"
61
62
  if File.exist?(file)
62
63
  config = YAML.load(File.read(file)).unshift(project_path)
63
64
  new *config
@@ -1,7 +1,7 @@
1
- class CIQuantum
1
+ module CIQuantum
2
2
  class Commit < Struct.new(:sha, :user, :project, :project_path)
3
3
  def url
4
- Adapter::default_adapter.commit_url self
4
+ Unfuddle.commit_url self
5
5
  end
6
6
 
7
7
  def author
@@ -1,4 +1,4 @@
1
- class CIQuantum
1
+ module CIQuantum
2
2
  class Config
3
3
  def self.method_missing(command, *args)
4
4
  new(command, *args)
@@ -0,0 +1,268 @@
1
+ module CIQuantum
2
+ class Core
3
+ attr_reader :user
4
+ attr_reader :project
5
+ attr_reader :url
6
+ attr_reader :current_build
7
+ attr_reader :last_build
8
+ attr_reader :campfire
9
+ attr_reader :projectname
10
+ attr_reader :coverage_path
11
+
12
+ HistoryLimit = 10
13
+
14
+ def initialize(project_path)
15
+ @project_path = File.expand_path(project_path)
16
+
17
+ @user, @project = git_user_and_project
18
+ @url = project_url
19
+ @projectname = repo_config.projectname.to_s
20
+ @coverage_path = repo_config.coveragepath.to_s
21
+
22
+ @last_build = nil
23
+ @current_build = nil
24
+ @queue = Queue.new(!repo_config.buildqueue.to_s.empty?, true)
25
+
26
+ trap("INT") { stop }
27
+ end
28
+
29
+ # is a build running?
30
+ def building?
31
+ !!@current_build
32
+ end
33
+
34
+ # the pid of the running child process
35
+ def pid
36
+ building? and current_build.pid
37
+ end
38
+
39
+ # kill the child and exit
40
+ def stop
41
+ Process.kill(9, pid) if pid
42
+ exit!
43
+ end
44
+
45
+ # build callbacks
46
+ def build_failed(output, error)
47
+ finish_build :failed, "#{error}\n\n#{output}"
48
+ run_hook "build-failed"
49
+ end
50
+
51
+ def build_worked(output)
52
+ finish_build :worked, output
53
+ run_hook "build-worked"
54
+ end
55
+
56
+ def finish_build(status, output)
57
+ @current_build.finished_at = Time.now
58
+ @current_build.status = status
59
+ @current_build.output = output
60
+ @last_build = @current_build
61
+
62
+ @current_build = nil
63
+ write_current_build
64
+ write_last_build
65
+ run_hook "postbuild"
66
+
67
+ build(@queue.next_branch_to_build) if @queue.waiting?
68
+ end
69
+
70
+ def build(branch=nil)
71
+ if building?
72
+ @queue.append_unless_already_exists(branch)
73
+ # leave anyway because a current build runs
74
+ return
75
+ end
76
+ @current_build = Build.new(@project_path, @user, @project)
77
+ write_current_build
78
+
79
+ Thread.new {
80
+ build!(branch)
81
+ }
82
+
83
+ end
84
+
85
+ def open_pipe(cmd)
86
+ read, write = IO.pipe
87
+
88
+ pid = fork do
89
+ read.close
90
+ $stdout.reopen write
91
+ exec cmd
92
+ end
93
+
94
+ write.close
95
+
96
+ yield read, pid
97
+ end
98
+
99
+ # update git then run the build
100
+ def build!(branch=nil)
101
+ @git_branch = branch
102
+ build = @current_build
103
+ run_hook "prebuild"
104
+ git_update
105
+ output = ''
106
+ build.sha = git_sha
107
+ build.branch = git_branch
108
+ write_build 'current', build
109
+
110
+ open_pipe("cd #{@project_path} && #{runner_command} 2>&1") do |pipe, pid|
111
+ puts "#{Time.now.to_i}: Building #{build.branch} at #{build.short_sha}: pid=#{pid}"
112
+
113
+ build.pid = pid
114
+ write_build 'current', build
115
+ output = pipe.read
116
+ end
117
+
118
+ Process.waitpid(build.pid, 1)
119
+ status = $?.exitstatus.to_i
120
+ @current_build = build
121
+ puts "#{Time.now.to_i}: Built #{build.short_sha}: status=#{status}"
122
+
123
+ status == 0 ? build_worked(output) : build_failed('', output)
124
+ rescue Object => e
125
+ puts "Exception building: #{e.message} (#{e.class})"
126
+ build_failed('', e.to_s)
127
+ end
128
+
129
+ # shellin' out
130
+ def runner_command
131
+ runner = repo_config.runner.to_s
132
+ runner == '' ? "rake -s test:units" : runner
133
+ end
134
+
135
+ def git_update
136
+ `cd #{@project_path} && git fetch origin && git reset --hard origin/#{git_branch}`
137
+ run_hook "after-reset"
138
+ end
139
+
140
+ def git_user_and_project
141
+ config = repo_config.send Unfuddle.name
142
+ Unfuddle.git_user_and_project config
143
+ end
144
+
145
+ def project_url
146
+ Unfuddle.project_url @user, @project
147
+ end
148
+
149
+ # massage our repo
150
+ def run_hook(hook)
151
+ if File.exists?(file=path_in_project(".git/hooks/#{hook}")) && File.executable?(file)
152
+ data =
153
+ if @last_build && @last_build.commit
154
+ {
155
+ "MESSAGE" => @last_build.commit.message,
156
+ "AUTHOR" => @last_build.commit.author,
157
+ "SHA" => @last_build.commit.sha,
158
+ "URL" => @last_build.commit.url,
159
+ "OUTPUT" => @last_build.env_output
160
+ }
161
+ else
162
+ {}
163
+ end
164
+
165
+ orig_ENV = ENV.to_hash
166
+ # ENV.clear
167
+ data.each{ |k, v| ENV[k] = v }
168
+ puts "Executing hook: #{file}"
169
+ output = `cd #{@project_path} && #{file}`
170
+
171
+ ENV.clear
172
+ orig_ENV.to_hash.each{ |k, v| ENV[k] = v}
173
+ output
174
+ end
175
+ end
176
+
177
+ # restore current / last build state from disk.
178
+ def restore
179
+ @last_build = read_last_build
180
+ @current_build = read_current_build
181
+
182
+ Process.kill(0, @current_build.pid) if @current_build && @current_build.pid
183
+ rescue Errno::ESRCH
184
+ @current_build = nil
185
+ end
186
+
187
+ def path_in_project(path)
188
+ File.join(@project_path, path)
189
+ end
190
+
191
+ def repo_config
192
+ Config.ciquantum(@project_path)
193
+ end
194
+
195
+ def swith_branch branch
196
+ repo_config.branch.set branch if git_branches.include? branch
197
+ end
198
+
199
+ def git_branches
200
+ branches = `cd #{@project_path} && git branch -r`.split("\n")
201
+ branches.collect{|s| s =~ /(?:\s|^)origin\/(?!HEAD)(\w+)(?:\s|$)/ ? $1.strip : nil}.compact
202
+ end
203
+
204
+ def git_branch
205
+ return @git_branch if @git_branch
206
+ branch = repo_config.branch.to_s
207
+ @git_branch = (branch == '' ? "master" : branch)
208
+ end
209
+
210
+ def git_sha
211
+ `cd #{@project_path} && git rev-parse origin/#{git_branch}`.chomp
212
+ end
213
+
214
+ def read_build(name)
215
+ Build.load(path_in_project(".git/builds/#{name}"), @project_path)
216
+ end
217
+
218
+ def read_last_build
219
+ read_build_by_index 0
220
+ end
221
+
222
+ def read_current_build
223
+ read_build 'current'
224
+ end
225
+
226
+ def read_build_by_index index
227
+ read_build old_builds[index] if old_builds[index]
228
+ end
229
+
230
+ def old_builds
231
+ Dir.glob(path_in_project(".git/builds/*")).collect do |f|
232
+ File.basename(f)
233
+ end.select do |f|
234
+ f =~ /\d+/
235
+ end.sort.reverse
236
+ end
237
+
238
+ def write_last_build
239
+ write_build @last_build.finished_at.to_i.to_s, @last_build
240
+ end
241
+
242
+ def write_current_build
243
+ write_build 'current', @current_build
244
+ end
245
+
246
+ def write_build(name, build)
247
+ filename = path_in_project(".git/builds/#{name}")
248
+ Dir.mkdir path_in_project('.git/builds') unless File.directory?(path_in_project('.git/builds'))
249
+ if build
250
+ build.dump filename
251
+ elsif File.exist?(filename)
252
+ File.unlink filename
253
+ end
254
+ remove_unused_build
255
+ end
256
+
257
+ def remove_unused_build
258
+ builds = old_builds
259
+ if builds.size > HistoryLimit
260
+ builds[HistoryLimit..builds.size].each do |file|
261
+ file = path_in_project(".git/builds/#{file}")
262
+ File.delete file if File.exists? file
263
+ end
264
+ end
265
+ end
266
+
267
+ end
268
+ end
@@ -1,8 +1,5 @@
1
- class CIQuantum
2
- # An in memory queue used for maintaining an order list of requested
3
- # builds.
1
+ module CIQuantum
4
2
  class Queue
5
- # enabled - determines whether builds should be queued or not.
6
3
  def initialize(enabled, verbose=false)
7
4
  @enabled = enabled
8
5
  @verbose = verbose
@@ -11,13 +8,6 @@ class CIQuantum
11
8
  log("Build queueing enabled") if enabled
12
9
  end
13
10
 
14
- # Public: Appends a branch to be built, unless it already exists
15
- # within the queue.
16
- #
17
- # branch - the name of the branch to build or nil if the default
18
- # should be built.
19
- #
20
- # Returns nothing
21
11
  def append_unless_already_exists(branch)
22
12
  return unless enabled?
23
13
  unless @queue.include? branch
@@ -26,15 +16,12 @@ class CIQuantum
26
16
  end
27
17
  end
28
18
 
29
- # Returns a String of the next branch to build
30
19
  def next_branch_to_build
31
20
  branch = @queue.shift
32
21
  log "#{Time.now.to_i}: De-queueing #{branch}"
33
22
  branch
34
23
  end
35
24
 
36
- # Returns true if there are requested builds waiting and false
37
- # otherwise.
38
25
  def waiting?
39
26
  if enabled?
40
27
  not @queue.empty?
@@ -1,9 +1,16 @@
1
- require 'sinatra/base'
2
1
  require 'erb'
3
2
  require 'json'
4
3
 
5
- class CIQuantum
4
+ require 'sinatra'
5
+ require 'sq_auth'
6
+
7
+ module CIQuantum
6
8
  class Server < Sinatra::Base
9
+
10
+ SqAuth.connect(host: "sqauth.socialquantum.com", port: 443) do |config|
11
+ config.project_name = "Enchanted"
12
+ end
13
+
7
14
  attr_reader :quantum
8
15
 
9
16
  dir = File.dirname(File.expand_path(__FILE__))
@@ -13,6 +20,9 @@ class CIQuantum
13
20
  set :static, true
14
21
  set :lock, true
15
22
 
23
+ enable :static
24
+ enable :sessions
25
+
16
26
  before { quantum.restore }
17
27
 
18
28
  get '/ping' do
@@ -23,33 +33,35 @@ class CIQuantum
23
33
  quantum.last_build.sha
24
34
  end
25
35
 
26
- get '/?' do
27
- erb(:template, {}, :quantum => quantum)
36
+ get ["ci::view", "ci::change_branch"], '/?' do
37
+ erb(:template, {}, :quantum => quantum, :can_change_branch => accessed_by?("ci::change_branch"))
28
38
  end
29
39
 
30
- post '/?' do
31
- puts params
32
- unless params[:rebuild]
33
- payload = JSON.parse(params[:payload])
34
- pushed_branch = payload["ref"].split('/').last
40
+ sq_auth_access do
41
+ access_action "/build" do
42
+ execute_for "ci::view"
35
43
  end
36
-
37
- # Only build if we were given an explicit branch via `?branch=blah`
38
- # or the payload exists and the "ref" property matches our
39
- # specified build branch.
40
- if params[:branch] || params[:rebuild] || pushed_branch == quantum.git_branch
41
- quantum.build(params[:branch])
44
+ access_action "/switch_branch" do
45
+ execute_for "ci::admin"
42
46
  end
47
+ end
43
48
 
44
- if params[:switch] == "Switch branch"
45
- quantum.repo_config.branch.set params[:branch] if quantum.git_branches.include? params[:branch]
46
- end
49
+ post '/build' do
50
+ quantum.build quantum.repo_config.branch
51
+
52
+ link_coverage_path
53
+ redirect '/'
54
+ end
47
55
 
56
+ post '/switch_branch' do
57
+ quantum.swith_branch params[:branch]
58
+ quantum.build params[:branch]
48
59
 
49
- redirect request.path
60
+ link_coverage_path
61
+ redirect '/'
50
62
  end
51
63
 
52
- get '/api/json' do
64
+ get ["ci::view"], '/api/json' do
53
65
  response = [200, {'Content-Type' => 'application/json'}]
54
66
  response_json = erb(:json, {}, :quantum => quantum)
55
67
  if params[:jsonp]
@@ -60,8 +72,20 @@ class CIQuantum
60
72
  response
61
73
  end
62
74
 
63
- get '/coverage' do
64
- redirect quantum.coverage_path
75
+ post '/push' do
76
+ begin
77
+ xml = request.body.read
78
+ changeset = Unfuddle::Changeset.new(xml)
79
+ quantum.build quantum.repo_config.branch
80
+ link_coverage_path
81
+ rescue Unfuddle::ChangesetError => e
82
+ logger.error "[error] Changeset error: #{e.inspect}, Content: #{xml.inspect}"
83
+ halt 400, "Changeset Error: #{e.message}"
84
+ end
85
+ end
86
+
87
+ get ["ci::view"], '/coverage?' do
88
+ redirect "coverage/index.html"
65
89
  end
66
90
 
67
91
  helpers do
@@ -83,6 +107,7 @@ class CIQuantum
83
107
  root = "" if root == "/"
84
108
  root
85
109
  end
110
+
86
111
  end
87
112
 
88
113
  def initialize(*args)
@@ -101,14 +126,17 @@ class CIQuantum
101
126
  self.new
102
127
  end
103
128
 
104
- def self.project_path=(project_path)
105
- user, pass = Config.ciquantum(project_path).user.to_s, Config.ciquantum(project_path).pass.to_s
106
- if user != '' && pass != ''
107
- use Rack::Auth::Basic do |username, password|
108
- [ username, password ] == [ user, pass ]
109
- end
110
- puts "Using HTTP basic auth"
129
+ def link_coverage_path
130
+ public_coverage_path = File.join settings.public_folder, "coverage"
131
+ project_coverage_path = File.join settings.project_path, quantum.coverage_path
132
+
133
+ File.unlink public_coverage_path if File.exists? public_coverage_path
134
+ if !quantum.coverage_path.empty? and File.exists? project_coverage_path
135
+ File.symlink project_coverage_path, public_coverage_path
111
136
  end
137
+ end
138
+
139
+ def self.project_path=(project_path)
112
140
  set :project_path, Proc.new{project_path}, true
113
141
  end
114
142
 
@@ -1,5 +1,5 @@
1
- class CIQuantum
2
- class UnfuddleAdapter
1
+ module CIQuantum
2
+ module Unfuddle
3
3
 
4
4
  def self.name
5
5
  "unfuddle"
@@ -10,12 +10,12 @@ class CIQuantum
10
10
  end
11
11
 
12
12
  def self.git_user_and_project config
13
- [ (config.user.empty? ? "linkfeed" : config.user), (config.project.empty? ? "17607" : config.project)]
13
+ [ config.user, config.project ]
14
14
  end
15
15
 
16
16
  def self.project_url user, project
17
- "https://#{user}.unfuddle.com/a#/repositories/#{project}/browse"
17
+ "https://#{user}.unfuddle.com/a#/repositories/#{project}/browse"
18
18
  end
19
19
 
20
20
  end
21
- end
21
+ end
@@ -0,0 +1,44 @@
1
+ require 'active_support/core_ext'
2
+
3
+ module CIQuantum
4
+ module Unfuddle
5
+ class ChangesetError < StandardError ; end
6
+
7
+ class Changeset
8
+ FIELDS = %w(repository_id revision message committer_name committer_date).freeze
9
+
10
+ attr_reader :author
11
+ attr_reader :message
12
+ attr_reader :date
13
+ attr_reader :commit
14
+ attr_reader :repo
15
+ attr_reader :xml
16
+
17
+ def initialize(xml)
18
+ xml = xml.to_s.strip
19
+ raise ChangesetError, 'Changeset XML required!' if xml.empty?
20
+
21
+ begin
22
+ @data = Hash.from_xml(xml)
23
+ rescue REXML::ParseException
24
+ raise ChangesetError, 'Invalid XML data!'
25
+ end
26
+
27
+ raise ChangesetError, 'Invalid changeset!' unless @data.key?('changeset')
28
+
29
+ @xml = xml
30
+ @data = @data['changeset']
31
+
32
+ unless (FIELDS & @data.keys).size == FIELDS.size
33
+ raise ChangesetError, 'Invalid changeset!'
34
+ end
35
+
36
+ @commit = @data['revision']
37
+ @author = @data['committer_name']
38
+ @message = @data['message']
39
+ @date = @data['committer_date']
40
+ @repo = @data['repository_id']
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,3 +1,3 @@
1
- class CIQuantum
2
- Version = VERSION = "0.0.3"
1
+ module CIQuantum
2
+ Version = VERSION = "0.0.6"
3
3
  end
@@ -2,7 +2,6 @@
2
2
  <html>
3
3
  <head>
4
4
  <link href="<%= ciquantum_root %>/screen.css" media="screen" rel="stylesheet" type="text/css" />
5
- <link rel="shortcut icon" href="<%= ciquantum_root %>/favicon.ico" type="image/x-icon" />
6
5
  <title><%= h(quantum.projectname) %>: CI Quantum</title>
7
6
  </head>
8
7
  <body>
@@ -26,16 +25,22 @@
26
25
  </li>
27
26
  <% else %>
28
27
  <li>
29
- <form method="POST">
30
- <input type="hidden", name="rebuild" value="true">
28
+ <form method="POST" action="/build">
29
+ <span class="branch">Current branch: <%= quantum.git_branch %></span>
30
+ <input type="submit" name="switch" value="Build"/>
31
+ </form>
32
+ </li>
33
+ <li>
34
+ <% if can_change_branch %>
35
+ <form method="POST" action="/switch_branch">
31
36
  <select name="branch">
32
37
  <% for @branch in quantum.git_branches %>
33
38
  <option value="<%= @branch %>" <%= "selected=\"selected\"" if (@branch == quantum.git_branch) %> >"<%= @branch %>"</option>
34
39
  <% end %>
35
40
  </select>
36
- <input type="submit" name="switch" value="Build once"/>
37
- <input type="submit" name="switch" value="Switch branch"/>
41
+ <input type="submit" name="switch" value="Switch branch and build"/>
38
42
  </form>
43
+ <% end %>
39
44
  </li>
40
45
  <% end %>
41
46
 
@@ -61,30 +66,6 @@
61
66
  <% end %>
62
67
  </ul>
63
68
  </div>
64
-
65
- <div class="footer">
66
- <div class="contact">
67
- <p>
68
- <a href="https://github.com/meredian/ciquantum#readme">Documentation</a><br/>
69
- <a href="https://github.com/meredian/ciquantum">Source</a><br/>
70
- <a href="https://github.com/meredian/ciquantum/issues">Issues</a><br/>
71
- <a href="https://github.com/meredian/ciquantum/tree/v<%= CIQuantum::VERSION %>">v<%= CIQuantum::VERSION %></a>
72
- </p>
73
- </div>
74
- <div class="contact">
75
- <p>
76
- Designed by <a href="http://tom.preston-werner.com/">Tom Preston-Werner</a><br/>
77
- Influenced by <a href="http://integrityapp.com/">Integrity</a><br/>
78
- Built with <a href="http://sinatrarb.com/">Sinatra</a><br/>
79
- Keep it simple, Sam.
80
- </p>
81
- </div>
82
- <div class="rss">
83
- <a href="http://github.com/meredian/ciquantum">
84
- <img src="<%= ciquantum_root %>/octocat.png" alt="Octocat!" />
85
- </a>
86
- </div>
87
- </div>
88
69
  </div>
89
70
  </body>
90
71
  </html>
@@ -0,0 +1,15 @@
1
+ require 'sinatra'
2
+ require 'sq_auth'
3
+
4
+ class Server < Sinatra::Base
5
+ enable :sessions
6
+ set :port, 5555
7
+
8
+ SqAuth.connect(host: "sqauth.socialquantum.com", port: 443) do |config|
9
+ config.project_name = "Enchanted"
10
+ end
11
+
12
+ get ["ci::view"], '/?' do
13
+ "Hello world. Authorize_info: #{access_for("ci::view"){"You can see it"}}"
14
+ end
15
+ end
@@ -18,19 +18,21 @@ class File
18
18
  end
19
19
 
20
20
  # #mock file to be the file I want
21
- class CIQuantum
22
- attr_writer :last_build
23
- alias orig_path_in_project path_in_project
24
- alias orig_git_user_and_project git_user_and_project
21
+ module CIQuantum
22
+ class Core
23
+ attr_writer :last_build
24
+ alias orig_path_in_project path_in_project
25
+ alias orig_git_user_and_project git_user_and_project
25
26
 
26
- def path_in_project(f)
27
- return '/tmp/test' if $hook_override
28
- orig_path_in_project
29
- end
27
+ def path_in_project(f)
28
+ return '/tmp/test' if $hook_override
29
+ orig_path_in_project
30
+ end
30
31
 
31
- def git_user_and_project
32
- return ['mine','yours'] if $hook_override
33
- orig_git_user_and_project
32
+ def git_user_and_project
33
+ return ['mine','yours'] if $hook_override
34
+ orig_git_user_and_project
35
+ end
34
36
  end
35
37
  end
36
38
 
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.3
4
+ version: 0.0.6
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-04-23 00:00:00.000000000 Z
14
+ date: 2012-05-03 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -109,6 +109,38 @@ dependencies:
109
109
  - - ! '>='
110
110
  - !ruby/object:Gem::Version
111
111
  version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: pony
114
+ requirement: !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ! '>='
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ type: :runtime
121
+ prerelease: false
122
+ version_requirements: !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ! '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ - !ruby/object:Gem::Dependency
129
+ name: sq_auth
130
+ requirement: !ruby/object:Gem::Requirement
131
+ none: false
132
+ requirements:
133
+ - - ! '>='
134
+ - !ruby/object:Gem::Version
135
+ version: 0.0.21
136
+ type: :runtime
137
+ prerelease: false
138
+ version_requirements: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ! '>='
142
+ - !ruby/object:Gem::Version
143
+ version: 0.0.21
112
144
  - !ruby/object:Gem::Dependency
113
145
  name: rack-test
114
146
  requirement: !ruby/object:Gem::Requirement
@@ -158,22 +190,22 @@ files:
158
190
  - ciquantum.gemspec
159
191
  - examples/build-failed
160
192
  - examples/build-worked
161
- - examples/cijoe.ru
162
- - examples/cijoed
193
+ - examples/ciquantum.ru
194
+ - examples/ciquantumd
163
195
  - lib/ciquantum.rb
164
- - lib/ciquantum/adapter.rb
165
196
  - lib/ciquantum/build.rb
166
197
  - lib/ciquantum/commit.rb
167
198
  - lib/ciquantum/config.rb
168
- - lib/ciquantum/public/favicon.ico
169
- - lib/ciquantum/public/octocat.png
199
+ - lib/ciquantum/core.rb
170
200
  - lib/ciquantum/public/screen.css
171
201
  - lib/ciquantum/queue.rb
172
202
  - lib/ciquantum/server.rb
173
- - lib/ciquantum/unfuddle_adapter.rb
203
+ - lib/ciquantum/unfuddle.rb
204
+ - lib/ciquantum/unfuddle/changeset.rb
174
205
  - lib/ciquantum/version.rb
175
206
  - lib/ciquantum/views/json.erb
176
207
  - lib/ciquantum/views/template.erb
208
+ - sample.rb
177
209
  - test/fixtures/payload.json
178
210
  - test/helper.rb
179
211
  - test/test_ciquantum_queue.rb
@@ -1,15 +0,0 @@
1
- require 'ciquantum/unfuddle_adapter'
2
-
3
- class CIQuantum
4
- class Adapter
5
- class << self
6
-
7
- attr_writer :default_adapter
8
-
9
- def default_adapter
10
- @default_adapter ||= CIQuantum::UnfuddleAdapter
11
- end
12
-
13
- end
14
- end
15
- end