Class: CIJoe
- Inherits:
-
Object
- Object
- CIJoe
- Defined in:
- lib/cijoe.rb,
lib/cijoe/build.rb,
lib/cijoe/commit.rb,
lib/cijoe/config.rb,
lib/cijoe/server.rb,
lib/cijoe/version.rb,
lib/cijoe/campfire.rb
Defined Under Namespace
Modules: Campfire Classes: Build, Commit, Config, Server
Constant Summary collapse
- Version =
"0.4.3"
Instance Attribute Summary collapse
-
#current_build ⇒ Object
readonly
Returns the value of attribute current_build.
-
#last_build ⇒ Object
readonly
Returns the value of attribute last_build.
-
#project ⇒ Object
readonly
Returns the value of attribute project.
-
#url ⇒ Object
readonly
Returns the value of attribute url.
-
#user ⇒ Object
readonly
Returns the value of attribute user.
Instance Method Summary collapse
-
#build ⇒ Object
run the build but make sure only one is running at a time (if new one comes in we will park it).
-
#build! ⇒ Object
update git then run the build.
-
#build_failed(output, error) ⇒ Object
build callbacks.
- #build_history ⇒ Object
- #build_worked(output) ⇒ Object
-
#building? ⇒ Boolean
is a build running?.
- #finish_build(status, output) ⇒ Object
- #git_branch ⇒ Object
- #git_sha ⇒ Object
- #git_update ⇒ Object
- #git_user_and_project ⇒ Object
-
#initialize(project_path) ⇒ CIJoe
constructor
A new instance of CIJoe.
- #open_pipe(cmd) {|read, pid| ... } ⇒ Object
-
#pid ⇒ Object
the pid of the running child process.
- #publish_metrics_and_coverage(build) ⇒ Object
- #publish_screenshots(build) ⇒ Object
-
#read_build(name) ⇒ Object
load build info from file.
-
#restore ⇒ Object
restore current / last build state from disk.
-
#run_hook(hook) ⇒ Object
massage our repo.
-
#runner_command ⇒ Object
shellin’ out.
-
#stop ⇒ Object
kill the child and exit.
-
#write_build(name, build) ⇒ Object
write build info for build to file.
Constructor Details
#initialize(project_path) ⇒ CIJoe
Returns a new instance of CIJoe.
28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/cijoe.rb', line 28 def initialize(project_path) project_path = File.(project_path) Dir.chdir(project_path) @user, @project = git_user_and_project @url = "http://github.com/#{@user}/#{@project}" @last_build = nil @current_build = nil trap("INT") { stop } end |
Instance Attribute Details
#current_build ⇒ Object (readonly)
Returns the value of attribute current_build.
26 27 28 |
# File 'lib/cijoe.rb', line 26 def current_build @current_build end |
#last_build ⇒ Object (readonly)
Returns the value of attribute last_build.
26 27 28 |
# File 'lib/cijoe.rb', line 26 def last_build @last_build end |
#project ⇒ Object (readonly)
Returns the value of attribute project.
26 27 28 |
# File 'lib/cijoe.rb', line 26 def project @project end |
#url ⇒ Object (readonly)
Returns the value of attribute url.
26 27 28 |
# File 'lib/cijoe.rb', line 26 def url @url end |
#user ⇒ Object (readonly)
Returns the value of attribute user.
26 27 28 |
# File 'lib/cijoe.rb', line 26 def user @user end |
Instance Method Details
#build ⇒ Object
run the build but make sure only one is running at a time (if new one comes in we will park it)
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/cijoe.rb', line 98 def build if building? # only if switched on to build all incoming requests if Config.cijoe.buildallfile # and there is no previous request return if File.exist?(Config.cijoe.buildallfile.to_s) # we will mark awaiting builds FileUtils.touch(Config.cijoe.buildallfile.to_s) end # leave anyway because a current build runs return end @current_build = Build.new(@user, @project) write_build 'current', @current_build Thread.new { build! } end |
#build! ⇒ Object
update git then run the build
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/cijoe.rb', line 130 def build! build = @current_build output = '' git_update build.sha = git_sha write_build 'current', build open_pipe("unset RACK_BASE_URI; unset RAILS_RELATIVE_URL_ROOT; #{runner_command} 2>&1") do |pipe, pid| puts "#{Time.now.to_i}: Building #{build.short_sha}: pid=#{pid}" build.pid = pid write_build 'current', build output = pipe.read end Process.waitpid(build.pid) status = $?.exitstatus.to_i puts "#{Time.now.to_i}: Built #{build.short_sha}: status=#{status}" status == 0 ? build_worked(output) : build_failed('', output) rescue Object => e puts "Exception building: #{e.} (#{e.class})" build_failed('', e.to_s) publish_screenshots(build) else publish_metrics_and_coverage(build) publish_screenshots(build) end |
#build_failed(output, error) ⇒ Object
build callbacks
64 65 66 67 |
# File 'lib/cijoe.rb', line 64 def build_failed(output, error) finish_build :failed, "#{error}\n\n#{output}" run_hook "build-failed" end |
#build_history ⇒ Object
253 254 255 256 257 258 259 |
# File 'lib/cijoe.rb', line 253 def build_history build_entries = Dir.open(".git/builds").entries.select { |dir| dir.match /^([a-z0-9]{8})\.([\d]{10})\.build$/ } history = build_entries.inject([]) do |builds, entry| builds << read_build(entry) end history.sort { |b,a| a.finished_at <=> b.finished_at } end |
#build_worked(output) ⇒ Object
69 70 71 72 |
# File 'lib/cijoe.rb', line 69 def build_worked(output) finish_build :worked, output run_hook "build-worked" end |
#building? ⇒ Boolean
is a build running?
42 43 44 |
# File 'lib/cijoe.rb', line 42 def building? !!@current_build end |
#finish_build(status, output) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/cijoe.rb', line 74 def finish_build(status, output) @current_build.finished_at = Time.now @current_build.status = status @current_build.output = output @last_build = @current_build @current_build = nil actual_build_id = "#{@last_build.commit.sha[0..7]}.#{Time.now.to_i}.build" write_build actual_build_id, @last_build write_build 'current', @current_build write_build 'last', @last_build @last_build.notify if @last_build.respond_to? :notify # another build waits if Config.cijoe.buildallfile && File.exist?(Config.cijoe.buildallfile.to_s) # clean out before new build FileUtils.rm(Config.cijoe.buildallfile.to_s) build end end |
#git_branch ⇒ Object
196 197 198 199 |
# File 'lib/cijoe.rb', line 196 def git_branch branch = Config.cijoe.branch.to_s branch == '' ? "master" : branch end |
#git_sha ⇒ Object
183 184 185 |
# File 'lib/cijoe.rb', line 183 def git_sha `git rev-parse origin/#{git_branch}`.chomp end |
#git_update ⇒ Object
187 188 189 190 |
# File 'lib/cijoe.rb', line 187 def git_update `git fetch origin && git reset --hard origin/#{git_branch}` run_hook "after-reset" end |
#git_user_and_project ⇒ Object
192 193 194 |
# File 'lib/cijoe.rb', line 192 def git_user_and_project Config.remote.origin.url.to_s.chomp('.git').split(':')[-1].split('/')[-2, 2] end |
#open_pipe(cmd) {|read, pid| ... } ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/cijoe.rb', line 115 def open_pipe(cmd) read, write = IO.pipe pid = fork do read.close $stdout.reopen write exec cmd end write.close yield read, pid end |
#pid ⇒ Object
the pid of the running child process
47 48 49 |
# File 'lib/cijoe.rb', line 47 def pid building? and current_build.pid end |
#publish_metrics_and_coverage(build) ⇒ Object
159 160 161 162 163 164 165 166 167 168 |
# File 'lib/cijoe.rb', line 159 def publish_metrics_and_coverage(build) puts "Creating metrics dir ..." `mkdir #{build.metrics_dir}` puts "Creating coverage dir ..." `mkdir #{build.coverage_dir}` puts "Publishing coverage ..." `cp -r coverage/* #{build.coverage_dir}` puts "Publishing metrics ..." `cp -r tmp/metric_fu/output/* #{build.metrics_dir}` end |
#publish_screenshots(build) ⇒ Object
170 171 172 173 174 175 |
# File 'lib/cijoe.rb', line 170 def publish_screenshots(build) puts "Creating screenshots dir ..." `mkdir #{build.screenshots_dir}` puts "Publishing screenshots ..." `mv screenshots/* #{build.screenshots_dir}` end |
#read_build(name) ⇒ Object
load build info from file.
249 250 251 |
# File 'lib/cijoe.rb', line 249 def read_build(name) Build.load(".git/builds/#{name}") end |
#restore ⇒ Object
restore current / last build state from disk.
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/cijoe.rb', line 221 def restore unless @last_build @last_build = read_build('last') end unless @current_build @current_build = read_build('current') end Process.kill(0, @current_build.pid) if @current_build && @current_build.pid rescue Errno::ESRCH # build pid isn't running anymore. assume previous # server died and reset. @current_build = nil end |
#run_hook(hook) ⇒ Object
massage our repo
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/cijoe.rb', line 202 def run_hook(hook) if File.exists?(file=".git/hooks/#{hook}") && File.executable?(file) data = if @last_build && @last_build.commit { "MESSAGE" => @last_build.commit., "AUTHOR" => @last_build.commit., "SHA" => @last_build.commit.sha, "OUTPUT" => @last_build.clean_output } else {} end data.each{ |k, v| ENV[k] = v } `sh #{file}` end end |
#runner_command ⇒ Object
shellin’ out
178 179 180 181 |
# File 'lib/cijoe.rb', line 178 def runner_command runner = Config.cijoe.runner.to_s runner == '' ? "rake -s test:units" : runner end |
#stop ⇒ Object
kill the child and exit
52 53 54 55 56 57 58 59 60 61 |
# File 'lib/cijoe.rb', line 52 def stop # another build waits if Config.cijoe.buildallfile && File.exist?(Config.cijoe.buildallfile.to_s) # clean out on stop FileUtils.rm(Config.cijoe.buildallfile.to_s) end Process.kill(9, pid) if pid exit! end |
#write_build(name, build) ⇒ Object
write build info for build to file.
238 239 240 241 242 243 244 245 246 |
# File 'lib/cijoe.rb', line 238 def write_build(name, build) filename = ".git/builds/#{name}" Dir.mkdir '.git/builds' unless File.directory?('.git/builds') if build build.dump filename elsif File.exist?(filename) File.unlink filename end end |