magi 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7b4d28573a8ed0497572635a79c1430e27e61e50
4
- data.tar.gz: 108e5eca7dd38c7edde9527ebb4cd7efda53412c
3
+ metadata.gz: 2db7f5dff13d75dd26fc1c8440bbb8cb68b51c92
4
+ data.tar.gz: 10ca4a6e4a4619df58bbc5a2f3c741c113cbf629
5
5
  SHA512:
6
- metadata.gz: ff4eca110f647870737e4ec032819f0b2919e7f70551f92f17f279e78ea312b203da5e5927caedbd582ccdf10e8e362b7b949cb4d4ccb09978312a9c1dbc7fe7
7
- data.tar.gz: 5080f4adeae11f1bb33e8e31d7a9910b62e1de6d787d07ce7ff581993f8d45bdabd3cdb7d94c6bb95c72e724b53901b0ade57cdeb90c437c8d7cafa51f1b86f9
6
+ metadata.gz: a637eed71179f9ccda64cc6185d439f3ee432413da2e8448bd48b38bbe4e733191312368c934634316ba85d3128c390109af6eaa161a1646d7371b68f1c22aa4
7
+ data.tar.gz: 705a9126445b1f52b78b957718e3484937366b5d03f69c8dc7f5e316d1db4add2fc86ca4eca850a6acf1606738c9ca7c221acdc3100dbd51c6c0e232d08bfcda
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ require "pathname"
2
+
1
3
  source "https://rubygems.org"
2
4
 
3
5
  gemspec
@@ -27,3 +29,8 @@ group :assets do
27
29
  gem "coffee-rails", "~> 3.2.1"
28
30
  gem "uglifier", ">= 1.0.3"
29
31
  end
32
+
33
+ # Put Gemfile in plugins/:name/Gemfile to use arbitrary gems in your plugin.
34
+ Pathname.glob("plugins/*/Gemfile").each do |pathname|
35
+ eval(pathname.read)
36
+ end
data/README.md CHANGED
@@ -25,8 +25,6 @@ Magi is just a rails application with some middlewares.
25
25
 
26
26
  ## Todo
27
27
  * async update by ajax
28
- * plugin system
29
- * git integration
30
28
  * command-line options
31
29
 
32
30
  ## API
@@ -16,7 +16,7 @@ class BuildsController < ApplicationController
16
16
  end
17
17
 
18
18
  def create
19
- resource = @job.enqueue
19
+ resource = @job.enqueue_without_before_enqueues
20
20
  respond_with resource, location: [@job, resource]
21
21
  end
22
22
 
data/app/models/build.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  class Build < ActiveRecord::Base
2
- extend Magi::Proprietary
2
+ include Magi::Proprietary
3
3
 
4
4
  attr_accessible :finished_at, :started_at, :output, :properties, :status
5
5
 
data/app/models/job.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  class Job < ActiveRecord::Base
2
- extend Magi::Proprietary
2
+ include Magi::Proprietary
3
3
 
4
4
  attr_accessible :name, :properties
5
5
 
@@ -20,24 +20,40 @@ class Job < ActiveRecord::Base
20
20
  new.update_attributes_with_properties(params)
21
21
  end
22
22
 
23
- def enqueue_with_before_hooks
24
- select(&:scheduled?).each(&:enqueue_with_before_hooks)
23
+ def scheduled
24
+ select(&:scheduled?)
25
25
  end
26
26
 
27
- def before_hook(&block)
28
- before_hooks << block
27
+ def before_enqueue(&block)
28
+ before_enqueues << block
29
29
  end
30
30
 
31
- def before_hooks
32
- @before_hooks ||= []
31
+ def before_enqueues
32
+ @before_enqueues ||= []
33
33
  end
34
34
 
35
- def after_hook(&block)
36
- after_hooks << block
35
+ def after_enqueue(&block)
36
+ after_enqueues << block
37
37
  end
38
38
 
39
- def after_hooks
40
- @after_hooks ||= []
39
+ def after_enqueues
40
+ @after_enqueues ||= []
41
+ end
42
+
43
+ def before_execute(&block)
44
+ before_executes << block
45
+ end
46
+
47
+ def before_executes
48
+ @before_executes ||= []
49
+ end
50
+
51
+ def after_execute(&block)
52
+ after_executes << block
53
+ end
54
+
55
+ def after_executes
56
+ @after_executes ||= []
41
57
  end
