perkins 0.0.3 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/Gemfile +1 -0
- data/README.md +11 -8
- data/Rakefile +1 -18
- data/config/database.yml +19 -0
- data/db/migrate/20150130143050_create_builds.rb +1 -1
- data/db/migrate/20150220143051_add_build_status_to_build_reports.rb +10 -0
- data/db/migrate/20150220143053_add_commit_to_build_reports.rb +10 -0
- data/db/migrate/20150220143054_add_hook_id_to_repo.rb +10 -0
- data/db/schema.rb +4 -2
- data/examples/Capfile +17 -0
- data/examples/Gemfile +14 -1
- data/examples/Gemfile.lock +45 -19
- data/examples/Procfile +8 -3
- data/examples/README.md +12 -0
- data/examples/boot.rb +5 -4
- data/examples/config.ru +2 -11
- data/examples/{database.yml → config/database.example.yml} +0 -0
- data/examples/config/database.yml +27 -0
- data/examples/config/deploy.rb +78 -0
- data/examples/config/deploy/staging.rb +61 -0
- data/examples/{rainbows.rb → config/rainbows/development.rb} +1 -1
- data/examples/config/rainbows/production.rb +56 -0
- data/examples/{sidekiq.yml → config/sidekiq.yml} +0 -0
- data/examples/db/schema.rb +43 -0
- data/examples/rakefile +8 -0
- data/lib/perkins/application.rb +1 -1
- data/lib/perkins/assets.rb +3 -3
- data/lib/perkins/assets/javascripts/app.js +1 -0
- data/lib/perkins/assets/javascripts/perkings.js.coffee +14 -9
- data/lib/perkins/assets/javascripts/perkins/helpers.js.coffee +2 -2
- data/lib/perkins/assets/javascripts/perkins/m/models.js.coffee +15 -9
- data/lib/perkins/assets/javascripts/perkins/router.js.coffee +1 -0
- data/lib/perkins/assets/javascripts/perkins/v/my_repos.js.coffee +1 -1
- data/lib/perkins/assets/javascripts/perkins/v/orgs.js.coffee +1 -1
- data/lib/perkins/assets/javascripts/perkins/v/repo.js.coffee +38 -5
- data/lib/perkins/assets/javascripts/templates/repo.hamlc +5 -14
- data/lib/perkins/assets/javascripts/templates/repos/build_row.hamlc +10 -5
- data/lib/perkins/assets/javascripts/templates/repos/config.hamlc +23 -13
- data/lib/perkins/assets/javascripts/templates/repos/report_detail.hamlc +6 -6
- data/lib/perkins/assets/javascripts/vendor/eventsource.polyfill.js +512 -0
- data/lib/perkins/build/script.rb +2 -1
- data/lib/perkins/build/script/go.rb +1 -1
- data/lib/perkins/build/script/ruby.rb +1 -1
- data/lib/perkins/build/script/stages.rb +0 -1
- data/lib/perkins/build_report.rb +27 -7
- data/lib/perkins/build_worker.rb +10 -15
- data/lib/perkins/git_loader_worker.rb +1 -14
- data/lib/perkins/repo.rb +106 -21
- data/lib/perkins/runner.rb +57 -12
- data/lib/perkins/server.rb +42 -46
- data/lib/perkins/socket_server.rb +38 -0
- data/lib/perkins/version.rb +1 -1
- data/lib/tasks/db_tasks.rake +35 -0
- data/perkins.gemspec +16 -19
- data/spec/README.md +3 -0
- data/spec/lib/build/build_spec.rb +7 -3
- data/spec/lib/repo_spec.rb +23 -32
- data/spec/lib/runner_spec.rb +52 -2
- data/spec/lib/server_spec.rb +15 -6
- data/spec/spec_helper.rb +6 -5
- metadata +21 -57
- data/.DS_Store +0 -0
- data/lib/perkins/views/builds.haml +0 -43
- data/lib/perkins/views/menu.haml +0 -18
- data/lib/perkins/views/orgs.haml +0 -101
- data/lib/perkins/views/profile.haml +0 -31
- data/lib/perkins/views/repos/config.haml +0 -72
- data/lib/perkins/views/repos/github.haml +0 -45
- data/lib/perkins/views/repos/menu.haml +0 -17
- data/lib/perkins/views/repos/repo.haml +0 -64
- data/lib/perkins/views/repos/spinner.haml +0 -3
data/lib/perkins/build/script.rb
CHANGED
@@ -157,7 +157,8 @@ module Perkins
|
|
157
157
|
end
|
158
158
|
|
159
159
|
def template(filename)
|
160
|
-
@working_dir = @repo.working_dir + @repo.
|
160
|
+
@working_dir = @repo.working_dir + @repo.download_name
|
161
|
+
#puts "REPO REPO #{@working_dir}"
|
161
162
|
ERB.new(File.read(File.expand_path(filename, TEMPLATES_PATH))).result(binding)
|
162
163
|
end
|
163
164
|
|
@@ -42,7 +42,7 @@ module Perkins
|
|
42
42
|
# `go` commands.
|
43
43
|
source_path = repo.url.gsub(/https\:\/\/|\.git/, "")
|
44
44
|
source_owner_path = source_path.split('/')[0..1].join("/")
|
45
|
-
local_path = self.repo.working_dir + self.repo.
|
45
|
+
local_path = self.repo.working_dir + self.repo.download_name
|
46
46
|
"export GOPATH=#{HOME_DIR}/gopath:$GOPATH && " <<
|
47
47
|
#binding.pry
|
48
48
|
"mkdir -p #{HOME_DIR}/gopath/src/#{source_owner_path} && " <<
|
data/lib/perkins/build_report.rb
CHANGED
@@ -2,9 +2,24 @@ module Perkins
|
|
2
2
|
class BuildReport < ActiveRecord::Base
|
3
3
|
belongs_to :repo
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
after_create :enqueue
|
6
|
+
|
7
|
+
serialize :commit
|
8
|
+
|
9
|
+
def enqueue
|
10
|
+
BuildWorker.perform_async(self.id, sha, branch )
|
11
|
+
end
|
12
|
+
|
13
|
+
#def formatted_commit
|
14
|
+
#self.repo.load_git
|
15
|
+
# self.commit ||= $github_client.commits(repo.name, sha)
|
16
|
+
# Perkins::Commit.new(self.commit)
|
17
|
+
#end
|
18
|
+
|
19
|
+
def retrieve_commit_info
|
20
|
+
hsh = $github_client.commits(repo.name, sha).first.to_attrs
|
21
|
+
self.commit = hsh
|
22
|
+
self.save
|
8
23
|
end
|
9
24
|
|
10
25
|
def send_github_status(sha)
|
@@ -17,7 +32,7 @@ module Perkins
|
|
17
32
|
|
18
33
|
unless fields = options[:only]
|
19
34
|
fields = [:id, :sha, :commit, :branch, :build_time,
|
20
|
-
:status, :duration, :build_time, :response]
|
35
|
+
:status, :duration, :build_time, :response, :build_status]
|
21
36
|
end
|
22
37
|
|
23
38
|
fields.each { |k| data[k] = send(k) }
|
@@ -25,10 +40,7 @@ module Perkins
|
|
25
40
|
data
|
26
41
|
end
|
27
42
|
|
28
|
-
|
29
|
-
|
30
43
|
# Status report to GITHUB repo
|
31
|
-
|
32
44
|
def build_status_report(sha)
|
33
45
|
$github_client.create_status(
|
34
46
|
self.repo.name, sha,
|
@@ -53,5 +65,13 @@ module Perkins
|
|
53
65
|
"#{Perkins::Application.instance.sse_endpoint}/repos/#{repo.name}/builds/#{self.id}"
|
54
66
|
end
|
55
67
|
|
68
|
+
def start!
|
69
|
+
update_attribute(:build_status, "started")
|
70
|
+
end
|
71
|
+
|
72
|
+
def stop!
|
73
|
+
update_attribute(:build_status, "stopped")
|
74
|
+
end
|
75
|
+
|
56
76
|
end
|
57
77
|
end
|
data/lib/perkins/build_worker.rb
CHANGED
@@ -6,33 +6,28 @@ module Perkins
|
|
6
6
|
|
7
7
|
include Sidekiq::Worker
|
8
8
|
|
9
|
-
def perform(
|
10
|
-
|
11
|
-
|
9
|
+
def perform(report_id, sha, branch)
|
10
|
+
report = Perkins::BuildReport.find(report_id)
|
11
|
+
report.retrieve_commit_info
|
12
|
+
repo = report.repo
|
13
|
+
repo.virtual_sha = "-#{report.id}-#{sha}"
|
14
|
+
#repo.build_runner_config
|
15
|
+
#it actually clone repo and instantiates git data & check travis.yml
|
12
16
|
repo.load_git
|
13
17
|
|
14
18
|
return if repo.runner.blank?
|
15
|
-
|
19
|
+
repo.runner.report = report
|
16
20
|
repo.runner.sha = sha
|
17
21
|
repo.runner.branch = branch
|
18
22
|
|
19
|
-
send_sse(
|
23
|
+
repo.send_sse(status: "start")
|
20
24
|
|
21
25
|
repo.runner.run(sha)
|
22
26
|
|
23
27
|
report = repo.build_reports.find_by(sha: sha)
|
24
28
|
report.send_github_status(sha)
|
25
29
|
|
26
|
-
send_sse({
|
27
|
-
end
|
28
|
-
|
29
|
-
def send_sse(msg)
|
30
|
-
url = "#{Perkins::Application.instance.sse_endpoint}/sse"
|
31
|
-
puts "send sse post to #{url} with msg: #{msg.to_json}".pink
|
32
|
-
postData = Net::HTTP.post_form(
|
33
|
-
URI.parse(url),
|
34
|
-
{'msg'=> msg.to_json }
|
35
|
-
)
|
30
|
+
repo.send_sse({ status: "stop", report: report })
|
36
31
|
end
|
37
32
|
|
38
33
|
end
|
@@ -8,22 +8,9 @@ module Perkins
|
|
8
8
|
|
9
9
|
def perform(repo_id)
|
10
10
|
repo = Perkins::Repo.find(repo_id)
|
11
|
+
#return if repo.downloading? or repo.downloaded?
|
11
12
|
#it actually clone repo and instantiates git data
|
12
|
-
send_sse({repo: {id: repo.id, name: repo.name , status: "downloading"} })
|
13
|
-
|
14
13
|
repo.load_git
|
15
|
-
|
16
|
-
send_sse({repo: {id: repo.id, name: repo.name , status: "downloaded" } })
|
17
14
|
end
|
18
|
-
|
19
|
-
def send_sse(msg)
|
20
|
-
url = "#{Perkins::Application.instance.sse_endpoint}/sse"
|
21
|
-
puts "send sse post to #{url} with msg: #{msg.to_json}".pink
|
22
|
-
postData = Net::HTTP.post_form(
|
23
|
-
URI.parse(url),
|
24
|
-
{'msg'=> msg.to_json }
|
25
|
-
)
|
26
|
-
end
|
27
|
-
|
28
15
|
end
|
29
16
|
end
|
data/lib/perkins/repo.rb
CHANGED
@@ -2,7 +2,7 @@ require "git"
|
|
2
2
|
module Perkins
|
3
3
|
class Repo < ActiveRecord::Base
|
4
4
|
attr_accessor :git
|
5
|
-
attr_accessor :new_commit, :runner
|
5
|
+
attr_accessor :new_commit, :runner, :virtual_sha
|
6
6
|
|
7
7
|
has_many :build_reports, class_name: 'Perkins::BuildReport'
|
8
8
|
serialize :github_data, ActiveSupport::HashWithIndifferentAccess
|
@@ -31,7 +31,7 @@ module Perkins
|
|
31
31
|
repo.url = r[:clone_url]
|
32
32
|
repo.name = r[:full_name]
|
33
33
|
repo.gb_id = r[:id]
|
34
|
-
repo.working_dir
|
34
|
+
repo.working_dir ||= DEFAULT_DIR
|
35
35
|
repo.save
|
36
36
|
end
|
37
37
|
|
@@ -41,9 +41,10 @@ module Perkins
|
|
41
41
|
|
42
42
|
def self.store_from_github(repo)
|
43
43
|
#repo
|
44
|
-
repo.working_dir
|
44
|
+
repo.working_dir ||= DEFAULT_DIR #this should be configurable from app
|
45
45
|
repo.cached = false
|
46
46
|
repo.save
|
47
|
+
repo
|
47
48
|
end
|
48
49
|
|
49
50
|
def self.initialize_from_store(opts)
|
@@ -52,7 +53,7 @@ module Perkins
|
|
52
53
|
repo.name = opts["name"]
|
53
54
|
repo.github_data = opts["github_data"]
|
54
55
|
repo.gb_id = opts["github_data"]["id"]
|
55
|
-
repo.working_dir
|
56
|
+
repo.working_dir ||= DEFAULT_DIR #this should be configurable from app
|
56
57
|
repo
|
57
58
|
end
|
58
59
|
|
@@ -60,31 +61,103 @@ module Perkins
|
|
60
61
|
clone_or_load
|
61
62
|
end
|
62
63
|
|
63
|
-
def downloaded?
|
64
|
-
|
64
|
+
#def downloaded?
|
65
|
+
# self.download_status == "downloaded"
|
66
|
+
#end
|
67
|
+
|
68
|
+
#def downloading?
|
69
|
+
# self.download_status == "downloading"
|
70
|
+
#end
|
71
|
+
|
72
|
+
def download!
|
73
|
+
# we need this only in the context of the first clone
|
74
|
+
# in the context of builds we are not going to notice
|
75
|
+
# the user that we are cloning the repo
|
76
|
+
if self.virtual_sha.present?
|
77
|
+
send_sse( status: "downloading")
|
78
|
+
#self.update_column(:download_status, "downloading")
|
79
|
+
end
|
80
|
+
|
81
|
+
#clone repo
|
82
|
+
ssh_url = self.github_data["ssh_url"]
|
83
|
+
Git.clone(ssh_url, download_name, :path => working_dir)
|
84
|
+
open
|
85
|
+
|
86
|
+
#TODO: fix this & handle with care
|
87
|
+
begin
|
88
|
+
add_hook #permissions issue
|
89
|
+
rescue Exception => e
|
90
|
+
puts e.message
|
91
|
+
end
|
92
|
+
|
93
|
+
send_sse(status: "downloaded") if self.virtual_sha.present?
|
94
|
+
end
|
95
|
+
|
96
|
+
def download_name
|
97
|
+
[name, self.virtual_sha].join
|
98
|
+
end
|
99
|
+
|
100
|
+
def add_hook(url=nil)
|
101
|
+
url = hook_url if url.blank?
|
102
|
+
|
103
|
+
if hook_id.blank?
|
104
|
+
res = $github_client.create_hook(
|
105
|
+
self.name,
|
106
|
+
'web',
|
107
|
+
{ :url => url, :content_type => 'json'},
|
108
|
+
{ :events => ['push', 'pull_request'],
|
109
|
+
:active => true}
|
110
|
+
)
|
111
|
+
self.update_attribute(:hook_id, res[:id]) if res[:id].present?
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def edit_hook(url)
|
116
|
+
|
117
|
+
url = hook_url if url.blank?
|
118
|
+
|
119
|
+
hook = get_hook
|
120
|
+
|
121
|
+
if hook.present?
|
122
|
+
res = $github_client.edit_hook(
|
123
|
+
self.name,
|
124
|
+
hook["id"],
|
125
|
+
'web',
|
126
|
+
{:url => url, :content_type => 'json'},
|
127
|
+
{:active => true}
|
128
|
+
)
|
129
|
+
self.update_attribute(:hook_id, res[:id]) if res[:id].present?
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def hook_url
|
134
|
+
u = Perkins::Application.instance.sse_endpoint
|
135
|
+
p = Perkins::Application.instance.port == "80" ? nil : Perkins::Application.instance.port
|
136
|
+
host = [u, p].compact.join(":")
|
137
|
+
url = "#{host}/repos/receiver.json"
|
65
138
|
end
|
66
139
|
|
67
|
-
def
|
68
|
-
self.
|
140
|
+
def get_hook
|
141
|
+
return {} if self.hook_id.blank?
|
142
|
+
$github_client.hook(self.name, self.hook_id)
|
69
143
|
end
|
70
144
|
|
71
145
|
def clone_or_load
|
72
146
|
if exists?
|
73
147
|
open
|
74
148
|
else
|
75
|
-
|
76
|
-
Git.clone(ssh_url, name, :path => working_dir)
|
77
|
-
open
|
149
|
+
download!
|
78
150
|
end
|
79
151
|
end
|
80
152
|
|
81
153
|
def open
|
82
154
|
self.git = Git.open(local_path) # :log => Logger.new(STDOUT)
|
83
|
-
build_runner_config
|
84
|
-
self.update_column(:download_status, "downloaded")
|
155
|
+
build_runner_config
|
156
|
+
#self.update_column(:download_status, "downloaded") #unless self.downloaded?
|
85
157
|
end
|
86
158
|
|
87
159
|
def check_config_existence
|
160
|
+
#puts "CURRENT GIT DIR: #{self.git.dir.path} !!!!!"
|
88
161
|
config = self.git.chdir{
|
89
162
|
if File.exist?(".travis.yml")
|
90
163
|
config = Travis::Yaml.parse( File.open(".travis.yml").read )
|
@@ -101,7 +174,7 @@ module Perkins
|
|
101
174
|
end
|
102
175
|
|
103
176
|
def local_path
|
104
|
-
|
177
|
+
[ self.working_dir , self.download_name].join
|
105
178
|
end
|
106
179
|
|
107
180
|
def branches
|
@@ -109,7 +182,8 @@ module Perkins
|
|
109
182
|
end
|
110
183
|
|
111
184
|
#http://docs.travis-ci.com/user/build-configuration/#The-Build-Matrix
|
112
|
-
def build_runner_config
|
185
|
+
def build_runner_config
|
186
|
+
config = self.check_config_existence
|
113
187
|
runner = Runner.new()
|
114
188
|
runner.config = config
|
115
189
|
runner.repo = self
|
@@ -129,18 +203,23 @@ module Perkins
|
|
129
203
|
end
|
130
204
|
|
131
205
|
def add_commit(sha, branch)
|
132
|
-
if runner_branch.include?(branch)
|
206
|
+
#if runner_branch.include?(branch)
|
133
207
|
#@new_commit = Perkins::Commit.new(sha, self)
|
134
208
|
#@new_commit.branch = branch
|
135
209
|
#enqueue_commit(@new_commit)
|
136
210
|
enqueue_commit(sha, branch)
|
137
|
-
else
|
138
|
-
|
139
|
-
end
|
211
|
+
#else
|
212
|
+
# puts "skipping commit from branch #{branch}"
|
213
|
+
#end
|
140
214
|
end
|
141
215
|
|
142
216
|
def enqueue_commit(sha, branch)
|
143
|
-
|
217
|
+
report = Perkins::BuildReport.new
|
218
|
+
report.sha = sha
|
219
|
+
report.branch = branch
|
220
|
+
|
221
|
+
self.build_reports << report
|
222
|
+
self.save
|
144
223
|
end
|
145
224
|
|
146
225
|
def http_url
|
@@ -154,7 +233,13 @@ module Perkins
|
|
154
233
|
build_reports.last.id if build_reports.any?
|
155
234
|
end
|
156
235
|
|
157
|
-
|
236
|
+
def send_sse(msg)
|
237
|
+
opts = {repo: {id: self.id, name: self.name }}
|
238
|
+
opts[:repo].merge!(msg) if msg.is_a?(Hash)
|
239
|
+
json_opts = opts.to_json
|
240
|
+
puts "Notify #{json_opts}".yellow
|
241
|
+
Redis.current.publish("message.", json_opts)
|
242
|
+
end
|
158
243
|
|
159
244
|
end
|
160
245
|
|
data/lib/perkins/runner.rb
CHANGED
@@ -2,22 +2,34 @@
|
|
2
2
|
module Perkins
|
3
3
|
class Runner
|
4
4
|
|
5
|
-
|
5
|
+
#include Process
|
6
|
+
|
7
|
+
attr_accessor :repo, :report, :command, :config, :sha, :branch
|
6
8
|
attr_reader :build_time, :duration, :response, :status, :current_build
|
7
9
|
|
8
10
|
def exec(cmd)
|
9
11
|
result = run_script(cmd)
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
if successful_command?(process_status) || config_command_with_empty_value?(result,process_status)
|
14
|
-
@response = result
|
12
|
+
@response = result.join("")
|
13
|
+
|
14
|
+
if result.last.chomp.include?("with 0")
|
15
15
|
@status = true
|
16
|
-
|
16
|
+
elsif result.last.chomp.include?("with 1")
|
17
|
+
@status = false
|
17
18
|
else
|
18
|
-
|
19
|
+
puts "status result not found!!"
|
19
20
|
@status = false
|
20
21
|
end
|
22
|
+
|
23
|
+
#puts result
|
24
|
+
#process_status = $?
|
25
|
+
#if successful_command?(process_status) || config_command_with_empty_value?(result,process_status)
|
26
|
+
# @response = result
|
27
|
+
# @status = true
|
28
|
+
# return result
|
29
|
+
#else
|
30
|
+
# @response = result
|
31
|
+
# @status = false
|
32
|
+
#end
|
21
33
|
end
|
22
34
|
|
23
35
|
def run_script(source)
|
@@ -28,33 +40,67 @@ module Perkins
|
|
28
40
|
File.open(script, 'w') { |f| f.write(source) }
|
29
41
|
FileUtils.chmod(0755, script)
|
30
42
|
Bundler.with_clean_env{
|
31
|
-
|
43
|
+
pipe_command("#{script} 2>&1")
|
44
|
+
#`bash #{script} 2>&1`.chomp
|
32
45
|
}
|
33
46
|
end
|
34
47
|
|
48
|
+
def pipe_command(cmd)
|
49
|
+
output = []
|
50
|
+
r, io = IO.pipe
|
51
|
+
pid = fork do
|
52
|
+
@process = system(cmd, out: io, err: :out)
|
53
|
+
end
|
54
|
+
io.close
|
55
|
+
r.each_line{|l|
|
56
|
+
puts l.yellow
|
57
|
+
output << l
|
58
|
+
#puts "CURRENT DIR: #{Dir.pwd} !!!!!"
|
59
|
+
#puts "CURRENT GIT DIR: #{repo.git.dir.path} !!!!!"
|
60
|
+
#puts "#{repo.download_name} !!!!!!!"
|
61
|
+
#updates each time, this should trigger event to interface to refresh
|
62
|
+
@current_report.update_column(:response, output.join(""))
|
63
|
+
}
|
64
|
+
#Process.waitpid(p1) #this is to get the $ exitstatus
|
65
|
+
output
|
66
|
+
end
|
67
|
+
|
35
68
|
def run(sha)
|
36
69
|
self.sha = sha
|
37
70
|
start_build
|
71
|
+
self.repo.virtual_sha = "-#{@current_report.id}-#{self.sha}"
|
72
|
+
#it actually clone repo and instantiates git data
|
73
|
+
repo.load_git
|
74
|
+
|
38
75
|
script = Perkins::Build::script(config, repo)
|
39
76
|
sh = script.compile
|
77
|
+
|
40
78
|
repo.git.chdir do
|
79
|
+
#puts "CURRENT DIR: #{Dir.pwd} !!!!!"
|
80
|
+
#puts "CURRENT GIT DIR: #{repo.git.dir.path} !!!!!"
|
41
81
|
git_update(sha)
|
42
82
|
set_build_stats do
|
43
83
|
puts "perform build".green
|
44
84
|
self.exec(sh)
|
45
85
|
end
|
46
86
|
end
|
47
|
-
store_report
|
87
|
+
#store_report
|
48
88
|
stop_build
|
49
89
|
end
|
50
90
|
|
51
91
|
def start_build
|
52
92
|
@running = true
|
93
|
+
store_report
|
94
|
+
@current_report.start!
|
53
95
|
@repo.update_column(:build_status, "started")
|
54
96
|
end
|
55
97
|
|
56
98
|
def stop_build
|
57
99
|
@running = false
|
100
|
+
@current_report.stop!
|
101
|
+
|
102
|
+
@current_report.update_attributes(self.to_report)
|
103
|
+
|
58
104
|
@repo.update_column(:build_status, "stopped")
|
59
105
|
end
|
60
106
|
|
@@ -103,8 +149,7 @@ module Perkins
|
|
103
149
|
end
|
104
150
|
|
105
151
|
def store_report
|
106
|
-
|
107
|
-
repo.build_reports << r
|
152
|
+
@current_report = Perkins::BuildReport.find(report)
|
108
153
|
end
|
109
154
|
|
110
155
|
def get_builds
|