magi 0.0.7 → 0.1.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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -3
  3. data/README.md +13 -18
  4. data/app/assets/javascripts/application.js +2 -0
  5. data/app/assets/javascripts/events.js.coffee +9 -0
  6. data/app/assets/javascripts/magi/job_model.js.coffee +12 -0
  7. data/app/assets/javascripts/magi/job_view.js.coffee +9 -0
  8. data/app/assets/javascripts/magi/server_event.js.coffee +11 -0
  9. data/app/assets/javascripts/magi.js.coffee +1 -0
  10. data/app/assets/stylesheets/jobs.scss +4 -0
  11. data/app/controllers/application_controller.rb +2 -0
  12. data/app/controllers/builds_controller.rb +1 -1
  13. data/app/controllers/events_controller.rb +34 -0
  14. data/app/controllers/jobs_controller.rb +1 -1
  15. data/app/helpers/application_helper.rb +3 -0
  16. data/app/models/build.rb +21 -6
  17. data/app/models/job.rb +3 -5
  18. data/app/views/jobs/index.html.slim +1 -1
  19. data/app/views/jobs/show.html.slim +4 -2
  20. data/app/views/layouts/application.html.slim +1 -1
  21. data/app/workers/build_worker.rb +1 -1
  22. data/config/application.rb +1 -13
  23. data/config/environments/development.rb +3 -17
  24. data/config/environments/production.rb +4 -0
  25. data/config/environments/test.rb +2 -6
  26. data/config/initializers/redis.rb +1 -0
  27. data/config/initializers/secret_token.rb +1 -0
  28. data/config/routes.rb +2 -0
  29. data/lib/magi/configuration.rb +9 -0
  30. data/lib/magi/responder.rb +12 -0
  31. data/lib/magi/version.rb +1 -1
  32. data/lib/magi.rb +4 -8
  33. data/magi.gemspec +10 -7
  34. data/plugins/git/git.rb +2 -2
  35. data/spec/models/build_spec.rb +5 -5
  36. data/spec/models/job_spec.rb +14 -4
  37. data/spec/requests/builds_spec.rb +13 -0
  38. data/spec/spec_helper.rb +13 -0
  39. metadata +70 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2db7f5dff13d75dd26fc1c8440bbb8cb68b51c92
4
- data.tar.gz: 10ca4a6e4a4619df58bbc5a2f3c741c113cbf629
3
+ metadata.gz: f2f3aa7e90d1b48ae6d264fe18d45927e151fe74
4
+ data.tar.gz: e08af400fadaf5e4ba012227a1a5ca827e988147
5
5
  SHA512:
6
- metadata.gz: a637eed71179f9ccda64cc6185d439f3ee432413da2e8448bd48b38bbe4e733191312368c934634316ba85d3128c390109af6eaa161a1646d7371b68f1c22aa4
7
- data.tar.gz: 705a9126445b1f52b78b957718e3484937366b5d03f69c8dc7f5e316d1db4add2fc86ca4eca850a6acf1606738c9ca7c221acdc3100dbd51c6c0e232d08bfcda
6
+ metadata.gz: 8aaacf0941adfe403a1949c99ae5b742a6dae0fbcfc983de921f7037cec182b719a5234bdbc7922761d4e74d414b2f64cc85522cf448dd881d76a6d2e5a011e6
7
+ data.tar.gz: 25ce48204fb196d6133df7f04e004c1020f446dd79f33e582087a86fd62e5a10d6e10f57a4fa72635e988923b29693b7ff4cf528b13f6a2787d39598326f0585
data/Gemfile CHANGED
@@ -6,6 +6,7 @@ gemspec
6
6
 
7
7
  gem "font-awesome-rails"
8
8
  gem "jquery-rails"
9
+ gem "kaminari"
9
10
  gem "quiet_assets"
10
11
  gem "resque"
11
12
  gem "slim"
@@ -25,9 +26,9 @@ group :test do
25
26
  end
26
27
 
27
28
  group :assets do
28
- gem "sass-rails", "~> 3.2.3"
29
- gem "coffee-rails", "~> 3.2.1"
30
- gem "uglifier", ">= 1.0.3"
29
+ gem "sass-rails"
30
+ gem "coffee-rails"
31
+ gem "uglifier"
31
32
  end
32
33
 
33
34
  # Put Gemfile in plugins/:name/Gemfile to use arbitrary gems in your plugin.