42
58
  end
43
59
 
@@ -59,9 +75,19 @@ class Job < ActiveRecord::Base
59
75
  builds.create.tap(&:enqueue)
60
76
  end
61
77
 
62
- def enqueue_with_before_hooks
63
- enqueue if execute_before_hooks
78
+ def enqueue_with_before_enqueues
79
+ if self.class.before_enqueues.all? {|hook| instance_exec(&hook) != false }
80
+ enqueue_without_before_enqueues
81
+ end
64
82
  end
83
+ alias_method_chain :enqueue, :before_enqueues
84
+
85
+ def enqueue_with_after_enqueues
86
+ enqueue_without_after_enqueues.tap do
87
+ self.class.after_enqueues.all? {|hook| instance_exec(&hook) != false }
88
+ end
89
+ end
90
+ alias_method_chain :enqueue, :after_enqueues
65
91
 
66
92
  def status_name
67
93
  last_finished_build.try(:status_name) || "unfinished"
@@ -82,24 +108,32 @@ class Job < ActiveRecord::Base
82
108
  tap(&:save)
83
109
  end
84
110
 
111
+ def workspace
112
+ @workspace ||= Magi::Workspace.new(workspace_path)
113
+ end
114
+
85
115
  private
86
116
 
87
- def execute
88
- Magi::Executer.execute(script)
117
+ def workspace_path
118
+ Magi.workspace.path + "jobs/#{id}"
89
119
  end
90
120
 
91
- def execute_with_after_hooks
92
- execute_without_after_hooks.tap { execute_after_hooks }
121
+ def execute
122
+ workspace.chdir { Magi::Executer.execute(script) }
93
123
  end
94
- alias_method_chain :execute, :after_hooks
95
124
 
96
- def execute_before_hooks
97
- self.class.before_hooks.all? {|hook| instance_exec(&hook) != false }
125
+ def execute_with_before_executes
126
+ self.class.before_executes.all? {|hook| instance_exec(&hook) != false }
127
+ execute_without_before_executes
98
128
  end
129
+ alias_method_chain :execute, :before_executes
99
130
 
100
- def execute_after_hooks
101
- self.class.after_hooks.all? {|hook| instance_exec(&hook) != false }
131
+ def execute_with_after_executes
132
+ execute_without_after_executes.tap do
133
+ self.class.after_executes.all? {|hook| instance_exec(&hook) != false }
134
+ end
102
135
  end
136
+ alias_method_chain :execute, :after_executes
103
137
 
104
138
  def raise_script_not_found
105
139
  raise ScriptNotFound, 'You must set properties["script"]'
@@ -3,7 +3,7 @@ class JobEnqueueWorker
3
3
 
4
4
  class << self
5
5
  def perform(id)
6
- Job.find(id).enqueue_with_before_hooks
6
+ Job.find(id).enqueue
7
7
  end
8
8
 
9
9
  def perform_async(id)
data/lib/magi/command.rb CHANGED
@@ -8,7 +8,7 @@
8
8
  # # Invokes "setup" command to set up your database.
9
9
  # Magi::Command.call(["setup"])
10
10
  #
11
- # # Invokes "start" command to start redis, rails, and sidekiq processes.
11
+ # # Invokes "start" command to start the processes.
12
12
  # Magi::Command.call(["start"])
13
13
  #
14
14
  module Magi
@@ -43,11 +43,19 @@ module Magi
43
43
  end
44
44
 
45
45
  def start
46
- system("cd #{root_path} && foreman start")
46
+ system(env, "cd #{root_path} && foreman start")
47
47
  end
48
48
 
49
49
  def root_path
50
50
  File.expand_path("../../..", __FILE__)
51
51
  end
52
+
53
+ def workspace_path
54
+ Dir.pwd
55
+ end
56
+
57
+ def env
58
+ { "WORKSPACE_PATH" => workspace_path }
59
+ end
52
60
  end
53
61
  end
@@ -1,13 +1,21 @@
1
1
  module Magi
2
2
  class PluginManager
3
- def plugins_directory
4
- @plugins_directory ||= Rails.root + "plugins"
3
+ def plugins_directories
4
+ [Rails.root + "plugins", Pathname.pwd + "plugins"].uniq
5
5
  end
