Class: CIJoe
- Inherits:
-
Object
- Object
- CIJoe
- Defined in:
- lib/cijoe.rb,
lib/cijoe/build.rb,
lib/cijoe/email.rb,
lib/cijoe/commit.rb,
lib/cijoe/config.rb,
lib/cijoe/server.rb,
lib/cijoe/version.rb
Defined Under Namespace
Modules: Email Classes: Build, Commit, Config, Server
Constant Summary collapse
- Version =
"0.2.14"
Instance Attribute Summary collapse
-
#current_build ⇒ Object
readonly
Returns the value of attribute current_build.
-
#old_builds ⇒ Object
readonly
Returns the value of attribute old_builds.
-
#project ⇒ Object
readonly
Returns the value of attribute project.
-
#runner ⇒ Object
readonly
Returns the value of attribute runner.
-
#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.
-
#build! ⇒ Object
update git then run the build.
-
#build_failed(output, error) ⇒ Object
build callbacks.
- #build_worked(output) ⇒ Object
-
#building? ⇒ Boolean
is a build running?.
-
#clean_builds ⇒ Object
removes builds older than what is set in the config.
- #failure_for_time(time) ⇒ Object
- #finish_build(status, output) ⇒ Object
- #git_branch ⇒ Object
- #git_sha ⇒ Object
- #git_update ⇒ Object
- #git_user_and_project ⇒ Object
-
#initialize(project_path, runner) ⇒ CIJoe
constructor
A new instance of CIJoe.
- #log_for_time(time) ⇒ Object
- #open_pipe(cmd) {|read, pid| ... } ⇒ Object
-
#pid ⇒ Object
the pid of the running child process.
-
#read_build(name) ⇒ Object
load build info from file.
-
#restore ⇒ Object
restore current / old 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, runner) ⇒ CIJoe
Returns a new instance of CIJoe.
32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/cijoe.rb', line 32 def initialize(project_path, runner) project_path = File.(project_path) Dir.chdir(project_path) @user, @project = git_user_and_project @url = "http://github.com/#{@user}/#{@project}" @old_builds = [] @current_build = nil @runner = runner trap("INT") { stop } end |
Instance Attribute Details
#current_build ⇒ Object (readonly)
Returns the value of attribute current_build.
30 31 32 |
# File 'lib/cijoe.rb', line 30 def current_build @current_build end |
#old_builds ⇒ Object (readonly)
Returns the value of attribute old_builds.
30 31 32 |
# File 'lib/cijoe.rb', line 30 def old_builds @old_builds end |
#project ⇒ Object (readonly)
Returns the value of attribute project.
30 31 32 |
# File 'lib/cijoe.rb', line 30 def project @project end |
#runner ⇒ Object (readonly)
Returns the value of attribute runner.
30 31 32 |
# File 'lib/cijoe.rb', line 30 def runner @runner end |
#url ⇒ Object (readonly)
Returns the value of attribute url.
30 31 32 |
# File 'lib/cijoe.rb', line 30 def url @url end |
#user ⇒ Object (readonly)
Returns the value of attribute user.
30 31 32 |
# File 'lib/cijoe.rb', line 30 def user @user end |
Instance Method Details
#build ⇒ Object
run the build but make sure only one is running at a time
114 115 116 117 118 119 |
# File 'lib/cijoe.rb', line 114 def build return if building? @current_build = Build.new(@user, @project) write_build 'current', @current_build Thread.new { build! } end |
#build! ⇒ Object
update git then run the build
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/cijoe.rb', line 136 def build! build = @current_build output = '' git_update build.sha = git_sha write_build 'current', build status, stdout, stderr = systemu(runner_command) do |pid| build.pid = pid write_build 'current', build end err, out = stderr, stdout status.exitstatus.to_i == 0 ? build_worked(out) : build_failed(out, err) rescue Object => e puts "Exception building: #{e.} (#{e.class})" build_failed('', e.to_s) 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_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?
48 49 50 |
# File 'lib/cijoe.rb', line 48 def building? !!@current_build end |
#clean_builds ⇒ Object
removes builds older than what is set in the config
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
# File 'lib/cijoe.rb', line 241 def clean_builds numbuilds = Config.cijoe.buildhistory.to_s.to_i numbuilds = numbuilds == 0 ? 10 : numbuilds builds = [] #old builds saved with thier name as a timestamp Dir.glob(".git/builds/*") do |file| file = File.basename(file) builds << file unless (file =~/\./ or file.to_i == 0) end if builds.length > numbuilds #sort and reverse, makes the older builds at the end builds = builds.sort.reverse #remove old builds builds[(numbuilds)...(builds.length)].each do |file| File.unlink(".git/builds/#{file}") if File.exist? ".git/builds/#{file}" end end end |
#failure_for_time(time) ⇒ Object
270 271 272 273 274 275 |
# File 'lib/cijoe.rb', line 270 def failure_for_time(time) @old_builds.each do |build| return build.faillog if build.finished_at.to_i.to_s == time.to_s and build.faillog.to_s != "" end "Log not available" 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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# 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 @current_build.total = $1 if ( output =~ /Agg Total: ([0-9]+)/ || output =~ /Total: ([0-9]+)/ ) @current_build.passes = $1 if ( output =~ /Agg Passed: ([0-9]+)/ || output =~ /Passed: ([0-9]+)/ ) @current_build.fails = $1 if ( output =~ /Agg Failed: ([0-9]+)/ || output =~ /Failed: ([0-9]+)/ ) Dir.glob("**/*.txt") do |f| @current_build.faillog = IO.read(f) if f =~ /faillog/ end @old_builds.insert(0,@current_build) @current_build = nil write_build 'current', @current_build @old_builds.each do |build| name = build.finished_at.to_i.to_s write_build name,build unless File.exist? ".git/builds/#{name}" end clean_builds # Send email notifications if this build failed, or this build # worked after the last one failed if @old_builds[0].failed? && (@old_builds[0].respond_to? :notify_fail) @old_builds[0].notify_fail end if @old_builds[0].worked? && @old_builds[1].failed? && (@old_builds[0].respond_to? :notify_recover) @old_builds[0].notify_recover end end |
#git_branch ⇒ Object
174 175 176 177 |
# File 'lib/cijoe.rb', line 174 def git_branch branch = Config.cijoe.branch.to_s branch == '' ? "master" : branch end |
#git_sha ⇒ Object
160 161 162 |
# File 'lib/cijoe.rb', line 160 def git_sha `git rev-parse origin/#{git_branch}`.chomp end |
#git_update ⇒ Object
164 165 166 167 168 |
# File 'lib/cijoe.rb', line 164 def git_update `git fetch origin` `git reset origin/#{git_branch}` run_hook "after-reset" end |
#git_user_and_project ⇒ Object
170 171 172 |
# File 'lib/cijoe.rb', line 170 def git_user_and_project Config.remote.origin.url.to_s.chomp('.git').split(':')[-1].split('/')[-2, 2] end |
#log_for_time(time) ⇒ Object
263 264 265 266 267 268 |
# File 'lib/cijoe.rb', line 263 def log_for_time(time) @old_builds.each do |build| return build.output if build.finished_at.to_i.to_s == time.to_s end "Log not available" end |
#open_pipe(cmd) {|read, pid| ... } ⇒ Object
121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/cijoe.rb', line 121 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
53 54 55 |
# File 'lib/cijoe.rb', line 53 def pid building? and current_build.pid end |
#read_build(name) ⇒ Object
load build info from file.
236 237 238 |
# File 'lib/cijoe.rb', line 236 def read_build(name) Build.load(".git/builds/#{name}") end |
#restore ⇒ Object
restore current / old build state from disk.
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/cijoe.rb', line 199 def restore unless @old_builds.length > 0 clean_builds builds = [] Dir.glob(".git/builds/*") do |file| file = File.basename(file) builds << file unless (file =~/\./ or file.to_i == 0) end builds = builds.sort.reverse builds.each do |file| @old_builds << read_build(file) end 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
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/cijoe.rb', line 180 def run_hook(hook) if File.exists?(file=".git/hooks/#{hook}") && File.executable?(file) data = if @old_builds[0] && @old_builds[0].commit { "MESSAGE" => @old_builds[0].commit., "AUTHOR" => @old_builds[0].commit., "SHA" => @old_builds[0].commit.sha, "OUTPUT" => @old_builds[0].clean_output } else {} end env = data.collect { |k, v| %(#{k}=#{v.inspect}) }.join(" ") `#{env} sh #{file}` end end |
#runner_command ⇒ Object
shellin’ out
155 156 157 158 |
# File 'lib/cijoe.rb', line 155 def runner_command runner = eval(@runner) runner == '' ? "rake -s test:units" : runner end |
#stop ⇒ Object
kill the child and exit
58 59 60 61 |
# File 'lib/cijoe.rb', line 58 def stop Process.kill(9, pid) if pid exit! end |
#write_build(name, build) ⇒ Object
write build info for build to file.
225 226 227 228 229 230 231 232 233 |
# File 'lib/cijoe.rb', line 225 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 |