data/README.md CHANGED
@@ -1,31 +1,26 @@
1
1
  # Magi
2
2
  A continuous integration server implementation.
3
3
 
4
- ![](http://dl.dropbox.com/u/5978869/image/20130607_012059.png)
5
-
6
- ## Install
7
- ```
8
- $ gem install magi
9
- $ brew install mysql redis # or other commands to install MySQL and Redis
10
- ```
11
-
12
4
  ## Usage
13
5
  ```
14
- $ magi setup
15
- $ magi start # open http://localhost:3000
6
+ $ gem install magi # install magi.gem
7
+ $ brew install mysql redis # install MySQL and Redis
8
+ $ magi setup # create mysql tables
9
+ $ magi start # launch server on http://localhost:3000
16
10
  ```
17
11
 
18
- ## Hack
12
+ ## Development
19
13
  Magi is just a rails application with some middlewares.
20
14
 
21
- * clockwork: scheduler
15
+ * rails4: notify build start/finish events via live streaming
16
+ * clockwork: cron scheduler
22
17
  * foreman: process manager
23
18
  * mysql: store jobs & builds
24
19
  * resque: background worker using redis
20
+ * autodoc: generate [RESTful API documents](https://github.com/r7kamura/magi/blob/master/doc) from request-specs
21
+ * jquery: ajax updated view
25
22
 
26
- ## Todo
27
- * async update by ajax
28
- * command-line options
29
-
30
- ## API
31
- [API documents](https://github.com/r7kamura/magi/blob/master/doc)
23
+ ### TODO
24
+ * build stop button
25
+ * self-repairing system
26
+ * plugin updater
@@ -12,4 +12,6 @@
12
12
  //
13
13
  //= require jquery
14
14
  //= require jquery_ujs
15
+ //= require magi
16
+ //= require_tree ./magi
15
17
  //= require_tree .
@@ -0,0 +1,9 @@
1
+ $ ->
2
+ $('.jobs_controller.index_action').each ->
3
+ job = new Magi.JobModel()
4
+ view = new Magi.JobView(job)
5
+ job.onChange -> view.render()
6
+
7
+ event = new Magi.ServerEvent()
8
+ event.onBuildStart (attributes) -> job.set(attributes)
9
+ event.onBuildFinish (attributes) -> job.set(attributes)
@@ -0,0 +1,12 @@
1
+ class window.Magi.JobModel
2
+ constructor: (@attributes = {}) ->
3
+
4
+ set: (attributes) ->
5
+ @attributes[key] = value for key, value of attributes
6
+ @change()
7
+
8
+ onChange: (callback) ->
9
+ @callback = callback
10
+
11
+ change: ->
12
+ @callback()
@@ -0,0 +1,9 @@
1
+ class window.Magi.JobView
2
+ constructor: (@job) ->
3
+
4
+ element: ->
5
+ $("#job#{@job.attributes.job_id}")
6
+
7
+ render: ->
8
+ @element().removeClass()
9
+ @element().addClass(@job.attributes.status)
@@ -0,0 +1,11 @@
1
+ class window.Magi.ServerEvent
2
+ constructor: ->
3
+ @source = new EventSource('/events')
4
+
5
+ onBuildStart: (callback) ->
6
+ @source.addEventListener 'build.start', (event) ->
7
+ callback($.parseJSON(event.data))
8
+
9
+ onBuildFinish: (callback) ->
10
+ @source.addEventListener 'build.finish', (event) ->
11
+ callback($.parseJSON(event.data))
@@ -0,0 +1 @@
1
+ window.Magi = {}
@@ -118,4 +118,8 @@ section.builds {
118
118
  h1:before {
119
119
  content: "\F0FB";
120
120
  }
121
+
122
+ .pagination {
123
+ text-align: center;
124
+ }
121
125
  }
@@ -7,6 +7,8 @@ class ApplicationController < ActionController::Base
7
7
  head 400
8
8
  end
9
9
 
10
+ self.responder = Magi::Responder
11
+
10
12
  private
11
13
 
12
14
  def require_resource_params
@@ -21,7 +21,7 @@ class BuildsController < ApplicationController
21
21
  end
22
22
 
23
23
  def update
24
- respond_with @resource.update_attributes(params.slice(:status))
24
+ respond_with @resource.update_attributes(params.permit(:status))
25
25
  end
26
26
 
27
27
  def destroy
@@ -0,0 +1,34 @@
1
+ class EventsController < ApplicationController
2
+ include ActionController::Live
3
+
4
+ before_filter :require_event_stream
5
+
6
+ def index
7
+ redis = Redis.new
8
+ redis.psubscribe("build.*") do |on|
9
+ on.pmessage do |pattern, event, data|
10
+ response.stream.write("event: #{event}\n")
11
+ response.stream.write("data: #{data}\n\n")
12
+ end
13
+ end
14
+ rescue IOError
15
+ rescue Redis::CannotConnectError
16
+ head 503
17
+ ensure
18
+ redis.quit rescue nil
19
+ response.stream.close
20
+ end
21
+
22
+ private
23
+
24
+ def index_with_redis_exception
25
+ index_without_redis_exception
26
+ rescue Redis::CannotConnectError
27
+ head 503
28
+ end
29
+ alias_method_chain :index, :redis_exception
30
+
31
+ def require_event_stream
32
+ response.headers["Content-Type"] = "text/event-stream"
33
+ end
34
+ end
@@ -37,7 +37,7 @@ class JobsController < ApplicationController
37
37
  private
38
38
 
39
39
  def scope
40
- Job.scoped
40
+ Job.all
41
41
  end
42
42
 
43
43
  def require_resources
@@ -1,2 +1,5 @@
1
1
  module ApplicationHelper
2
+ def action_classes
3
+ %W[#{controller_name}_controller #{action_name}_action]
4
+ end
2
5
  end
data/app/models/build.rb CHANGED
@@ -1,8 +1,6 @@
1
1
  class Build < ActiveRecord::Base
2
2
  include Magi::Proprietary
3
3
 
4
- attr_accessible :finished_at, :started_at, :output, :properties, :status
5
-
6
4
  serialize :properties, Hash
7
5
 
8
6
  validates :job_id, presence: true
@@ -19,6 +17,8 @@ class Build < ActiveRecord::Base
19
17
 
20
18
  scope :running, -> { started.unfinished }
21
19
 
20
+ paginates_per 10
21
+
22
22
  def self.latest
23
23
  recent.first
24
24
  end
@@ -29,10 +29,9 @@ class Build < ActiveRecord::Base
29
29
  end
30
30
 
31
31
  # Runs this build, usually called from BuildWorker#perform.
32
- def start
33
- update_attributes!(started_at: Time.now)
34
- result = job.start
35
- reload.update_attributes!(finished_at: Time.now, status: result[:status], output: result[:output])
32
+ def run
33
+ start
34
+ finish(job.run)
36
35
  end
37
36
 
38
37
  # Returns elapsed sec as a Float or nil.
@@ -50,4 +49,20 @@ class Build < ActiveRecord::Base
50
49
  "unfinished"
51
50
  end
52
51
  end
52
+
53
+ private
54
+
55
+ def notify(type)
56
+ $redis.publish("build.#{type}", { id: id, job_id: job.id, status: status_name }.to_json)
57
+ end
58
+
59
+ def start
60
+ update_attributes!(started_at: Time.now)
61
+ notify(:start)
62
+ end
63
+
64
+ def finish(result)
65
+ reload.update_attributes!(finished_at: Time.now, output: result[:output], status: result[:status])
66
+ notify(:finish)
67
+ end
53
68
  end
data/app/models/job.rb CHANGED
@@ -1,8 +1,6 @@
1
1
  class Job < ActiveRecord::Base
2
2
  include Magi::Proprietary
3
3
 
4
- attr_accessible :name, :properties
5
-
6
4
  serialize :properties, Hash
7
5
 
8
6
  validates :name, presence: true
@@ -63,12 +61,12 @@ class Job < ActiveRecord::Base
63
61
 
64
62
  property(:script)
65
63
 
66
- def start
64
+ def run
67
65
  script ? execute : raise_script_not_found
68
66
  end
69
67
 
70
68
  def scheduler
71
- Magi::Scheduler.new(schedule) if schedule
69
+ Magi::Scheduler.new(schedule) if schedule.present?
72
70
  end
73
71
 
74
72
  def enqueue
@@ -115,7 +113,7 @@ class Job < ActiveRecord::Base
115
113
  private
116
114
 
117
115
  def workspace_path
118
- Magi.workspace.path + "jobs/#{id}"
116
+ Magi.configuration.workspace_path + "jobs/#{id}"
119
117
  end
120
118
 
121
119
  def execute
@@ -13,7 +13,7 @@ section.jobs
13
13
 
14
14
  ul
15
15
  - @resources.recent.each do |resource|
16
- li class = resource.status_name
16
+ li class=resource.status_name id="job#{resource.id}"
17
17
  = link_to resource do
18
18
  span
19
19
  = resource.name
@@ -14,11 +14,13 @@ section.builds
14
14
  .buttons
15
15
  = link_to "Run", [@resource, :builds], method: "POST", class: "button run"
16
16
  = link_to "Settings", [:edit, @resource], class: "button settings"
17
- = link_to "Delete", @resource, method: "DELETE", confirm: "Are you sure?", class: "button delete"
17
+ = link_to "Delete", @resource, method: "DELETE", data: { confirm: "Are you sure?" }, class: "button delete"
18
18
 
19
19
  ul
20
- - @resource.builds.recent.limit(10).each do |build|
20
+ - @resource.builds.page(params[:page]).recent.limit(10).each do |build|
21
21
  li class = build.status_name
22
22
  = link_to [@resource, build] do
23
23
  span.id ##{build.id}
24
24
  span= build.finished_at
25
+
26
+ = paginate @resource.builds.page(params[:page])
@@ -6,5 +6,5 @@ html
6
6
  = stylesheet_link_tag "application", media: "all"
7
7
  = javascript_include_tag "application"
8
8
 
9
- body
9
+ body class = action_classes
10
10
  = yield
@@ -3,7 +3,7 @@ class BuildWorker
3
3
 
4
4
  class << self
5
5
  def perform(id)
6
- Build.find(id).start
6
+ Build.find(id).run
7
7
  end
8
8
 
9
9
  def perform_async(id)
@@ -3,10 +3,7 @@ require File.expand_path('../boot', __FILE__)
3
3
  require 'rails/all'
4
4
 
5
5
  if defined?(Bundler)
6
- # If you precompile assets before deploying to production, use this line
7
- # Bundler.require(*Rails.groups(:assets => %w(development test)))
8
- # If you want your assets lazily compiled in production, use this line
9
- Bundler.require(:default, :assets, Rails.env)
6
+ Bundler.require(:default, Rails.env)
10
7
  end
11
8
 
12
9
  module Magi
@@ -47,15 +44,6 @@ module Magi
47
44
  # like if you have constraints or database-specific column types
48
45
  # config.active_record.schema_format = :sql
49
46
 
50
- # Enforce whitelist mode for mass assignment.
51
- # This will create an empty whitelist of attributes available for mass-assignment for all models
52
- # in your app. As such, your models will need to explicitly whitelist or blacklist accessible
53
- # parameters by using an attr_accessible or attr_protected declaration.
54
- config.active_record.whitelist_attributes = true
55
-
56
- # Enable the asset pipeline
57
- config.assets.enabled = true
58
-
59
47
  # Version of your assets, change this if you want to expire all your assets
60
48
  config.assets.version = '1.0'
61
49
  end
@@ -4,10 +4,7 @@ Magi::Application.configure do
4
4
  # In the development environment your application's code is reloaded on
5
5
  # every request. This slows down response time but is perfect for development
6
6
  # since you don't have to restart the web server when you make code changes.
7
- config.cache_classes = false
8
-
9
- # Log error messages when you accidentally call methods on nil.
10
- config.whiny_nils = true
7
+ config.cache_classes = true
11
8
 
12
9
  # Show full error reports and disable caching
13
10
  config.consider_all_requests_local = true
@@ -19,19 +16,8 @@ Magi::Application.configure do
19
16
  # Print deprecation notices to the Rails logger
20
17
  config.active_support.deprecation = :log
21
18
 
22
- # Only use best-standards-support built into browsers
23
- config.action_dispatch.best_standards_support = :builtin
24
-
25
- # Raise exception on mass assignment protection for Active Record models
26
- config.active_record.mass_assignment_sanitizer = :strict
27
-
28
- # Log the query plan for queries taking more than this (works
29
- # with SQLite, MySQL, and PostgreSQL)
30
- config.active_record.auto_explain_threshold_in_seconds = 0.5
31
-
32
- # Do not compress assets
33
- config.assets.compress = false
34
-
35
19
  # Expands the lines which load the assets
36
20
  config.assets.debug = true
21
+
22
+ config.eager_load = true
37
23
  end
@@ -64,4 +64,8 @@ Magi::Application.configure do
64
64
  # Log the query plan for queries taking more than this (works
65
65
  # with SQLite, MySQL, and PostgreSQL)
66
66
  # config.active_record.auto_explain_threshold_in_seconds = 0.5
67
+
68
+ config.eager_load = true
69
+
70
+ config.assets.js_compressor = :uglifier
67
71
  end
@@ -11,9 +11,6 @@ Magi::Application.configure do
11
11
  config.serve_static_assets = true
12
12
  config.static_cache_control = "public, max-age=3600"
13
13
 
14
- # Log error messages when you accidentally call methods on nil
15
- config.whiny_nils = true
16
-
17
14
  # Show full error reports and disable caching
18
15
  config.consider_all_requests_local = true
19
16
  config.action_controller.perform_caching = false
@@ -29,9 +26,8 @@ Magi::Application.configure do
29
26
  # ActionMailer::Base.deliveries array.
30
27
  config.action_mailer.delivery_method = :test
31
28
 
32
- # Raise exception on mass assignment protection for Active Record models
33
- config.active_record.mass_assignment_sanitizer = :strict
34
-
35
29
  # Print deprecation notices to the stderr
36
30
  config.active_support.deprecation = :stderr
31
+
32
+ config.eager_load = false
37
33
  end
@@ -0,0 +1 @@
1
+ $redis = Redis.new
@@ -5,3 +5,4 @@
5
5
  # Make sure the secret is at least 30 characters and all random,
6
6
  # no regular words or you'll be exposed to dictionary attacks.
7
7
  Magi::Application.config.secret_token = '52e56b4c387efb5ac8eb96c71963f58de5432808e97bc5d971ea8e04997bab457094ed4da841829ce98933564259a213dd249fb2a1079bd895e703eebfc4e8a2'
8
+ Magi::Application.config.secret_key_base = 'e856f5fcd6c1e77a152fb5726fe8b14e149463de77df20bf6ee8ee73cc985d09219df9a247f2f29b0349634dc794ec7909804d14c03615c2c2a9bed4451cc790'
data/config/routes.rb CHANGED
@@ -4,4 +4,6 @@ Magi::Application.routes.draw do
4
4
  resources :jobs do
5
5
  resources :builds, only: [:index, :show, :create, :update, :destroy]
6
6
  end
7
+
8
+ resources :events, only: :index
7
9
  end
@@ -0,0 +1,9 @@
1
+ module Magi
2
+ class Configuration
3
+ attr_accessor :workspace_path
4
+
5
+ def initialize
6
+ @workspace_path = Pathname.new(ENV["WORKSPACE_PATH"] || ".")
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ require "action_controller"
2
+
3
+ module Magi
4
+ class Responder < ActionController::Responder
5
+ def initialize(controller, resources, *args)
6
+ if resources[0].respond_to?(:page)
7
+ resources[0] = resources[0].page(controller.params[:page])
8
+ end
9
+ super
10
+ end
11
+ end
12
+ end
data/lib/magi/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Magi
2
- VERSION = "0.0.7"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/magi.rb CHANGED
@@ -1,22 +1,18 @@
1
1
  require "magi/command"
2
+ require "magi/configuration"
2
3
  require "magi/plugin_manager"
4
+ require "magi/responder"
3
5
  require "magi/version"
4
6
  require "magi/workspace"
5
7
 
6
8
  module Magi
7
9
  class << self
8
- def workspace
9
- @workspace ||= Magi::Workspace.new(workspace_path)
10
+ def configuration
11
+ @configuration ||= Magi::Configuration.new
10
12
  end
11
13
 
12
14
  def plugin_manager
13
15
  @plugin_manager ||= Magi::PluginManager.new
14
16
  end
15
-
16
- private
17
-
18
- def workspace_path
19
- ENV["WORKSPACE_PATH"] || "."
20
- end
21
17
  end
22
18
  end
data/magi.gemspec CHANGED
@@ -27,20 +27,23 @@ Gem::Specification.new do |spec|
27
27
  spec.require_paths = ["lib"]
28
28
 
29
29
  spec.add_dependency "clockwork"
30
- spec.add_dependency "coffee-rails", "~> 3.2.1"
30
+ spec.add_dependency "coffee-rails", ">= 4.0.0"
31
31
  spec.add_dependency "font-awesome-rails"
32
32
  spec.add_dependency "foreman"
33
33
  spec.add_dependency "jquery-rails"
34
+ spec.add_dependency "kaminari"
34
35
  spec.add_dependency "mysql2"
36
+ spec.add_dependency "puma"
35
37
  spec.add_dependency "quiet_assets"
36
- spec.add_dependency "rails", "3.2.13"
38
+ spec.add_dependency "rails", ">= 4.0.0.rc2"
37
39
  spec.add_dependency "rake"
40
+ spec.add_dependency "redis"
38
41
  spec.add_dependency "resque"
39
- spec.add_dependency "sass-rails", "~> 3.2.3"
42
+ spec.add_dependency "sass-rails", ">= 4.0.0.rc1"
40
43
  spec.add_dependency "slim"
41
- spec.add_dependency "uglifier", ">= 1.0.3"
42
- spec.add_dependency "weak_parameters", ">= 0.0.3"
43
- spec.add_development_dependency "bundler", "~> 1.3"
44
+ spec.add_dependency "uglifier", ">= 1.3.0"
45
+ spec.add_dependency "weak_parameters"
46
+
47
+ spec.add_development_dependency "bundler"
44
48
  spec.add_development_dependency "pry-rails"
45
- spec.add_development_dependency "thin"
46
49
  end
data/plugins/git/git.rb CHANGED
@@ -21,7 +21,7 @@ module Magi
21
21
  command("cd #{job.workspace.path} && git rev-parse HEAD").rstrip
22
22
  end
23
23
 
24
- def updated?
24
+ def updated_since_last_finished_build?
25
25
  revision != job.last_finished_build.try(:revision)
26
26
  end
27
27
 
@@ -54,7 +54,7 @@ Job.class_eval do
54
54
  if git_url.present?
55
55
  repository.clone unless repository.cloned?
56
56
  repository.update
57
- repository.updated?
57
+ repository.updated_since_last_finished_build?
58
58
  end
59
59
  end
60
60
 
@@ -9,10 +9,10 @@ describe Build do
9
9
  FactoryGirl.create(:job, properties: { "script" => "true" })
10
10
  end
11
11
 
12
- describe "#start" do
12
+ describe "#run" do
13
13
  context "with success" do
14
- it "starts its job and sets status with true" do
15
- build.start
14
+ it "runs its job and sets status with true" do
15
+ build.run
16
16
  build.started_at.should be_present
17
17
  build.finished_at.should be_present
18
18
  build.status.should == true
@@ -24,8 +24,8 @@ describe Build do
24
24
  build.job.script = "false"
25
25
  end
26
26
 
27
- it "starts its job and sets status with false" do
28
- build.start
27
+ it "runs its job and sets status with false" do
28
+ build.run
29
29
  build.started_at.should be_present
30
30
  build.finished_at.should be_present
31
31
  build.status.should == false
@@ -5,14 +5,14 @@ describe Job do
5
5
  FactoryGirl.create(:job, properties: { "script" => "true" })
6
6
  end
7
7
 
8
- describe "#start" do
8
+ describe "#run" do
9
9
  context "without script" do
10
10
  before do
11
11
  job.script = nil
12
12
  end
13
13
 
14
14
  it "raises Job::ScriptNotFound" do
15
- expect { job.start }.to raise_error(Job::ScriptNotFound)
15
+ expect { job.run }.to raise_error(Job::ScriptNotFound)
16
16
  end
17
17
  end
18
18
 
@@ -21,9 +21,9 @@ describe Job do
21
21
  job.script = "true"
22
22
  end
23
23
 
24
- it "starts its job" do
24
+ it "runs its job" do
25
25
  Magi::Executer.should_receive(:execute).with("true")
26
- job.start
26
+ job.run
27
27
  end
28
28
  end
29
29
  end
@@ -35,6 +35,16 @@ describe Job do
35
35
  end
36
36
  end
37
37
 
38
+ context "with empty schedule" do
39
+ before do
40
+ job.schedule = ""
41
+ end
42
+
43
+ it "returns false" do
44
+ job.should_not be_scheduled
45
+ end
46
+ end
47
+
38
48
  context "with matched schedule" do
39
49
  before do
40
50
  job.schedule = "* * * * *"
@@ -27,6 +27,19 @@ describe "Builds" do
27
27
  response.status.should == 200
28
28
  response.body.should be_json([Hash])
29
29
  end
30
+
31
+ context "with page" do
32
+ before do
33
+ params[:page] = 2
34
+ 10.times { job.builds.create }
35
+ end
36
+
37
+ it "paginates builds" do
38
+ get "/jobs/#{job.id}/builds", params, env
39
+ response.status.should == 200
40
+ response.body.should be_json([Hash])
41
+ end
42
+ end
30
43
  end
31
44
 
32
45
  describe "GET /jobs/:job_id/builds/:id" do
data/spec/spec_helper.rb CHANGED
@@ -24,6 +24,19 @@ RSpec.configure do |config|
24
24
 
25
25
  config.include RSpec::JsonMatcher, type: :request
26
26
  config.include ResponseCodeMatchers, type: :request
27
+
28
+ config.before(:suite) do
29
+ Magi.configuration.workspace_path = Rails.root.join("tmp/workspace")
30
+ end
31
+
32
+ config.after(:suite) do
33
+ workspace = Rails.root.join("tmp/workspace")
34
+ workspace.rmtree if workspace.exist?
35
+ end
36
+
37
+ config.before do
38
+ $redis.stub(:publish)
39
+ end
27
40
  end
28
41
 
29
42
  Resque.inline = true
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: magi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryo Nakamura
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-15 00:00:00.000000000 Z
11
+ date: 2013-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clockwork
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: coffee-rails
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - '>='
32
32
  - !ruby/object:Gem::Version
33
- version: 3.2.1
33
+ version: 4.0.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - '>='
39
39
  - !ruby/object:Gem::Version
40
- version: 3.2.1
40
+ version: 4.0.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: font-awesome-rails
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - '>='
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: kaminari
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: mysql2
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +108,20 @@ dependencies:
94
108
  - - '>='
95
109
  - !ruby/object:Gem::Version
96
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: puma
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
97
125
  - !ruby/object:Gem::Dependency
98
126
  name: quiet_assets
99
127
  requirement: !ruby/object:Gem::Requirement
@@ -112,16 +140,16 @@ dependencies:
112
140
  name: rails
113
141
  requirement: !ruby/object:Gem::Requirement
114
142
  requirements:
115
- - - '='
143
+ - - '>='
116
144
  - !ruby/object:Gem::Version
117
- version: 3.2.13
145
+ version: 4.0.0.rc2
118
146
  type: :runtime
119
147
  prerelease: false
120
148
  version_requirements: !ruby/object:Gem::Requirement
121
149
  requirements:
122
- - - '='
150
+ - - '>='
123
151
  - !ruby/object:Gem::Version
124
- version: 3.2.13
152
+ version: 4.0.0.rc2
125
153
  - !ruby/object:Gem::Dependency
126
154
  name: rake
127
155
  requirement: !ruby/object:Gem::Requirement
@@ -137,7 +165,7 @@ dependencies:
137
165
  - !ruby/object:Gem::Version
138
166
  version: '0'
139
167
  - !ruby/object:Gem::Dependency
140
- name: resque
168
+ name: redis
141
169
  requirement: !ruby/object:Gem::Requirement
142
170
  requirements:
143
171
  - - '>='
@@ -151,77 +179,77 @@ dependencies:
151
179
  - !ruby/object:Gem::Version
152
180
  version: '0'
153
181
  - !ruby/object:Gem::Dependency
154
- name: sass-rails
182
+ name: resque
155
183
  requirement: !ruby/object:Gem::Requirement
156
184
  requirements:
157
- - - ~>
185
+ - - '>='
158
186
  - !ruby/object:Gem::Version
159
- version: 3.2.3
187
+ version: '0'
160
188
  type: :runtime
161
189
  prerelease: false
162
190
  version_requirements: !ruby/object:Gem::Requirement
163
191
  requirements:
164
- - - ~>
192
+ - - '>='
165
193
  - !ruby/object:Gem::Version
166
- version: 3.2.3
194
+ version: '0'
167
195
  - !ruby/object:Gem::Dependency
168
- name: slim
196
+ name: sass-rails
169
197
  requirement: !ruby/object:Gem::Requirement
170
198
  requirements:
171
199
  - - '>='
172
200
  - !ruby/object:Gem::Version
173
- version: '0'
201
+ version: 4.0.0.rc1
174
202
  type: :runtime
175
203
  prerelease: false
176
204
  version_requirements: !ruby/object:Gem::Requirement
177
205
  requirements:
178
206
  - - '>='
179
207
  - !ruby/object:Gem::Version
180
- version: '0'
208
+ version: 4.0.0.rc1
181
209
  - !ruby/object:Gem::Dependency
182
- name: uglifier
210
+ name: slim
183
211
  requirement: !ruby/object:Gem::Requirement
184
212
  requirements:
185
213
  - - '>='
186
214
  - !ruby/object:Gem::Version
187
- version: 1.0.3
215
+ version: '0'
188
216
  type: :runtime
189
217
  prerelease: false
190
218
  version_requirements: !ruby/object:Gem::Requirement
191
219
  requirements:
192
220
  - - '>='
193
221
  - !ruby/object:Gem::Version
194
- version: 1.0.3
222
+ version: '0'
195
223
  - !ruby/object:Gem::Dependency
196
- name: weak_parameters
224
+ name: uglifier
197
225
  requirement: !ruby/object:Gem::Requirement
198
226
  requirements:
199
227
  - - '>='
200
228
  - !ruby/object:Gem::Version
201
- version: 0.0.3
229
+ version: 1.3.0
202
230
  type: :runtime
203
231
  prerelease: false
204
232
  version_requirements: !ruby/object:Gem::Requirement
205
233
  requirements:
206
234
  - - '>='
207
235
  - !ruby/object:Gem::Version
208
- version: 0.0.3
236
+ version: 1.3.0
209
237
  - !ruby/object:Gem::Dependency
210
- name: bundler
238
+ name: weak_parameters
211
239
  requirement: !ruby/object:Gem::Requirement
212
240
  requirements:
213
- - - ~>
241
+ - - '>='
214
242
  - !ruby/object:Gem::Version
215
- version: '1.3'
216
- type: :development
243
+ version: '0'
244
+ type: :runtime
217
245
  prerelease: false
218
246
  version_requirements: !ruby/object:Gem::Requirement
219
247
  requirements:
220
- - - ~>
248
+ - - '>='
221
249
  - !ruby/object:Gem::Version
222
- version: '1.3'
250
+ version: '0'
223
251
  - !ruby/object:Gem::Dependency
224
- name: pry-rails
252
+ name: bundler
225
253
  requirement: !ruby/object:Gem::Requirement
226
254
  requirements:
227
255
  - - '>='
@@ -235,7 +263,7 @@ dependencies:
235
263
  - !ruby/object:Gem::Version
236
264
  version: '0'
237
265
  - !ruby/object:Gem::Dependency
238
- name: thin
266
+ name: pry-rails
239
267
  requirement: !ruby/object:Gem::Requirement
240
268
  requirements:
241
269
  - - '>='
@@ -258,6 +286,11 @@ extra_rdoc_files: []
258
286
  files:
259
287
  - app/assets/images/rails.png
260
288
  - app/assets/javascripts/application.js
289
+ - app/assets/javascripts/events.js.coffee
290
+ - app/assets/javascripts/magi/job_model.js.coffee
291
+ - app/assets/javascripts/magi/job_view.js.coffee
292
+ - app/assets/javascripts/magi/server_event.js.coffee
293
+ - app/assets/javascripts/magi.js.coffee
261
294
  - app/assets/stylesheets/application.css
262
295
  - app/assets/stylesheets/builds.scss
263
296
  - app/assets/stylesheets/common.scss
@@ -266,6 +299,7 @@ files:
266
299
  - app/assets/stylesheets/mixin.scss
267
300
  - app/controllers/application_controller.rb
268
301
  - app/controllers/builds_controller.rb
302
+ - app/controllers/events_controller.rb
269
303
  - app/controllers/jobs_controller.rb
270
304
  - app/helpers/application_helper.rb
271
305
  - app/models/build.rb
@@ -291,6 +325,7 @@ files:
291
325
  - config/initializers/inflections.rb
292
326
  - config/initializers/load_plugins.rb
293
327
  - config/initializers/mime_types.rb
328
+ - config/initializers/redis.rb
294
329
  - config/initializers/secret_token.rb
295
330
  - config/initializers/session_store.rb
296
331
  - config/initializers/wrap_parameters.rb
@@ -303,9 +338,11 @@ files:
303
338
  - db/schema.rb
304
339
  - db/seeds.rb
305
340
  - lib/magi/command.rb
341
+ - lib/magi/configuration.rb
306
342
  - lib/magi/executer.rb
307
343
  - lib/magi/plugin_manager.rb
308
344
  - lib/magi/proprietary.rb
345
+ - lib/magi/responder.rb
309
346
  - lib/magi/scheduler.rb
310
347
  - lib/magi/version.rb
311
348
  - lib/magi/workspace.rb