Class: CIJoe

Inherits:
Object
  • Object
show all
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.1.8"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project_path) ⇒ CIJoe

Returns a new instance of CIJoe.



32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/cijoe.rb', line 32

def initialize(project_path)
  project_path = File.expand_path(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_buildObject (readonly)

Returns the value of attribute current_build.



30
31
32
# File 'lib/cijoe.rb', line 30

def current_build
  @current_build
end

#last_buildObject (readonly)

Returns the value of attribute last_build.



30
31
32
# File 'lib/cijoe.rb', line 30

def last_build
  @last_build
end

#projectObject (readonly)

Returns the value of attribute project.



30
31
32
# File 'lib/cijoe.rb', line 30

def project
  @project
end

#urlObject (readonly)

Returns the value of attribute url.



30
31
32
# File 'lib/cijoe.rb', line 30

def url
  @url
end

#userObject (readonly)

Returns the value of attribute user.



30
31
32
# File 'lib/cijoe.rb', line 30

def user
  @user
end

Instance Method Details

#buildObject

run the build but make sure only one is running at a time



85
86
87
88
89
90
# File 'lib/cijoe.rb', line 85

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



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/cijoe.rb', line 93

def build!
  build = @current_build
  out, err, status = '', '', nil
  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
  build_failed('', e.to_s)
end

#build_failed(output, error) ⇒ Object

build callbacks



62
63
64
65
# File 'lib/cijoe.rb', line 62

def build_failed(output, error)
  finish_build :failed, "#{error}\n\n#{output}"
  run_hook "build-failed"
end

#build_worked(output) ⇒ Object



67
68
69
70
# File 'lib/cijoe.rb', line 67

def build_worked(output)
  finish_build :worked, output
  run_hook "build-worked"
end

#building?Boolean

is a build running?

Returns:

  • (Boolean)


46
47
48
# File 'lib/cijoe.rb', line 46

def building?
  !!@current_build
end

#finish_build(status, output) ⇒ Object



72
73
74
75
76
77
78
79
80
81
# File 'lib/cijoe.rb', line 72

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
  write_build 'current', @current_build
  write_build 'last', @last_build
  @last_build.notify if @last_build.respond_to? :notify
end

#git_branchObject



129
130
131
132
# File 'lib/cijoe.rb', line 129

def git_branch
  branch = Config.cijoe.branch.to_s
  branch == '' ? "master" : branch
end

#git_shaObject



116
117
118
# File 'lib/cijoe.rb', line 116

def git_sha
  `git rev-parse origin/#{git_branch}`.chomp
end

#git_updateObject



120
121
122
123
# File 'lib/cijoe.rb', line 120

def git_update
  `git fetch origin && git reset --hard origin/#{git_branch}`
  run_hook "after-reset"
end

#git_user_and_projectObject



125
126
127
# File 'lib/cijoe.rb', line 125

def git_user_and_project
  Config.remote.origin.url.to_s.chomp('.git').split(':')[-1].split('/')[-2, 2]
end

#pidObject

the pid of the running child process



51
52
53
# File 'lib/cijoe.rb', line 51

def pid
  building? and current_build.pid
end

#read_build(name) ⇒ Object

load build info from file.



176
177
178
# File 'lib/cijoe.rb', line 176

def read_build(name)
  Build.load(".git/builds/#{name}")
end

#restoreObject

restore current / last build state from disk.



154
155
156
157
158
159
160
161
162
# File 'lib/cijoe.rb', line 154

def restore
  @last_build = read_build('last')
  @current_build = read_build('current')
  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



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/cijoe.rb', line 135

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.message,
          "AUTHOR" => @last_build.commit.author,
          "SHA" => @last_build.commit.sha,
          "OUTPUT" => @last_build.clean_output
        }
      else
        {}
      end
    env = data.collect { |k, v| %(#{k}=#{v.inspect}) }.join(" ")
    `#{env} sh #{file}`
  end
end

#runner_commandObject

shellin’ out



111
112
113
114
# File 'lib/cijoe.rb', line 111

def runner_command
  runner = Config.cijoe.runner.to_s
  runner == '' ? "rake -s test:units" : runner
end

#stopObject

kill the child and exit



56
57
58
59
# File 'lib/cijoe.rb', line 56

def stop
  Process.kill(9, pid) if pid
  exit!
end

#write_build(name, build) ⇒ Object

write build info for build to file.



165
166
167
168
169
170
171
172
173
# File 'lib/cijoe.rb', line 165

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