magi 0.0.7 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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