6
6
 
7
7
  def load_plugins
8
- Dir.glob("#{plugins_directory}/*/*.rb").sort.each do |path|
9
- require path
10
- end
8
+ plugin_filepaths.each {|path| require path }
9
+ end
10
+
11
+ private
12
+
13
+ def plugin_filepaths
14
+ Dir.glob("#{plugins_directories_pattern}/*/*.rb").sort
15
+ end
16
+
17
+ def plugins_directories_pattern
18
+ plugins_directories.join(",")
11
19
  end
12
20
  end
13
21
  end
@@ -1,19 +1,30 @@
1
1
  module Magi
2
2
  module Proprietary
3
- def property(name)
4
- properties << name
3
+ extend ActiveSupport::Concern
5
4
 
6
- define_method(name) do
7
- properties[name.to_s]
5
+ def update_properties(properties)
6
+ properties.each do |key, value|
7
+ send("#{key}=", value)
8
8
  end
9
+ save
10
+ end
11
+
12
+ module ClassMethods
13
+ def property(name)
14
+ properties << name
15
+
16
+ define_method(name) do
17
+ properties[name.to_s]
18
+ end
9
19
 
10
- define_method("#{name}=") do |value|
11
- properties[name.to_s] = value
20
+ define_method("#{name}=") do |value|
21
+ properties[name.to_s] = value
22
+ end
12
23
  end
13
- end
14
24
 
15
- def properties
16
- @properties ||= []
25
+ def properties
26
+ @properties ||= []
27
+ end
17
28
  end
18
29
  end
19
30
  end
data/lib/magi/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Magi
2
- VERSION = "0.0.6"
2
+ VERSION = "0.0.7"
3
3
  end
@@ -0,0 +1,26 @@
1
+ module Magi
2
+ class Workspace
3
+ attr_reader :path
4
+
5
+ def initialize(path)
6
+ @path = Pathname.new(path)
7
+ end
8
+
9
+ def chdir
10
+ mkpath_unless_exist
11
+ Dir.chdir(path) { yield }
12
+ end
13
+
14
+ def mkpath_unless_exist
15
+ mkpath unless exist?
16
+ end
17
+
18
+ def mkpath
19
+ path.mkpath
20
+ end
21
+
22
+ def exist?
23
+ path.exist?
24
+ end
25
+ end
26
+ end
data/lib/magi.rb CHANGED
@@ -1,9 +1,22 @@
1
1
  require "magi/command"
2
2
  require "magi/plugin_manager"
3
3
  require "magi/version"
4
+ require "magi/workspace"
4
5
 
5
6
  module Magi
6
- def self.plugin_manager
7
- @plugin_manager ||= Magi::PluginManager.new
7
+ class << self
8
+ def workspace
9
+ @workspace ||= Magi::Workspace.new(workspace_path)
10
+ end
11
+
12
+ def plugin_manager
13
+ @plugin_manager ||= Magi::PluginManager.new
14
+ end
15
+
16
+ private
17
+
18
+ def workspace_path
19
+ ENV["WORKSPACE_PATH"] || "."
20
+ end
8
21
  end
9
22
  end
data/magi.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.homepage = "https://github.com/r7kamura/magi"
13
13
  spec.license = "MIT"
14
14
 
