juici 0.0.0.alpha1 → 0.0.0

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.
Files changed (69) hide show
  1. data/Gemfile +1 -4
  2. data/Gemfile.lock +9 -19
  3. data/README.md +6 -45
  4. data/Rakefile +0 -24
  5. data/config/mongoid.yml.sample +5 -20
  6. data/juici.gemspec +3 -7
  7. data/lib/juici.rb +3 -8
  8. data/lib/juici/app.rb +23 -19
  9. data/lib/juici/build_environment.rb +1 -1
  10. data/lib/juici/build_logic.rb +1 -10
  11. data/lib/juici/build_queue.rb +3 -30
  12. data/lib/juici/callback.rb +5 -9
  13. data/lib/juici/config.rb +0 -4
  14. data/lib/juici/controllers/build_controller.rb +0 -0
  15. data/lib/juici/controllers/{trigger.rb → trigger_controller.rb} +5 -24
  16. data/lib/juici/database.rb +13 -19
  17. data/lib/juici/helpers/url_helpers.rb +0 -28
  18. data/lib/juici/models/build.rb +24 -81
  19. data/lib/juici/models/project.rb +1 -1
  20. data/lib/juici/server.rb +40 -103
  21. data/lib/juici/url_helpers.rb +15 -0
  22. data/lib/juici/views/README.markdown +6 -45
  23. data/lib/juici/views/about.erb +5 -5
  24. data/lib/juici/views/builds/list.erb +33 -26
  25. data/lib/juici/views/builds/new.erb +37 -42
  26. data/lib/juici/views/builds/show.erb +28 -4
  27. data/lib/juici/views/index.erb +13 -30
  28. data/lib/juici/views/layout.erb +13 -22
  29. data/lib/juici/views/partials/builds/debug.erb +18 -12
  30. data/lib/juici/watcher.rb +25 -33
  31. data/public/styles/builds.css +8 -59
  32. data/public/styles/juici.css +2 -226
  33. data/spec/build_callback_spec.rb +1 -46
  34. data/spec/build_process_spec.rb +5 -71
  35. data/spec/build_queue_spec.rb +1 -3
  36. data/spec/juici_app_spec.rb +15 -0
  37. data/spec/spec_helper.rb +0 -13
  38. metadata +12 -76
  39. data/.gitignore +0 -2
  40. data/bin/juicic +0 -54
  41. data/juici-interface.gemspec +0 -19
  42. data/lib/juici/controllers.rb +0 -6
  43. data/lib/juici/controllers/base.rb +0 -26
  44. data/lib/juici/controllers/build_queue.rb +0 -14
  45. data/lib/juici/controllers/builds.rb +0 -74
  46. data/lib/juici/controllers/index.rb +0 -20
  47. data/lib/juici/exceptions.rb +0 -2
  48. data/lib/juici/find_logic.rb +0 -11
  49. data/lib/juici/helpers/form_helpers.rb +0 -11
  50. data/lib/juici/helpers/html_helpers.rb +0 -4
  51. data/lib/juici/interface.rb +0 -13
  52. data/lib/juici/version.rb +0 -8
  53. data/lib/juici/views/builds/edit.erb +0 -23
  54. data/lib/juici/views/not_found.erb +0 -3
  55. data/lib/juici/views/partials/builds/output.erb +0 -1
  56. data/lib/juici/views/partials/builds/show.erb +0 -19
  57. data/lib/juici/views/partials/builds/sidebar.erb +0 -13
  58. data/lib/juici/views/partials/index/recently_built.erb +0 -19
  59. data/lib/juici/views/queue/list.erb +0 -6
  60. data/public/favicon.ico +0 -0
  61. data/public/images/black_denim.png +0 -0
  62. data/public/vendor/bootstrap.css +0 -6004
  63. data/public/vendor/bootstrap.js +0 -2036
  64. data/public/vendor/img/glyphicons-halflings-white.png +0 -0
  65. data/public/vendor/jquery.js +0 -9440
  66. data/script/cibuild +0 -10
  67. data/spec/controllers/builds_spec.rb +0 -68
  68. data/spec/controllers/index_spec.rb +0 -28
  69. data/spec/models/build_spec.rb +0 -54
