perkins 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +5 -0
- data/.ruby-version +1 -0
- data/.vagrant/machines/default/virtualbox/action_provision +1 -0
- data/.vagrant/machines/default/virtualbox/action_set_name +1 -0
- data/.vagrant/machines/default/virtualbox/id +1 -0
- data/Gemfile +0 -1
- data/README.md +11 -4
- data/Rakefile +3 -2
- data/TODO.md +2 -2
- data/Vagrantfile +53 -0
- data/db/migrate/20150220143050_add_status_fields_to_repos.rb +11 -0
- data/db/schema.rb +3 -1
- data/examples/Gemfile +4 -0
- data/examples/Gemfile.lock +164 -0
- data/examples/Procfile +4 -0
- data/examples/boot.rb +15 -0
- data/examples/config.ru +22 -0
- data/examples/database.yml +2 -2
- data/examples/sidekiq.yml +9 -0
- data/lib/core_ext/string/color.rb +22 -0
- data/lib/perkins/application.rb +27 -3
- data/lib/perkins/assets/images/error.gif +0 -0
- data/lib/perkins/assets/images/working.gif +0 -0
- data/lib/perkins/assets/javascripts/app.js +17 -1
- data/lib/perkins/assets/javascripts/config.js.coffee +14 -0
- data/lib/perkins/assets/javascripts/log_view.js.coffee +1 -2
- data/lib/perkins/assets/javascripts/perkings.js.coffee +129 -20
- data/lib/perkins/assets/javascripts/perkins/helpers.js.coffee +21 -0
- data/lib/perkins/assets/javascripts/perkins/m/models.js.coffee +50 -0
- data/lib/perkins/assets/javascripts/perkins/router.js.coffee +10 -0
- data/lib/perkins/assets/javascripts/perkins/v/dashboard.js.coffee +17 -0
- data/lib/perkins/assets/javascripts/perkins/v/err.js.coffee +12 -0
- data/lib/perkins/assets/javascripts/perkins/v/menu.js.coffee +10 -0
- data/lib/perkins/assets/javascripts/perkins/v/my_repos.js.coffee +41 -0
- data/lib/perkins/assets/javascripts/perkins/v/orgs.js.coffee +39 -0
- data/lib/perkins/assets/javascripts/perkins/v/profile.js.coffee +20 -0
- data/lib/perkins/assets/javascripts/perkins/v/repo.js.coffee +192 -0
- data/lib/perkins/assets/javascripts/perkins/v/sidebar.js.coffee +33 -0
- data/lib/perkins/assets/javascripts/templates/dashboard.hamlc +11 -0
- data/lib/perkins/assets/javascripts/templates/error.hamlc +22 -0
- data/lib/perkins/assets/javascripts/templates/menu.hamlc +18 -0
- data/lib/perkins/assets/javascripts/templates/org.hamlc +77 -0
- data/lib/perkins/assets/javascripts/templates/profile.hamlc +28 -0
- data/lib/perkins/assets/javascripts/templates/repo.hamlc +37 -0
- data/lib/perkins/assets/javascripts/templates/repos/build_row.hamlc +19 -0
- data/lib/perkins/assets/javascripts/templates/repos/builds.hamlc +25 -0
- data/lib/perkins/assets/javascripts/templates/repos/config.hamlc +77 -0
- data/lib/perkins/assets/javascripts/templates/repos/gb_repo.hamlc +31 -0
- data/lib/perkins/assets/javascripts/templates/repos/github.hamlc +7 -0
- data/lib/perkins/assets/javascripts/templates/repos/menu.hamlc +17 -0
- data/lib/perkins/assets/javascripts/templates/repos/report_detail.hamlc +53 -0
- data/lib/perkins/assets/javascripts/templates/sidebar.hamlc +14 -0
- data/lib/perkins/assets/javascripts/templates/sidebar_repo.hamlc +4 -0
- data/lib/perkins/assets/javascripts/vendor/backbone-min.js +2 -0
- data/lib/perkins/assets/javascripts/vendor/backbone.marionette.js +2891 -0
- data/lib/perkins/assets/javascripts/vendor/hamlcoffee.js.coffee.erb +138 -0
- data/lib/perkins/assets/javascripts/vendor/livequery.jquery.js +8 -0
- data/lib/perkins/assets/javascripts/vendor/log.js +1 -1
- data/lib/perkins/assets/javascripts/vendor/md5.js +207 -0
- data/lib/perkins/assets/javascripts/vendor/nprogress.js +476 -0
- data/lib/perkins/assets/javascripts/vendor/underscore.js +6 -0
- data/lib/perkins/assets/stylesheets/app.css +3 -0
- data/lib/perkins/assets/stylesheets/bootstrap-overrides.css.scss +13 -0
- data/lib/perkins/assets/stylesheets/styles.css.scss +30 -3
- data/lib/perkins/assets/stylesheets/vendor/nprogress.css +74 -0
- data/lib/perkins/assets.rb +42 -0
- data/lib/perkins/build/script/ruby.rb +1 -1
- data/lib/perkins/build_report.rb +13 -0
- data/lib/perkins/{worker.rb → build_worker.rb} +9 -5
- data/lib/perkins/cli.rb +4 -2
- data/lib/perkins/commit.rb +8 -1
- data/lib/perkins/git_loader_worker.rb +29 -0
- data/lib/perkins/repo.rb +23 -9
- data/lib/perkins/runner.rb +16 -25
- data/lib/perkins/server.rb +121 -116
- data/lib/perkins/version.rb +1 -1
- data/lib/perkins/views/builds.haml +0 -3
- data/lib/perkins/views/layout.haml +25 -36
- data/lib/perkins/views/menu.haml +1 -1
- data/lib/perkins/views/repos/github.haml +0 -31
- data/lib/perkins/views/repos/repo.haml +1 -1
- data/lib/perkins.rb +4 -2
- data/perkins.gemspec +5 -2
- data/spec/lib/repo_spec.rb +27 -6
- data/spec/lib/runner_spec.rb +1 -0
- data/spec/lib/server_spec.rb +6 -23
- data/spec/spec_helper.rb +14 -3
- metadata +160 -70
- data/examples/config.rb +0 -12
- data/examples/mongo.yml +0 -13
- data/lib/perkins/listener.rb +0 -38
- data/spec/lib/listener_spec.rb +0 -30
data/lib/perkins/server.rb
CHANGED
|
@@ -9,48 +9,11 @@ require 'coffee_script'
|
|
|
9
9
|
require "sass"
|
|
10
10
|
require "rdiscount"
|
|
11
11
|
require "perkins/auth/github"
|
|
12
|
+
require "perkins/assets"
|
|
13
|
+
require "eventmachine"
|
|
12
14
|
|
|
13
15
|
module Perkins
|
|
14
16
|
|
|
15
|
-
class Assets < Sinatra::Base
|
|
16
|
-
|
|
17
|
-
configure do
|
|
18
|
-
set :assets, (Sprockets::Environment.new { |env|
|
|
19
|
-
env.append_path(settings.root + "/assets/images")
|
|
20
|
-
env.append_path(settings.root + "/assets/javascripts")
|
|
21
|
-
env.append_path(settings.root + "/assets/stylesheets")
|
|
22
|
-
# compress everything in production
|
|
23
|
-
if ENV["RACK_ENV"] == "production"
|
|
24
|
-
env.js_compressor = YUI::JavaScriptCompressor.new
|
|
25
|
-
env.css_compressor = YUI::CssCompressor.new
|
|
26
|
-
end
|
|
27
|
-
})
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
get "/assets/app.js" do
|
|
31
|
-
content_type("application/javascript")
|
|
32
|
-
settings.assets["app.js"]
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
get "/assets/app.css" do
|
|
36
|
-
content_type("text/css")
|
|
37
|
-
settings.assets["app.css"]
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
%w{jpg png}.each do |format|
|
|
41
|
-
get "/assets/:image.#{format}" do |image|
|
|
42
|
-
content_type("image/#{format}")
|
|
43
|
-
settings.assets["#{image}.#{format}"]
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
get "/assets/:image.svg" do |image|
|
|
48
|
-
content_type("image/svg+xml")
|
|
49
|
-
settings.assets["#{image}.svg"]
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
end
|
|
53
|
-
|
|
54
17
|
class Server < Sinatra::Application
|
|
55
18
|
|
|
56
19
|
attr_reader :app
|
|
@@ -61,12 +24,30 @@ module Perkins
|
|
|
61
24
|
#set :environment, :production
|
|
62
25
|
set :session_secret, '*&(^B234'
|
|
63
26
|
|
|
27
|
+
configure :development do
|
|
28
|
+
#register Sinatra::Reloader
|
|
29
|
+
end
|
|
30
|
+
|
|
64
31
|
use Perkins::Assets
|
|
65
32
|
|
|
66
33
|
register Perkins::Auth::Github
|
|
67
34
|
|
|
35
|
+
#authenticate all -
|
|
36
|
+
before do
|
|
37
|
+
unless %w[stream sse logout unauthenticated /auth/github/callback /repos/receiver badge].include? request.path_info.split('/')[1]
|
|
38
|
+
authenticate!
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
#render index if not ajax request!
|
|
43
|
+
before do
|
|
44
|
+
return if %w[stream sse logout unauthenticated /auth/github/callback /repos/receiver badge config].include? request.path_info.split('/')[1]
|
|
45
|
+
unless request.xhr?
|
|
46
|
+
halt 200, haml( :index , locals: default_data)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
68
50
|
get '/' do
|
|
69
|
-
authenticate!
|
|
70
51
|
haml :index , locals: default_data
|
|
71
52
|
end
|
|
72
53
|
|
|
@@ -74,19 +55,23 @@ module Perkins
|
|
|
74
55
|
settings.perkins_application.to_json
|
|
75
56
|
end
|
|
76
57
|
|
|
77
|
-
get '/repos/sync' do
|
|
78
|
-
|
|
58
|
+
#get '/repos/sync' do
|
|
59
|
+
# @github_repos = build_data
|
|
60
|
+
#end
|
|
61
|
+
|
|
62
|
+
get '/repos' do
|
|
63
|
+
content_type :json
|
|
64
|
+
repos = Perkins::Repo.added.all
|
|
65
|
+
repos.to_json
|
|
79
66
|
end
|
|
80
67
|
|
|
81
68
|
post '/repos/receiver' do
|
|
82
69
|
#NEEDS VALIDATIONS
|
|
83
70
|
payload = JSON.parse request.body.read
|
|
84
71
|
repo = Perkins::Repo.added.find_by(gb_id: payload["repository"]["id"])
|
|
85
|
-
repo.load_git
|
|
86
|
-
|
|
72
|
+
#repo.load_git
|
|
87
73
|
pushed_branch = payload["ref"].split('/').last
|
|
88
74
|
repo.add_commit(payload["after"], pushed_branch)
|
|
89
|
-
#binding.pry
|
|
90
75
|
"received post #{payload}"
|
|
91
76
|
end
|
|
92
77
|
|
|
@@ -96,42 +81,57 @@ module Perkins
|
|
|
96
81
|
Repo.sync_github_repo(repo)
|
|
97
82
|
r = Repo.add_from_github(params[:id])
|
|
98
83
|
r.to_json
|
|
99
|
-
redirect "/me"
|
|
100
84
|
end
|
|
101
85
|
|
|
102
86
|
get '/repos/:login/:name' do
|
|
87
|
+
content_type :json
|
|
103
88
|
repo = find_repo(params)
|
|
104
|
-
|
|
105
|
-
|
|
89
|
+
#detects a recently added repo (no dir and no prev builds)
|
|
90
|
+
enqueue_git_clone(repo) if !repo.exists? && repo.last_report_id.blank?
|
|
91
|
+
repo.as_json(methods: [:last_report_id, :http_url]).to_json
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
get '/badge' do
|
|
95
|
+
content_type "image/svg+xml"
|
|
96
|
+
repo = Repo.find_by(name: params[:repo])
|
|
97
|
+
build = repo.build_reports.last
|
|
98
|
+
request_badge({status: build.status ? "passing" : "error" , color: build.status ? "green" : "red" })
|
|
106
99
|
end
|
|
107
100
|
|
|
108
101
|
get '/repos/:login/:name/builds' do
|
|
102
|
+
content_type :json
|
|
109
103
|
repo = find_repo(params)
|
|
110
|
-
|
|
104
|
+
#respond or delay git load
|
|
105
|
+
repo.exists? ? repo.build_reports.to_json : enqueue_git_clone(repo)
|
|
111
106
|
end
|
|
112
107
|
|
|
113
108
|
get '/repos/:login/:name/builds/:build_id' do
|
|
109
|
+
content_type :json
|
|
114
110
|
repo = find_repo(params)
|
|
115
111
|
record = repo.build_reports.find(params[:build_id])
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
get '/repos/:login/:name/run_commit' do
|
|
121
|
-
repo = find_repo(params)
|
|
122
|
-
sha = repo.git.log.map(&:sha).first
|
|
123
|
-
repo.add_commit(sha, "master")
|
|
124
|
-
redirect "/repos/#{repo.name}"
|
|
112
|
+
#record.to_json
|
|
113
|
+
repo.exists? ? record.to_json : enqueue_git_clone(repo)
|
|
125
114
|
end
|
|
126
115
|
|
|
127
116
|
get '/repos/:login/:name/config' do
|
|
117
|
+
content_type :json
|
|
128
118
|
repo = find_repo(params)
|
|
129
119
|
#find by id
|
|
130
120
|
hook = github_user.api.hooks("#{repo.name}").detect{|o| o[:name] == "web"}
|
|
121
|
+
hook.to_attrs.to_json
|
|
122
|
+
end
|
|
131
123
|
|
|
132
|
-
|
|
124
|
+
#TODO send this through bg job
|
|
125
|
+
get '/repos/:login/:name/run_commit' do
|
|
126
|
+
content_type :json
|
|
127
|
+
repo = find_repo(params)
|
|
128
|
+
repo.load_git
|
|
129
|
+
sha = repo.git.log.map(&:sha).first
|
|
130
|
+
repo.add_commit(sha, "master")
|
|
131
|
+
repo.to_json
|
|
133
132
|
end
|
|
134
133
|
|
|
134
|
+
#TODO for json
|
|
135
135
|
post '/repos/:login/:name/add_hook' do
|
|
136
136
|
repo = find_repo(params)
|
|
137
137
|
hook = github_user.api.hooks("#{repo.name}").detect{|o| o[:name] == "web"}
|
|
@@ -155,56 +155,52 @@ module Perkins
|
|
|
155
155
|
end
|
|
156
156
|
|
|
157
157
|
get '/repos/:login/:name/builds/:build_id/restart' do
|
|
158
|
+
content_type :json
|
|
158
159
|
repo = find_repo(params)
|
|
160
|
+
#repo.load_git
|
|
159
161
|
record = repo.build_reports.find(params[:build_id])
|
|
160
162
|
repo.add_commit(record['sha'], record['branch'])
|
|
161
|
-
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
get '/stream', provides: 'text/event-stream' do
|
|
165
|
-
stream :keep_open do |out|
|
|
166
|
-
settings.connections << out
|
|
167
|
-
out.callback { settings.connections.delete(out) }
|
|
168
|
-
end
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
post '/sse' do
|
|
172
|
-
settings.connections.each { |out| out << "data: #{params[:msg]}\n\n" }
|
|
173
|
-
204 # response without entity body
|
|
163
|
+
record.to_json
|
|
174
164
|
end
|
|
175
165
|
|
|
176
166
|
get '/me' do
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
#"Hello There, #{github_user.name}! You have access to the #{params['id']} organization."
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
get '/myrepos' do
|
|
186
|
-
authenticate!
|
|
187
|
-
repos = github_user.api.repos
|
|
188
|
-
haml :"repos/github", locals: { user: github_user.api, repos: repos }
|
|
167
|
+
content_type :json
|
|
168
|
+
a = github_user.api
|
|
169
|
+
@user = a.user
|
|
170
|
+
@orgs = a.orgs.map(&:login)
|
|
171
|
+
@user.to_attrs.merge({orgs: @orgs}).to_json
|
|
189
172
|
end
|
|
190
173
|
|
|
191
174
|
get '/orgs/:id' do
|
|
175
|
+
content_type :json
|
|
192
176
|
github_organization_authenticate!(params['id'])
|
|
193
|
-
#"Hello There, #{github_user.name}! You have access to the #{params['id']} organization."
|
|
194
177
|
org = github_user.api.organization(params['id'])
|
|
195
|
-
orgs = github_user.api.orgs
|
|
196
|
-
repos = github_user.api.org_repos(params["id"])
|
|
197
|
-
|
|
178
|
+
#orgs = github_user.api.orgs
|
|
179
|
+
repos = github_user.api.org_repos(params["id"]).map(&:to_attrs)
|
|
180
|
+
org.to_attrs.merge({repos: repos}).to_json
|
|
198
181
|
end
|
|
199
182
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
183
|
+
#TODO for json
|
|
184
|
+
get '/myrepos' do
|
|
185
|
+
repos = github_user.api.repos.map(&:to_attrs)
|
|
186
|
+
github_user.api.user.to_attrs.merge({repos: repos}).to_json
|
|
203
187
|
end
|
|
204
188
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
189
|
+
|
|
190
|
+
get '/stream', provides: 'text/event-stream' do
|
|
191
|
+
stream :keep_open do |out|
|
|
192
|
+
#EM.run {
|
|
193
|
+
# EventMachine::PeriodicTimer.new(20) { out << "data: \n\n" } # added
|
|
194
|
+
#}
|
|
195
|
+
settings.connections << out
|
|
196
|
+
out.callback { settings.connections.delete(out) }
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
post '/sse' do
|
|
201
|
+
puts "connections #{settings.connections.size}".yellow
|
|
202
|
+
settings.connections.each { |out| out << "data: #{params[:msg]}\n\n" }
|
|
203
|
+
204 # response without entity body
|
|
208
204
|
end
|
|
209
205
|
|
|
210
206
|
get '/logout' do
|
|
@@ -212,11 +208,17 @@ module Perkins
|
|
|
212
208
|
redirect 'https://github.com'
|
|
213
209
|
end
|
|
214
210
|
|
|
215
|
-
def initialize(
|
|
211
|
+
def initialize(args={})
|
|
216
212
|
super
|
|
217
|
-
|
|
218
|
-
#
|
|
219
|
-
|
|
213
|
+
return if args.blank?
|
|
214
|
+
puts "PerkinsCI environment loaded on #{args[:host]}:#{args[:port]}".green
|
|
215
|
+
app = Perkins::Application.instance
|
|
216
|
+
self.class.set :perkins_application, app
|
|
217
|
+
self.class.set :github_options, {
|
|
218
|
+
:scopes => "admin:repo_hook,repo,user:email",
|
|
219
|
+
:secret => app.github_client_secret,
|
|
220
|
+
:client_id => app.github_client_id,
|
|
221
|
+
}
|
|
220
222
|
end
|
|
221
223
|
|
|
222
224
|
def github_repos
|
|
@@ -235,26 +237,32 @@ module Perkins
|
|
|
235
237
|
def find_repo(params)
|
|
236
238
|
id = "#{params[:login]}/#{params[:name]}"
|
|
237
239
|
repo = Repo.find_by(name: id)
|
|
238
|
-
repo.load_git
|
|
240
|
+
#repo.load_git #it seems that we dont need this here
|
|
239
241
|
repo
|
|
240
242
|
end
|
|
241
243
|
|
|
242
|
-
def
|
|
244
|
+
def enqueue_git_clone(repo)
|
|
245
|
+
GitLoaderWorker.perform_async(repo.id )
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def request_badge(opts={})
|
|
249
|
+
begin
|
|
250
|
+
url = URI.parse("https://img.shields.io/badge/build-#{opts[:status]}-#{opts[:color]}.svg?style=flat-square")
|
|
251
|
+
result = Net::HTTP.get(url)
|
|
252
|
+
rescue => e
|
|
253
|
+
e
|
|
254
|
+
end
|
|
255
|
+
end
|
|
243
256
|
|
|
257
|
+
####################################
|
|
258
|
+
#TODO: deprecate this
|
|
259
|
+
def self.start(app, options)
|
|
244
260
|
options = options.dup
|
|
245
261
|
ENV['RACK_ENV'] = options.delete("e")
|
|
246
262
|
|
|
247
|
-
app = eval(File.open(config_file).read)
|
|
248
|
-
self.start_listener(app)
|
|
249
|
-
|
|
250
|
-
set :perkins_application, app
|
|
251
|
-
set :github_options, {
|
|
252
|
-
:scopes => "admin:repo_hook,repo,user:email",
|
|
253
|
-
:secret => app.github_client_secret,
|
|
254
|
-
:client_id => app.github_client_id,
|
|
255
|
-
}
|
|
256
|
-
|
|
257
263
|
register Sinatra::ActiveRecordExtension
|
|
264
|
+
app = app.is_a?(String) ? eval(File.open(app).read) : app
|
|
265
|
+
self.start_listener(app)
|
|
258
266
|
|
|
259
267
|
configure :development do
|
|
260
268
|
#register Sinatra::Reloader
|
|
@@ -269,7 +277,8 @@ module Perkins
|
|
|
269
277
|
#set :database, 'sqlite:///db/test.sqlite3'
|
|
270
278
|
end
|
|
271
279
|
|
|
272
|
-
Perkins::Server.run!
|
|
280
|
+
#::Perkins::Server.run!(options)
|
|
281
|
+
|
|
273
282
|
end
|
|
274
283
|
|
|
275
284
|
def self.start_listener(app_config)
|
|
@@ -279,11 +288,8 @@ module Perkins
|
|
|
279
288
|
listener.run!
|
|
280
289
|
end
|
|
281
290
|
end
|
|
291
|
+
####################################
|
|
282
292
|
|
|
283
|
-
##use in rack
|
|
284
|
-
##And a corresponding config.ru:
|
|
285
|
-
#require './app'
|
|
286
|
-
#run Sinatra::Application
|
|
287
293
|
def default_data
|
|
288
294
|
{author: "miguel michelson", year: Time.now.year, app: @app}
|
|
289
295
|
end
|
|
@@ -299,7 +305,6 @@ module Perkins
|
|
|
299
305
|
status ? "glyphicon glyphicon-ok" : "glyphicon glyphicon-remove"
|
|
300
306
|
end
|
|
301
307
|
|
|
302
|
-
|
|
303
308
|
def avatar_url(email, size)
|
|
304
309
|
gravatar_id = Digest::MD5.hexdigest(email.downcase)
|
|
305
310
|
"http://gravatar.com/avatar/#{gravatar_id}.png?s=#{size}"
|
data/lib/perkins/version.rb
CHANGED
|
@@ -15,39 +15,28 @@
|
|
|
15
15
|
minispade.require('log')
|
|
16
16
|
|
|
17
17
|
%body
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
.clearfix
|
|
45
|
-
#footer
|
|
46
|
-
-#= render 'footer'
|
|
47
|
-
.pull-right
|
|
48
|
-
Copyright © #{Time.now.year} Perkins
|
|
49
|
-
%strong
|
|
50
|
-
Redis connection:
|
|
51
|
-
%span
|
|
52
|
-
= $redis.client.host
|
|
53
|
-
= $redis.client.port
|
|
18
|
+
#perkins-layout
|
|
19
|
+
%nav#main-menu.navbar.navbar-fixed-top{role:"navigation"}
|
|
20
|
+
|
|
21
|
+
-#= haml :menu
|
|
22
|
+
|
|
23
|
+
.container
|
|
24
|
+
#content
|
|
25
|
+
#left-wrap.col-sm-3
|
|
26
|
+
#sidebar.affix.col-sm-3
|
|
27
|
+
|
|
28
|
+
#main-content.col-sm-9
|
|
29
|
+
-#= yield
|
|
30
|
+
|
|
31
|
+
#inner
|
|
32
|
+
|
|
33
|
+
.clearfix
|
|
34
|
+
#footer
|
|
35
|
+
-#= render 'footer'
|
|
36
|
+
.pull-right
|
|
37
|
+
Copyright © #{Time.now.year} Perkins
|
|
38
|
+
%strong
|
|
39
|
+
Redis connection:
|
|
40
|
+
%span
|
|
41
|
+
= $redis.client.host
|
|
42
|
+
= $redis.client.port
|
data/lib/perkins/views/menu.haml
CHANGED
|
@@ -6,37 +6,6 @@
|
|
|
6
6
|
%span.glyphicon.glyphicon-refresh
|
|
7
7
|
SYNC
|
|
8
8
|
|
|
9
|
-
-#
|
|
10
|
-
- repos.each do |repo|
|
|
11
|
-
%ul.list-group
|
|
12
|
-
%li.list-group-item
|
|
13
|
-
|
|
14
|
-
.pull-right
|
|
15
|
-
%a.btn{href: "/repos/add/#{repo.gb_id}"}
|
|
16
|
-
ADD REPO
|
|
17
|
-
%span.btn.glyphicon.glyphicon-plus-sign
|
|
18
|
-
|
|
19
|
-
.row
|
|
20
|
-
%span.col-sm-1
|
|
21
|
-
%a{src: repo.github_data["owner"]["url"] }
|
|
22
|
-
%img{ src: repo.github_data["owner"]["avatar_url"], width: 66 }
|
|
23
|
-
%span.col-sm-8
|
|
24
|
-
%h4= repo.name
|
|
25
|
-
%a{href: repo.url}
|
|
26
|
-
view on github
|
|
27
|
-
%p
|
|
28
|
-
.clearfix
|
|
29
|
-
.well
|
|
30
|
-
%p= repo.github_data["description"]
|
|
31
|
-
-#
|
|
32
|
-
%p
|
|
33
|
-
clone url:
|
|
34
|
-
= repo.github_data["clone_url"]
|
|
35
|
-
|
|
36
|
-
%span
|
|
37
|
-
= repo.github_data["fork"]
|
|
38
|
-
= repo.github_data["private"]
|
|
39
|
-
|
|
40
9
|
- if repos.any?
|
|
41
10
|
%h2 Repositories:
|
|
42
11
|
|
data/lib/perkins.rb
CHANGED
|
@@ -7,12 +7,14 @@ require 'redis'
|
|
|
7
7
|
require 'redis-namespace'
|
|
8
8
|
require "travis/yaml"
|
|
9
9
|
require "active_record"
|
|
10
|
+
require "sidekiq"
|
|
10
11
|
|
|
11
12
|
require 'dotenv'
|
|
12
13
|
Dotenv.load
|
|
13
14
|
require 'octokit'
|
|
14
15
|
Octokit.auto_paginate = true
|
|
15
16
|
#require 'core_ext/hash/deep_symbolize_keys'
|
|
17
|
+
require 'core_ext/string/color'
|
|
16
18
|
|
|
17
19
|
module Perkins
|
|
18
20
|
autoload :VERSION, 'perkins/version.rb'
|
|
@@ -22,8 +24,8 @@ module Perkins
|
|
|
22
24
|
autoload :Build, 'perkins/build.rb'
|
|
23
25
|
autoload :Commit, 'perkins/commit.rb'
|
|
24
26
|
autoload :Server, 'perkins/server.rb'
|
|
25
|
-
autoload :
|
|
26
|
-
autoload :
|
|
27
|
+
autoload :BuildWorker, 'perkins/build_worker.rb'
|
|
28
|
+
autoload :GitLoaderWorker, 'perkins/git_loader_worker.rb'
|
|
27
29
|
autoload :ThorUtils, 'perkins/thor_utils.rb'
|
|
28
30
|
autoload :Logger, 'perkins/logger.rb'
|
|
29
31
|
autoload :Application, 'perkins/application.rb'
|
data/perkins.gemspec
CHANGED
|
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
|
|
|
8
8
|
spec.version = Perkins::VERSION
|
|
9
9
|
spec.authors = ["miguel michelson"]
|
|
10
10
|
spec.email = ["miguelmichelson@gmail.com"]
|
|
11
|
-
spec.summary = "
|
|
12
|
-
spec.description = "
|
|
11
|
+
spec.summary = "A travis compatible standalone CI solution for ruby"
|
|
12
|
+
spec.description = "Continous integration solution compatible with travis.ci"
|
|
13
13
|
spec.homepage = ""
|
|
14
14
|
spec.license = "MIT"
|
|
15
15
|
|
|
@@ -33,11 +33,14 @@ Gem::Specification.new do |spec|
|
|
|
33
33
|
spec.add_runtime_dependency("sinatra")
|
|
34
34
|
spec.add_runtime_dependency("haml")
|
|
35
35
|
spec.add_runtime_dependency("sprockets")
|
|
36
|
+
spec.add_runtime_dependency("haml_coffee_assets")
|
|
36
37
|
spec.add_runtime_dependency("yui-compressor")
|
|
37
38
|
spec.add_runtime_dependency("rdiscount")
|
|
38
39
|
spec.add_runtime_dependency("travis-yaml")
|
|
39
40
|
spec.add_runtime_dependency("redis-namespace")
|
|
40
41
|
spec.add_runtime_dependency("thin")
|
|
42
|
+
spec.add_runtime_dependency("sidekiq")
|
|
43
|
+
spec.add_runtime_dependency("dotenv-rails")
|
|
41
44
|
|
|
42
45
|
spec.add_dependency "warden-github", "~>1.0"
|
|
43
46
|
|
data/spec/lib/repo_spec.rb
CHANGED
|
@@ -47,6 +47,22 @@ describe "Repo" do
|
|
|
47
47
|
#expect(r.local_path).to_not be_blank
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
+
context "load git" do
|
|
51
|
+
before :each do
|
|
52
|
+
@repo = Perkins::Repo.first
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "will not be downloaded" do
|
|
56
|
+
expect(@repo.download_status).to be_blank
|
|
57
|
+
expect(@repo.downloaded?).to be == false
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "will be downloaded after load_git" do
|
|
61
|
+
@repo.load_git
|
|
62
|
+
expect(@repo.downloaded?).to be == true
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
50
66
|
context "loaded repo" do
|
|
51
67
|
before :each do
|
|
52
68
|
@repo = Perkins::Repo.first
|
|
@@ -56,7 +72,7 @@ describe "Repo" do
|
|
|
56
72
|
end
|
|
57
73
|
|
|
58
74
|
it "should download repo" do
|
|
59
|
-
expect(File.
|
|
75
|
+
expect(File.exist?(@path)).to be_present
|
|
60
76
|
end
|
|
61
77
|
|
|
62
78
|
it "should have a default runner" do
|
|
@@ -82,11 +98,15 @@ describe "Repo" do
|
|
|
82
98
|
expect(@repo.runner).to be_instance_of(Perkins::Runner)
|
|
83
99
|
end
|
|
84
100
|
|
|
85
|
-
it "
|
|
101
|
+
it "runner true" do
|
|
86
102
|
sha = @repo.git.log.map(&:sha).first
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
103
|
+
allow_any_instance_of(Perkins::Runner).to receive(:run_script).and_return("stubbed")
|
|
104
|
+
allow_any_instance_of(Perkins::Runner).to receive(:successful_command?).and_return(true)
|
|
105
|
+
runner = @repo.runner
|
|
106
|
+
runner.run(sha)
|
|
107
|
+
expect(runner.response).to be == "stubbed"
|
|
108
|
+
expect(runner.status).to be == true
|
|
109
|
+
expect(@repo.build_status).to be == "stopped"
|
|
90
110
|
end
|
|
91
111
|
end
|
|
92
112
|
|
|
@@ -99,10 +119,11 @@ describe "Repo" do
|
|
|
99
119
|
@path = @repo.git.dir.path
|
|
100
120
|
end
|
|
101
121
|
|
|
102
|
-
it "receive commit" do
|
|
122
|
+
it "will increment Worker jobs when receive commit " do
|
|
103
123
|
sha = @repo.git.log.map(&:sha).first
|
|
104
124
|
@repo.add_commit(sha, "master")
|
|
105
125
|
expect(@repo.new_commit).to be_instance_of(Perkins::Commit)
|
|
126
|
+
expect(Perkins::Worker.jobs.size).to be > 0
|
|
106
127
|
end
|
|
107
128
|
|
|
108
129
|
end
|
data/spec/lib/runner_spec.rb
CHANGED
data/spec/lib/server_spec.rb
CHANGED
|
@@ -55,36 +55,18 @@ describe 'Server App' do
|
|
|
55
55
|
it "profile" do
|
|
56
56
|
allow_any_instance_of(Warden::GitHub::User).to receive(:api).and_return(user_api)
|
|
57
57
|
get "/me"
|
|
58
|
-
#puts last_response.body
|
|
59
58
|
expect(last_response).to be_ok
|
|
60
59
|
end
|
|
61
60
|
|
|
62
61
|
describe "github" do
|
|
63
62
|
|
|
64
|
-
it "sync" do
|
|
65
|
-
|
|
66
|
-
allow_any_instance_of(Warden::GitHub::User).to receive(:api).and_return(user_api)
|
|
67
|
-
|
|
68
|
-
get "/repos/sync"
|
|
69
|
-
|
|
70
|
-
follow_redirect!
|
|
71
|
-
|
|
72
|
-
expect("http://example.org/me").to be == last_request.url
|
|
73
|
-
|
|
74
|
-
expect(last_response).to be_ok
|
|
75
|
-
|
|
76
|
-
expect(Perkins::Repo.synced_records).to be_any
|
|
77
|
-
end
|
|
78
|
-
|
|
79
63
|
it "add repo" do
|
|
80
64
|
allow_any_instance_of(Warden::GitHub::User).to receive(:api).and_return(user_api)
|
|
81
65
|
a = Warden::GitHub::User.new
|
|
82
66
|
Perkins::Repo.sync_github_repos(a)
|
|
83
67
|
repo = Perkins::Repo.synced_records.first
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
expect("http://example.org/me").to be == last_request.url
|
|
87
|
-
expect(last_response).to be_ok
|
|
68
|
+
xhr("/repos/add/#{repo.gb_id}")
|
|
69
|
+
expect(last_response.body).to be == "true"
|
|
88
70
|
expect(Perkins::Repo.find(repo.id).github_data).to_not be_blank
|
|
89
71
|
end
|
|
90
72
|
|
|
@@ -92,9 +74,10 @@ describe 'Server App' do
|
|
|
92
74
|
allow_any_instance_of(Warden::GitHub::User).to receive(:api).and_return(user_api)
|
|
93
75
|
a = Warden::GitHub::User.new
|
|
94
76
|
Perkins::Repo.sync_github_repos(a)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
77
|
+
repo = Perkins::Repo.synced_records.first
|
|
78
|
+
allow_any_instance_of(Perkins::Server).to receive(:find_repo).and_return(repo)
|
|
79
|
+
xhr "/repos/name/any_repo"
|
|
80
|
+
expect(last_response.body).to include(repo.name)
|
|
98
81
|
end
|
|
99
82
|
|
|
100
83
|
it "receive hook" do
|