15
- spec.files = Dir["{app,bin,config,db,lib,public,script,spec}/**/*"]
15
+ spec.files = Dir["{app,bin,config,db,lib,plugins,public,script,spec}/**/*"]
16
16
  spec.files += %w[
17
17
  Gemfile
18
18
  LICENSE.txt
@@ -0,0 +1,84 @@
1
+ require "open3"
2
+
3
+ module Magi
4
+ class Repository
5
+ attr_reader :job
6
+
7
+ def initialize(job)
8
+ @job = job
9
+ end
10
+
11
+ def clone
12
+ validate_existence_of_git_url
13
+ command("git clone #{job.git_url} #{job.workspace.path}")
14
+ end
15
+
16
+ def update
17
+ command("cd #{job.workspace.path} && git pull")
18
+ end
19
+
20
+ def revision
21
+ command("cd #{job.workspace.path} && git rev-parse HEAD").rstrip
22
+ end
23
+
24
+ def updated?
25
+ revision != job.last_finished_build.try(:revision)
26
+ end
27
+
28
+ def cloned?
29
+ job.workspace.path.join(".git").exist?
30
+ end
31
+
32
+ private
33
+
34
+ def command(script)
35
+ Open3.capture3(script)[0]
36
+ end
37
+
38
+ def validate_existence_of_git_url
39
+ raise GitUrlNotFound unless job.git_url
40
+ end
41
+
42
+ class GitUrlNotFound < StandardError
43
+ def message
44
+ "You must set `git_url`"
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ Job.class_eval do
51
+ property(:git_url)
52
+
53
+ before_enqueue do
54
+ if git_url.present?
55
+ repository.clone unless repository.cloned?
56
+ repository.update
57
+ repository.updated?
58
+ end
59
+ end
60
+
61
+ before_execute do
62
+ if git_url.present?
63
+ repository.clone unless repository.cloned?
64
+ end
65
+ end
66
+
67
+ after_execute do
68
+ if git_url.present?
69
+ current_build.update_revision
70
+ end
71
+ end
72
+
73
+ def repository
74
+ @repository ||= Magi::Repository.new(self)
75
+ end
76
+ end
77
+
78
+ Build.class_eval do
79
+ property(:revision)
80
+
81
+ def update_revision
82
+ update_properties(revision: job.repository.revision)
83
+ end
84
+ end
data/script/clock.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require File.expand_path("../../config/environment.rb", __FILE__)
2
2
 
3
3
  Clockwork.every(1.minute, "JobEnqueueWorker") do
4
- Job.enqueue_with_before_hooks
4
+ Job.scheduled.each(&:enqueue)
5
5
  end
@@ -2,11 +2,15 @@ require "spec_helper"
2
2
 
3
3
  describe Job do
4
4
  let(:job) do
5
- FactoryGirl.create(:job)
5
+ FactoryGirl.create(:job, properties: { "script" => "true" })
6
6
  end
7
7
 
8
8
  describe "#start" do
9
9
  context "without script" do
10
+ before do
11
+ job.script = nil
12
+ end
13
+
10
14
  it "raises Job::ScriptNotFound" do
11
15
  expect { job.start }.to raise_error(Job::ScriptNotFound)
12
16
  end
@@ -52,37 +56,35 @@ describe Job do
52
56
  end
53
57
  end
54
58
 
55
- describe "#enqueue_with_before_hooks" do
59
+ describe "#enqueue" do
56
60
  before do
57
- Job.before_hooks.clear
61
+ Job.before_enqueues.clear
58
62
  end
59
63
 
60
64
  after do
61
- Job.before_hooks.clear
65
+ Job.before_enqueues.clear
62
66
  end
63
67
 
64
68
  context "with successful hooks" do
65
69
  before do
66
- Job.before_hook { Job.hook_is_executed }
70
+ Job.before_enqueue { Job.hook_is_executed }
67
71
  end
68
72
 
69
73
  it "enqueues a new build" do
70
74
  Job.should_receive(:hook_is_executed)
71
- job.should_receive(:enqueue)
72
- job.enqueue_with_before_hooks
75
+ job.enqueue
73
76
  end
74
77
  end
75
78
 
76
79
  context "with failed hooks" do
77
80
  before do
78
- Job.before_hook { false }
79
- Job.before_hook { Job.hook_is_executed }
81
+ Job.before_enqueue { false }
82
+ Job.before_enqueue { Job.hook_is_executed }
80
83
  end
81
84
 
82
85
  it "stops at failed hook" do
83
86
  Job.should_not_receive(:hook_is_executed)
84
- job.should_not_receive(:enqueue)
85
- job.enqueue_with_before_hooks
87
+ job.enqueue
86
88
  end
87
89
  end
88
90
  end
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.6
4
+ version: 0.0.7
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-11 00:00:00.000000000 Z
11
+ date: 2013-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clockwork
@@ -308,8 +308,10 @@ files:
308
308
  - lib/magi/proprietary.rb
309
309
  - lib/magi/scheduler.rb
310
310
  - lib/magi/version.rb
311
+ - lib/magi/workspace.rb
311
312
  - lib/magi.rb
312
313
  - lib/tasks/resque.rake
314
+ - plugins/git/git.rb
313
315
  - public/404.html
314
316
  - public/422.html
315
317
  - public/500.html