@@ -4,8 +4,4 @@ class Juici::Config; class << self
4
4
  "/tmp/juici/workspace"
5
5
  end
6
6
 
7
- def builds_per_page
8
- 10
9
- end
10
-
11
7
  end; end
@@ -1,31 +1,15 @@
1
- module Juici::Controllers
2
- class Trigger
1
+ module Juici
2
+ class TriggerController
3
3
 
4
4
  attr_reader :project, :params
5
5
  def initialize(project, params)
6
- @project = ::Juici::Project.find_or_create_by(name: 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 = ::Juici::BuildEnvironment.new
28
- ::Juici::Build.new(parent: project.name).tap do |build|
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
 
@@ -1,25 +1,19 @@
1
- require 'mongoid'
2
- module Juici
3
- class Database
4
- class << self
5
- def mongoid_config_file
6
- %w[mongoid.yml mongoid.yml.sample].each do |file|
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
- def initialize!
14
- if ::Juici.respond_to? :dbgp
15
- ::Juici.dbgp "initializing Mongoid with environment: #{ENV['RACK_ENV']}"
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
@@ -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 => WAIT.to_sym
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.status= value
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 START
41
+ set_status :started
56
42
  end
57
43
 
58
44
  def success!
59
45
  finish
60
- set_status PASS
46
+ set_status :success
61
47
  process_callbacks
62
48
  end
63
49
 
64
50
  def failure!
65
51
  finish
66
- set_status FAIL
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) if $build_queue
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 WAIT
88
+ when :waiting
113
89
  "build-heading-pending"
114
- when FAIL
90
+ when :failed
115
91
  "build-heading-failed"
116
- when PASS
92
+ when :success
117
93
  "build-heading-success"
118
- when START
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
- c = Callback.new(callback_url)
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
@@ -1,7 +1,7 @@
1
1
  module Juici
2
2
  class Project
3
3
  include Mongoid::Document
4
- extend FindLogic
4
+ include Juici.url_helpers("builds")
5
5
 
6
6
  field :name, type: String
7
7
 
@@ -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
- @@juici = App.new
25
- Juici::Server.run!(:host => host, :port => port) do |server|
26
- [:INT, :TERM].each do |sig|
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
- Controllers::Index.new.index do |template, opts|
46
- erb(template, {}, opts)
47
- end
36
+ @page = :index
37
+ erb(:index, {}, :juici => juici)
48
38
  end
49
39
 
50
40
  get '/about' do
51
- Controllers::Index.new.about do |template, opts|
52
- erb(template, {}, opts)
53
- end
41
+ @page = :about
42
+ @action = :show
43
+ erb(:about)
54
44
  end
55
45
 
56
46
  get '/builds' do
57
- Controllers::Index.new.builds do |template, opts|
58
- erb(template, {}, opts)
59
- end
47
+ @page = :builds
48
+ @action = :list
49
+ erb(:builds, {}, :juici => juici)
60
50
  end
61
51
 
62
- get '/support' do
63
- Controllers::Index.new.support do |template, opts|
64
- erb(template, {}, opts)
65
- end
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
- build = Controllers::Trigger.new(params[:project], params).build!
70
- @redirect_to = build_url_for(build)
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
- post '/builds/kill' do
88
- build = Controllers::Builds.new(params).kill
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
- Controllers::Builds.new(params).list do |template, opts|
107
- erb(template, {}, opts)
108
- end
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
- Controllers::Builds.new(params).list do |template, opts|
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
- post '/builds/:user/:project/edit/:id' do
138
- params[:project] = "#{params[:user]}/#{params[:project]}"
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
- Controllers::Builds.new(params).show do |template, opts|
146
- erb(template, {}, opts)
147
- end
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
- Controllers::Builds.new(params).show do |template, opts|
153
- erb(template, {}, opts)
154
- end
95
+ show_build(params)
155
96
  end
156
97
 
157
- post '/trigger/:project' do
158
- Controllers::Trigger.new(params[:project], params).build!
159
- end
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
- not_found do
168
- erb(:not_found, {}, {})
104
+ post '/trigger/:project' do
105
+ TriggerController.new(params[:project], params).build!
169
106
  end
170
107
 
171
108
  end