Skip to content

Instantly share code, notes, and snippets.

@science
Created January 6, 2015 04:19
Show Gist options
  • Save science/776757a72b7c29160b60 to your computer and use it in GitHub Desktop.
Save science/776757a72b7c29160b60 to your computer and use it in GitHub Desktop.
Simple Workstation CI system. Runs your code when changes are detected. Supports line-by-line debugging.
require 'irb'
require 'term/ansicolor'
require 'open3'
module LT
module Term class << self
include ::Term::ANSIColor
end; end
end
# Monitors all files matching "test_*" in ./test and subfolders for changes
# When it detects a change, it runs the file
# To use, you must edit line 15 for any boot up prelim tasks
# And edit line 56 to tell monitor how to run your test file (via rake or ruby or however your test system works)
desc "Monitor files for changes and run a single test when a change is detected"
task :monitor => [:"ANY BOOT UP TASKS HERE"] do |t, args|
keep_running = true
last_test_file = nil
test_file = ""
puts "\n\n"
dot = ['.', ' '].cycle
while keep_running do
# Loop until interrupted by ctrl-c
trap("INT") { puts "\nExiting"; keep_running = false; exit;}
# if ctrl-z is pressed, re-run the last test file
trap("TSTP") {
if !last_test_file.nil? then
puts "\nRe-running last test: #{last_test_file}"
test_file = last_test_file
end
}
test_list = FileList['test/**/*_test.rb']
orig_test_dates = {}
test_list.each do |file|
orig_test_dates[file] = File.stat(file).mtime
end
# loop through test_list looking for date changes
keep_searching = true
while keep_searching && keep_running do
print "\r#{LT::Term::white}***#{LT::Term::reset} Waiting for file changes. (#{Time::now.strftime('%I:%M %p')}), ctrl-z: re-run last, ctrl-c: exit#{dot.next}"
Kernel::sleep(0.3) # wait 3/10 second between searches for changed files
test_list.each do |file|
Kernel::sleep(0.05) # keep the cpu from maxing out
if orig_test_dates[file] != File.stat(file).mtime
print "\n",LT::Term::white," File change detected: ", LT::Term::bold,"./#{file}",LT::Term::reset,"\n"
puts " Time is: #{Time::now}"
keep_searching = false
test_file = file
end
end
if !test_file.blank? && keep_running
full_test_file = File::expand_path(File::join('.',test_file))
# invoke the test b/c the file has changed
puts "Running test suite..."
last_test_file = test_file
# we capture the output and stream to stdout it line-by-line
IO.popen("rake TASK TO RUN YOUR TEST FILE HERE[#{full_test_file}]").each do |result_line|
failure_error = result_line.match(/^\s+[0-9]+\) Error:/) || result_line.match(/^\s+[0-9]+\) Failure:/)
asserts_failed = result_line.match(/runs, ([0-9]+) assertions, ([0-9]+) failures, ([0-9]+) errors/)
if failure_error then
puts LT::Term::red+result_line+LT::Term::reset+LT::Term::yellow
elsif asserts_failed
asserts = asserts_failed[1]
failures = asserts_failed[2]
errors = asserts_failed[3]
if failures == "0" && errors == "0" then
puts LT::Term::reset+LT::Term::green+result_line+LT::Term::reset
else
puts LT::Term::reset+LT::Term::red+result_line
end
else
puts result_line
end
end
print LT::Term::reset
test_file = ""
end
end # while keep_searching... -- change detection loop
end # while keep_running do -- main loop
end # task :monitor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment