juici 0.0.0.alpha1 → 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -4
- data/Gemfile.lock +9 -19
- data/README.md +6 -45
- data/Rakefile +0 -24
- data/config/mongoid.yml.sample +5 -20
- data/juici.gemspec +3 -7
- data/lib/juici.rb +3 -8
- data/lib/juici/app.rb +23 -19
- data/lib/juici/build_environment.rb +1 -1
- data/lib/juici/build_logic.rb +1 -10
- data/lib/juici/build_queue.rb +3 -30
- data/lib/juici/callback.rb +5 -9
- data/lib/juici/config.rb +0 -4
- data/lib/juici/controllers/build_controller.rb +0 -0
- data/lib/juici/controllers/{trigger.rb → trigger_controller.rb} +5 -24
- data/lib/juici/database.rb +13 -19
- data/lib/juici/helpers/url_helpers.rb +0 -28
- data/lib/juici/models/build.rb +24 -81
- data/lib/juici/models/project.rb +1 -1
- data/lib/juici/server.rb +40 -103
- data/lib/juici/url_helpers.rb +15 -0
- data/lib/juici/views/README.markdown +6 -45
- data/lib/juici/views/about.erb +5 -5
- data/lib/juici/views/builds/list.erb +33 -26
- data/lib/juici/views/builds/new.erb +37 -42
- data/lib/juici/views/builds/show.erb +28 -4
- data/lib/juici/views/index.erb +13 -30
- data/lib/juici/views/layout.erb +13 -22
- data/lib/juici/views/partials/builds/debug.erb +18 -12
- data/lib/juici/watcher.rb +25 -33
- data/public/styles/builds.css +8 -59
- data/public/styles/juici.css +2 -226
- data/spec/build_callback_spec.rb +1 -46
- data/spec/build_process_spec.rb +5 -71
- data/spec/build_queue_spec.rb +1 -3
- data/spec/juici_app_spec.rb +15 -0
- data/spec/spec_helper.rb +0 -13
- metadata +12 -76
- data/.gitignore +0 -2
- data/bin/juicic +0 -54
- data/juici-interface.gemspec +0 -19
- data/lib/juici/controllers.rb +0 -6
- data/lib/juici/controllers/base.rb +0 -26
- data/lib/juici/controllers/build_queue.rb +0 -14
- data/lib/juici/controllers/builds.rb +0 -74
- data/lib/juici/controllers/index.rb +0 -20
- data/lib/juici/exceptions.rb +0 -2
- data/lib/juici/find_logic.rb +0 -11
- data/lib/juici/helpers/form_helpers.rb +0 -11
- data/lib/juici/helpers/html_helpers.rb +0 -4
- data/lib/juici/interface.rb +0 -13
- data/lib/juici/version.rb +0 -8
- data/lib/juici/views/builds/edit.erb +0 -23
- data/lib/juici/views/not_found.erb +0 -3
- data/lib/juici/views/partials/builds/output.erb +0 -1
- data/lib/juici/views/partials/builds/show.erb +0 -19
- data/lib/juici/views/partials/builds/sidebar.erb +0 -13
- data/lib/juici/views/partials/index/recently_built.erb +0 -19
- data/lib/juici/views/queue/list.erb +0 -6
- data/public/favicon.ico +0 -0
- data/public/images/black_denim.png +0 -0
- data/public/vendor/bootstrap.css +0 -6004
- data/public/vendor/bootstrap.js +0 -2036
- data/public/vendor/img/glyphicons-halflings-white.png +0 -0
- data/public/vendor/jquery.js +0 -9440
- data/script/cibuild +0 -10
- data/spec/controllers/builds_spec.rb +0 -68
- data/spec/controllers/index_spec.rb +0 -28
- data/spec/models/build_spec.rb +0 -54
data/lib/juici/config.rb
CHANGED
File without changes
|
@@ -1,31 +1,15 @@
|
|
1
|
-
module Juici
|
2
|
-
class
|
1
|
+
module Juici
|
2
|
+
class TriggerController
|
3
3
|
|
4
4
|
attr_reader :project, :params
|
5
5
|
def initialize(project, params)
|
6
|
-
@project =
|
6
|
+
@project = Project.find_or_create_by(name: project)
|
7
7
|
@params = params
|
8
8
|
end
|
9
9
|
|
10
|
-
# Find an existing build, duplicate the sane parts of it.
|
11
|
-
def rebuild!
|
12
|
-
unless project = ::Juici::Project.where(name: params[:project]).first
|
13
|
-
not_found
|
14
|
-
end
|
15
|
-
unless build = ::Juici::Build.where(parent: project.name, _id: params[:id]).first
|
16
|
-
not_found
|
17
|
-
end
|
18
|
-
|
19
|
-
::Juici::Build.new_from(build).tap do |new_build|
|
20
|
-
new_build.save!
|
21
|
-
$build_queue << new_build
|
22
|
-
$build_queue.bump!
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
10
|
def build!
|
27
|
-
environment =
|
28
|
-
|
11
|
+
environment = BuildEnvironment.new
|
12
|
+
Build.new(parent: project.name).tap do |build|
|
29
13
|
# The seperation of concerns around this madness is horrifying
|
30
14
|
unless environment.load_json!(params['environment'])
|
31
15
|
build.warn!("Failed to parse environment")
|
@@ -52,9 +36,6 @@ module Juici::Controllers
|
|
52
36
|
# TODO Throw 422 not acceptable if missing
|
53
37
|
params['command'].tap do |c|
|
54
38
|
raise "No command given" if c.nil?
|
55
|
-
# TODO Detect that we've recieved this from a browser session and only
|
56
|
-
# do this replacement there, we can trust API supplied data.
|
57
|
-
c.gsub!(/\r\n/, "\n")
|
58
39
|
end
|
59
40
|
end
|
60
41
|
|
data/lib/juici/database.rb
CHANGED
@@ -1,25 +1,19 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
path = File.join("config", file)
|
8
|
-
return path if File.exist?(path)
|
9
|
-
end
|
10
|
-
raise "No database config file"
|
1
|
+
class Juici::Database
|
2
|
+
class << self
|
3
|
+
def mongoid_config_file
|
4
|
+
%w[mongoid.yml mongoid.yml.sample].each do |file|
|
5
|
+
path = File.join("config", file)
|
6
|
+
return path if File.exist?(path)
|
11
7
|
end
|
8
|
+
raise "No database config file"
|
9
|
+
end
|
12
10
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
17
|
-
if ENV['RACK_ENV'] == "development"
|
18
|
-
Mongoid.logger.level = Logger::INFO
|
19
|
-
end
|
20
|
-
|
21
|
-
Mongoid.load!(mongoid_config_file)
|
11
|
+
def initialize!
|
12
|
+
if ENV['RACK_ENV'] == "development"
|
13
|
+
Mongoid.logger.level = Logger::INFO
|
22
14
|
end
|
15
|
+
|
16
|
+
Mongoid.load!(mongoid_config_file)
|
23
17
|
end
|
24
18
|
end
|
25
19
|
end
|
@@ -8,31 +8,3 @@ def build_url_for(entity)
|
|
8
8
|
"/builds/#{entity[:parent]}/show/#{entity[:_id]}"
|
9
9
|
end
|
10
10
|
end
|
11
|
-
|
12
|
-
def rebuild_url_for(entity)
|
13
|
-
URI.escape case entity
|
14
|
-
when ::Juici::Build
|
15
|
-
"/builds/#{entity[:parent]}/rebuild/#{entity[:_id]}"
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def kill_url_for(entity)
|
20
|
-
URI.escape case entity
|
21
|
-
when ::Juici::Build
|
22
|
-
"/builds/kill"
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def cancel_url_for(entity)
|
27
|
-
URI.escape case entity
|
28
|
-
when ::Juici::Build
|
29
|
-
"/builds/cancel"
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def edit_url_for(entity)
|
34
|
-
URI.escape case entity
|
35
|
-
when ::Juici::Build
|
36
|
-
"/builds/#{entity[:parent]}/edit/#{entity[:_id]}"
|
37
|
-
end
|
38
|
-
end
|
data/lib/juici/models/build.rb
CHANGED
@@ -1,43 +1,29 @@
|
|
1
1
|
require 'json'
|
2
|
-
|
2
|
+
# status enum
|
3
|
+
# :waiting
|
4
|
+
# :started
|
5
|
+
# :failed
|
6
|
+
# :success
|
7
|
+
#
|
8
|
+
# ???
|
9
|
+
# :profit!
|
10
|
+
#
|
3
11
|
module Juici
|
4
12
|
class Build
|
5
13
|
# A wrapper around the build process
|
6
14
|
|
7
15
|
include Mongoid::Document
|
16
|
+
include ::Juici.url_helpers("builds")
|
8
17
|
include BuildLogic
|
9
|
-
include BuildStatus
|
10
|
-
extend FindLogic
|
11
18
|
# TODO Builds should probably be children of projects in the URL?
|
12
19
|
|
13
|
-
# Finder classmethods
|
14
|
-
def self.get_recent(n, opts={})
|
15
|
-
self.where(opts).
|
16
|
-
limit(n).
|
17
|
-
desc(:_id)
|
18
|
-
end
|
19
|
-
|
20
|
-
CLONABLE_FIELDS = [:command, :priority, :environment, :callbacks, :title, :parent]
|
21
|
-
EDITABLE_ATTRIBUTES = {
|
22
|
-
:string => [:priority, :title],
|
23
|
-
:array => [:environment, :callbacks]
|
24
|
-
}
|
25
|
-
|
26
|
-
def self.new_from(other)
|
27
|
-
new.tap do |b|
|
28
|
-
CLONABLE_FIELDS.each do |prop|
|
29
|
-
b[prop] = other[prop]
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
20
|
field :parent, type: String
|
35
21
|
field :command, type: String
|
36
22
|
field :environment, type: Hash
|
37
23
|
field :create_time, type: Time, :default => Proc.new { Time.now }
|
38
24
|
field :start_time, type: Time, :default => nil
|
39
25
|
field :end_time, type: Time, :default => nil
|
40
|
-
field :status, type: Symbol, :default =>
|
26
|
+
field :status, type: Symbol, :default => :waiting
|
41
27
|
field :priority, type: Fixnum, :default => 1
|
42
28
|
field :pid, type: Fixnum
|
43
29
|
field :buffer, type: String
|
@@ -46,43 +32,37 @@ module Juici
|
|
46
32
|
field :title, type: String, :default => Proc.new { Time.now.to_s }
|
47
33
|
|
48
34
|
def set_status(value)
|
49
|
-
self
|
35
|
+
self[:status] = value
|
50
36
|
save!
|
51
37
|
end
|
52
38
|
|
53
39
|
def start!
|
54
40
|
self[:start_time] = Time.now
|
55
|
-
set_status
|
41
|
+
set_status :started
|
56
42
|
end
|
57
43
|
|
58
44
|
def success!
|
59
45
|
finish
|
60
|
-
set_status
|
46
|
+
set_status :success
|
61
47
|
process_callbacks
|
62
48
|
end
|
63
49
|
|
64
50
|
def failure!
|
65
51
|
finish
|
66
|
-
set_status
|
52
|
+
set_status :failed
|
67
53
|
process_callbacks
|
68
54
|
end
|
69
55
|
|
70
56
|
def finish
|
71
57
|
self[:end_time] = Time.now
|
72
58
|
self[:output] = get_output
|
73
|
-
$build_queue.purge(:pid, self)
|
74
|
-
end
|
75
|
-
|
76
|
-
def cancel
|
77
|
-
warn! "Cancelled"
|
78
|
-
set_status FAIL
|
79
|
-
$build_queue.delete(self[:_id]) if $build_queue
|
59
|
+
$build_queue.purge(:pid, self)
|
80
60
|
end
|
81
61
|
|
82
62
|
def build!
|
83
|
-
start!
|
84
63
|
case pid = spawn_build
|
85
64
|
when Fixnum
|
65
|
+
start!
|
86
66
|
Juici.dbgp "#{pid} away!"
|
87
67
|
self[:pid] = pid
|
88
68
|
self[:buffer] = @buffer.path
|
@@ -100,22 +80,18 @@ module Juici
|
|
100
80
|
|
101
81
|
def worktree
|
102
82
|
File.join(Config.workspace, parent)
|
103
|
-
rescue TypeError => e
|
104
|
-
warn! "Invalid workdir"
|
105
|
-
failure!
|
106
|
-
raise AbortBuild
|
107
83
|
end
|
108
84
|
|
109
85
|
# View helpers
|
110
86
|
def heading_color
|
111
87
|
case status
|
112
|
-
when
|
88
|
+
when :waiting
|
113
89
|
"build-heading-pending"
|
114
|
-
when
|
90
|
+
when :failed
|
115
91
|
"build-heading-failed"
|
116
|
-
when
|
92
|
+
when :success
|
117
93
|
"build-heading-success"
|
118
|
-
when
|
94
|
+
when :started
|
119
95
|
"build-heading-started"
|
120
96
|
end
|
121
97
|
end
|
@@ -133,20 +109,14 @@ module Juici
|
|
133
109
|
self[:title] || self[:create_time]
|
134
110
|
end
|
135
111
|
|
136
|
-
def link_title
|
137
|
-
"#{self[:parent]}/#{display_title}"
|
138
|
-
end
|
139
|
-
|
140
112
|
def warn!(msg)
|
141
113
|
warnings << msg
|
142
114
|
save!
|
143
115
|
end
|
144
116
|
|
145
117
|
def process_callbacks
|
146
|
-
callbacks.each do |callback_url|
|
147
|
-
|
148
|
-
c.payload = self.to_callback_json
|
149
|
-
c.process!
|
118
|
+
self[:callbacks].each do |callback_url|
|
119
|
+
Callback.new(self, callback_url).process!
|
150
120
|
end
|
151
121
|
end
|
152
122
|
|
@@ -155,36 +125,9 @@ module Juici
|
|
155
125
|
{
|
156
126
|
"project" => self[:parent],
|
157
127
|
"status" => self[:status],
|
158
|
-
"url" => build_url_for(self)
|
159
|
-
"time" => time_elapsed
|
128
|
+
"url" => build_url_for(self)
|
160
129
|
}.to_json
|
161
130
|
end
|
162
131
|
|
163
|
-
def callbacks
|
164
|
-
self[:callbacks] || []
|
165
|
-
end
|
166
|
-
|
167
|
-
def time_elapsed
|
168
|
-
if self[:end_time]
|
169
|
-
self[:end_time] - self[:start_time]
|
170
|
-
elsif self[:start_time]
|
171
|
-
Time.now - self[:start_time]
|
172
|
-
else
|
173
|
-
nil
|
174
|
-
end
|
175
|
-
rescue
|
176
|
-
-1 # Throw an obviously impossible build time.
|
177
|
-
# This will only occur as a result of old builds.
|
178
|
-
end
|
179
|
-
|
180
|
-
# Use symbols internally
|
181
|
-
def status
|
182
|
-
self[:status].to_s
|
183
|
-
end
|
184
|
-
|
185
|
-
def status=(s)
|
186
|
-
self[:status] = s.to_sym
|
187
|
-
end
|
188
|
-
|
189
132
|
end
|
190
133
|
end
|
data/lib/juici/models/project.rb
CHANGED
data/lib/juici/server.rb
CHANGED
@@ -11,8 +11,6 @@ module Juici
|
|
11
11
|
end
|
12
12
|
|
13
13
|
helpers do
|
14
|
-
include Ansible
|
15
|
-
|
16
14
|
Dir[File.dirname(__FILE__) + "/helpers/**/*.rb"].each do |file|
|
17
15
|
load file
|
18
16
|
end
|
@@ -21,16 +19,9 @@ module Juici
|
|
21
19
|
dir = File.dirname(File.expand_path(__FILE__))
|
22
20
|
|
23
21
|
def self.start(host, port)
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
trap(sig) do
|
28
|
-
$stderr.puts "Shutting down JuiCI"
|
29
|
-
App.shutdown
|
30
|
-
server.respond_to?(:stop!) ? server.stop! : server.stop
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
22
|
+
Database.initialize!
|
23
|
+
@@juici = App.new
|
24
|
+
Juici::Server.run! :host => host, :port => port
|
34
25
|
end
|
35
26
|
|
36
27
|
def self.rack_start(project_path)
|
@@ -42,130 +33,76 @@ module Juici
|
|
42
33
|
set :static, true
|
43
34
|
|
44
35
|
get '/' do
|
45
|
-
|
46
|
-
|
47
|
-
end
|
36
|
+
@page = :index
|
37
|
+
erb(:index, {}, :juici => juici)
|
48
38
|
end
|
49
39
|
|
50
40
|
get '/about' do
|
51
|
-
|
52
|
-
|
53
|
-
|
41
|
+
@page = :about
|
42
|
+
@action = :show
|
43
|
+
erb(:about)
|
54
44
|
end
|
55
45
|
|
56
46
|
get '/builds' do
|
57
|
-
|
58
|
-
|
59
|
-
|
47
|
+
@page = :builds
|
48
|
+
@action = :list
|
49
|
+
erb(:builds, {}, :juici => juici)
|
60
50
|
end
|
61
51
|
|
62
|
-
get '/
|
63
|
-
|
64
|
-
|
65
|
-
|
52
|
+
get '/builds/new' do
|
53
|
+
@page = :builds
|
54
|
+
@action = :new
|
55
|
+
erb(:"builds/new", :juici => juici)
|
66
56
|
end
|
67
57
|
|
68
58
|
post '/builds/new' do
|
69
|
-
|
70
|
-
@redirect_to = build_url_for(
|
71
|
-
erb(:redirect, {},
|
72
|
-
end
|
73
|
-
|
74
|
-
post '/builds/:project/rebuild/:id' do
|
75
|
-
build = Controllers::Trigger.new(params[:project], params).rebuild!
|
76
|
-
@redirect_to = build_url_for(build)
|
77
|
-
erb(:redirect, {}, {})
|
78
|
-
end
|
79
|
-
|
80
|
-
post '/builds/:user/:project/rebuild/:id' do
|
81
|
-
params[:project] = "#{params[:user]}/#{params[:project]}"
|
82
|
-
build = Controllers::Trigger.new(params[:project], params).rebuild!
|
83
|
-
@redirect_to = build_url_for(build)
|
84
|
-
erb(:redirect, {}, {})
|
59
|
+
TriggerController.new(params[:project], params).build!
|
60
|
+
@redirect_to = build_url_for(params[:project])
|
61
|
+
erb(:redirect, {}, :juici => juici)
|
85
62
|
end
|
86
63
|
|
87
|
-
|
88
|
-
|
89
|
-
@redirect_to = build_url_for(build)
|
90
|
-
erb(:redirect, {}, {})
|
91
|
-
end
|
92
|
-
|
93
|
-
post '/builds/cancel' do
|
94
|
-
build = Controllers::Builds.new(params).cancel
|
95
|
-
@redirect_to = build_url_for(build)
|
96
|
-
erb(:redirect, {}, {})
|
97
|
-
end
|
98
|
-
|
99
|
-
get ::Juici::Routes::NEW_BUILD do
|
100
|
-
Controllers::Builds.new(params).new do |template, opts|
|
101
|
-
erb(template, {}, opts)
|
102
|
-
end
|
64
|
+
def list_builds(params)
|
65
|
+
erb(:"builds/list", {}, :juici => juici, :project => params[:project])
|
103
66
|
end
|
104
67
|
|
105
68
|
get '/builds/:project/list' do
|
106
|
-
|
107
|
-
|
108
|
-
|
69
|
+
@page = :builds
|
70
|
+
@action = :list
|
71
|
+
list_builds(params)
|
109
72
|
end
|
110
73
|
|
111
74
|
get '/builds/:user/:project/list' do
|
75
|
+
@page = :builds
|
76
|
+
@action = :list
|
112
77
|
params[:project] = "#{params[:user]}/#{params[:project]}"
|
113
|
-
|
114
|
-
erb(template, {}, opts)
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
get '/builds/:project/edit/:id' do
|
119
|
-
Controllers::Builds.new(params).edit do |template, opts|
|
120
|
-
erb(template, {}, opts)
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
get '/builds/:user/:project/edit/:id' do
|
125
|
-
params[:project] = "#{params[:user]}/#{params[:project]}"
|
126
|
-
Controllers::Builds.new(params).edit do |template, opts|
|
127
|
-
erb(template, {}, opts)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
post '/builds/:project/edit/:id' do
|
132
|
-
build = Controllers::Builds.new(params).update!
|
133
|
-
@redirect_to = build_url_for(build)
|
134
|
-
erb(:redirect, {}, {})
|
78
|
+
list_builds(params)
|
135
79
|
end
|
136
80
|
|
137
|
-
|
138
|
-
|
139
|
-
build = Controllers::Builds.new(params).update!
|
140
|
-
@redirect_to = build_url_for(build)
|
141
|
-
erb(:redirect, {}, {})
|
81
|
+
def show_build(params)
|
82
|
+
erb(:"builds/show", {}, :juici => juici, :project => params[:project], :id => params[:id])
|
142
83
|
end
|
143
84
|
|
144
85
|
get '/builds/:project/show/:id' do
|
145
|
-
|
146
|
-
|
147
|
-
|
86
|
+
@page = :builds
|
87
|
+
@action = :show
|
88
|
+
show_build(params)
|
148
89
|
end
|
149
90
|
|
150
91
|
get '/builds/:user/:project/show/:id' do
|
92
|
+
@page = :builds
|
93
|
+
@action = :show
|
151
94
|
params[:project] = "#{params[:user]}/#{params[:project]}"
|
152
|
-
|
153
|
-
erb(template, {}, opts)
|
154
|
-
end
|
95
|
+
show_build(params)
|
155
96
|
end
|
156
97
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
get '/queue' do
|
162
|
-
Controllers::BuildQueue.new(params).list do |template, opts|
|
163
|
-
erb(template, {}, opts)
|
164
|
-
end
|
98
|
+
get '/support' do
|
99
|
+
@page = :support
|
100
|
+
@action = :show
|
101
|
+
erb(:"support", {})
|
165
102
|
end
|
166
103
|
|
167
|
-
|
168
|
-
|
104
|
+
post '/trigger/:project' do
|
105
|
+
TriggerController.new(params[:project], params).build!
|
169
106
|
end
|
170
107
|
|
171
108
|
end
|