jenkins-plugin-runtime 0.1.18 → 0.1.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/README.md +12 -0
  2. data/Rakefile +2 -1
  3. data/jenkins-plugin-runtime.gemspec +2 -1
  4. data/lib/core_ext/exception.rb +36 -0
  5. data/lib/jenkins/cli/command.rb +167 -0
  6. data/lib/jenkins/cli/command_proxy.rb +62 -0
  7. data/lib/jenkins/filepath.rb +1 -6
  8. data/lib/jenkins/launcher.rb +4 -14
  9. data/lib/jenkins/model.rb +8 -41
  10. data/lib/jenkins/model/action.rb +1 -9
  11. data/lib/jenkins/model/build.rb +4 -5
  12. data/lib/jenkins/model/describable.rb +16 -30
  13. data/lib/jenkins/model/root_action.rb +2 -2
  14. data/lib/jenkins/plugin.rb +61 -12
  15. data/lib/jenkins/plugin/behavior.rb +96 -0
  16. data/lib/jenkins/plugin/proxies.rb +4 -0
  17. data/lib/jenkins/plugin/proxies/action.rb +10 -6
  18. data/lib/jenkins/plugin/proxies/build_step.rb +1 -0
  19. data/lib/jenkins/plugin/proxies/build_wrapper.rb +2 -5
  20. data/lib/jenkins/plugin/proxies/builder.rb +1 -5
  21. data/lib/jenkins/plugin/proxies/describable.rb +6 -0
  22. data/lib/jenkins/plugin/proxies/publisher.rb +1 -5
  23. data/lib/jenkins/plugin/proxies/root_action.rb +2 -17
  24. data/lib/jenkins/plugin/proxy.rb +27 -6
  25. data/lib/jenkins/plugin/runtime.rb +3 -0
  26. data/lib/jenkins/plugin/runtime/version.rb +1 -1
  27. data/lib/jenkins/plugin/wrapper.rb +29 -0
  28. data/spec/jenkins/cli/command_proxy_spec.rb +5 -0
  29. data/spec/jenkins/cli/command_spec.rb +5 -0
  30. data/spec/jenkins/launcher_spec.rb +0 -4
  31. data/spec/jenkins/model/action_spec.rb +2 -1
  32. data/spec/jenkins/model/build_spec.rb +2 -3
  33. data/spec/jenkins/model/describable_spec.rb +22 -7
  34. data/spec/jenkins/model_spec.rb +0 -28
  35. data/spec/jenkins/plugin/behavior_spec.rb +109 -0
  36. data/spec/jenkins/plugin/proxy_spec.rb +14 -0
  37. data/spec/jenkins/plugin_spec.rb +20 -0
  38. data/spec/spec_helper.rb +11 -5
  39. metadata +34 -13
  40. data/spec/mockito-all-1.8.5.jar +0 -0
@@ -10,11 +10,12 @@ module Jenkins
10
10
  #
11
11
  # This module provides common functionality for all proxies.
12
12
  module Proxy
13
- def self.included(mod)
14
- super
15
- mod.extend(Marshal)
16
- mod.send(:include, Unmarshal)
17
- mod.send(:include, Customs)
13
+ extend Plugin::Behavior
14
+
15
+ implemented do |cls|
16
+ cls.class_eval do
17
+ include Java.org.kohsuke.stapler.StaplerProxy
18
+ end
18
19
  end
19
20
 
20
21
  # Every Proxy object has a reference to the plugin to which it belongs, as well as the
@@ -30,11 +31,21 @@ module Jenkins
30
31
  end
31
32
 
32
33
  # tell Stapler to go look for views from the wrapped object
33
- include Java.org.kohsuke.stapler.StaplerProxy
34
34
  def getTarget
35
35
  @object
36
36
  end
37
37
 
38
+ # Used to specify which Ruby class this will act as a proxy
39
+ module ProxyFor
40
+ # register this class as a proxy for `internal_class`. Jenkins
41
+ # will auto-create instances of this class when passing to
42
+ # ruby and vice-versa
43
+ def proxy_for(internal_class)
44
+ fail "not a ruby class" unless internal_class.is_a? Class
45
+ Jenkins::Plugin::Proxies.register internal_class, self
46
+ end
47
+ end
48
+
38
49
  # Make sure that proxy classes do not try to persist the plugin parameter.
39
50
  # when serializing this proxy to XStream. It will be reconstructed with
40
51
  # [Unmarshal#read_completed]
@@ -78,6 +89,16 @@ module Jenkins
78
89
  @plugin.export(object)
79
90
  end
80
91
  end
92
+
93
+ module ClassMethods
94
+ include Marshal
95
+ include ProxyFor
96
+ end
97
+
98
+ module InstanceMethods
99
+ include Unmarshal
100
+ include Customs
101
+ end
81
102
  end
82
103
  end
83
104
  end
@@ -1,9 +1,12 @@
1
1
  require 'jenkins/plugin'
2
+ require 'jenkins/plugin/behavior'
3
+ require 'jenkins/plugin/wrapper'
2
4
  require 'jenkins/plugin/specification'
3
5
  require 'jenkins/plugin/runtime/version'
4
6
  require 'jenkins/plugin/proxy'
5
7
  require 'jenkins/plugin/proxies/describable'
6
8
  require 'jenkins/plugin/proxies'
9
+ require 'jenkins/cli/command'
7
10
  require 'jenkins/model'
8
11
  require 'jenkins/model/action'
9
12
  require 'jenkins/model/root_action'
@@ -1,7 +1,7 @@
1
1
  module Jenkins
2
2
  class Plugin
3
3
  module Runtime
4
- VERSION = "0.1.18"
4
+ VERSION = "0.1.20"
5
5
  end
6
6
  end
7
7
  end
@@ -0,0 +1,29 @@
1
+ class Jenkins::Plugin
2
+ # Proxies provide a lens through which the Java world sees a Ruby
3
+ # object. On the other hand, Wrappers are a lens through which
4
+ # the Ruby world sees a Java object.
5
+ module Wrapper
6
+ extend Behavior
7
+
8
+ # The native [java.lang.Object] which this object wraps
9
+ attr_reader :native
10
+
11
+ def initialize(*args)
12
+ @native, = *args
13
+ end
14
+
15
+ module ClassMethods
16
+
17
+ # Declare a wrapper class to wrap a certain type of
18
+ # java class. The plugin runtime will maintain this
19
+ # mapping so that whenever it sees an object coming
20
+ # in from Java, it knows the appropriate wrapper
21
+ # class to choose.
22
+ #
23
+ # @param [java.lang.Class] the java class equivalent
24
+ def wrapper_for(java_class)
25
+ Jenkins::Plugin::Proxies.register self, java_class
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jenkins::CLI::CommandProxy do
4
+ it 'works and is testable *cough* @kohsuke *cough*'
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jenkins::CLI::Command do
4
+ it 'works and is testable *cough* @kohsuke *cough*'
5
+ end
@@ -10,10 +10,6 @@ describe Jenkins::Launcher do
10
10
  @launcher = Jenkins::Launcher.new(@native)
11
11
  end
12
12
 
13
- it "can be instantiated" do
14
- Jenkins::Launcher.new
15
- end
16
-
17
13
  describe "execute" do
18
14
  it "passes a simple command to a native launcher" do
19
15
  @starter.should_receive(:envs).with({})
@@ -35,7 +35,8 @@ describe Jenkins::Model::Action do
35
35
  private
36
36
 
37
37
  def new_action(&body)
38
- action = Class.new(Jenkins::Model::Action)
38
+ action = Class.new
39
+ action.send(:include, Jenkins::Model::Action)
39
40
  action.class_eval(&body) if block_given?
40
41
  return action
41
42
  end
@@ -5,8 +5,8 @@ describe Jenkins::Model::Build do
5
5
  include SpecHelper
6
6
 
7
7
  before :each do
8
- @native = mockito(Java.hudson.model.AbstractBuild)
9
- @native.buildEnvironments = java.util.ArrayList.new
8
+ @native = mock(Java.hudson.model.AbstractBuild)
9
+ @native.stub(:buildEnvironments).and_return(java.util.ArrayList.new)
10
10
  @build = Jenkins::Model::Build.new(@native)
11
11
  end
12
12
 
@@ -50,7 +50,6 @@ describe Jenkins::Model::Build do
50
50
  pending "we need to get some full stack testing for this to fully work"
51
51
  @build.env['FOO'] = 'bar'
52
52
  @build.env[:bar] = :baz
53
- Java.org.mockito.Mockito.when(@native.getEvironment(nil)).thenCallRealMethod()
54
53
  @vars = @native.getEnvironment(nil)
55
54
  end
56
55
 
@@ -4,14 +4,14 @@ describe Jenkins::Model::Describable do
4
4
 
5
5
  before do
6
6
  @plugin = mock(Jenkins::Plugin)
7
- Jenkins::Plugin.stub(:instance).and_return(@plugin)
7
+ Jenkins.stub(:plugin).and_return(@plugin)
8
8
  end
9
9
 
10
10
  describe "when mixed into a class" do
11
11
  before do
12
12
  @class = Class.new
13
- @class.send(:include, Jenkins::Model::Describable)
14
13
  @plugin.stub(:register_describable)
14
+ @class.send(:include, Jenkins::Model::Describable)
15
15
  end
16
16
 
17
17
 
@@ -30,11 +30,17 @@ describe Jenkins::Model::Describable do
30
30
  describe "a subclass of that class" do
31
31
  before do
32
32
  @class.describe_as java.lang.Object
33
+ def @class.to_s; "SuperClass" end
33
34
  @subclass = Class.new(@class)
35
+ def @subclass.to_s; "SubClass" end
34
36
  end
35
37
 
36
- it "is registered as an extension of the java type" do
37
- @plugin.should have_received(:register_describable).with(@subclass, java.lang.Object.java_class, nil)
38
+ it "is registered as an extension" do
39
+ @plugin.should have_received(:register_describable).with(@subclass)
40
+ end
41
+
42
+ it "has the same java type as its superclass" do
43
+ @subclass.describe_as_type.should eql java.lang.Object.java_class
38
44
  end
39
45
 
40
46
  describe ". a sub-subclass" do
@@ -43,20 +49,29 @@ describe Jenkins::Model::Describable do
43
49
  end
44
50
 
45
51
  it "is also registered as an extension of the original java type" do
46
- @plugin.should have_received(:register_describable).with(@subsubclass, java.lang.Object.java_class, nil)
52
+ @plugin.should have_received(:register_describable).with(@subsubclass)
53
+ end
54
+
55
+ it 'inherits its describe_as_type' do
56
+ @subsubclass.describe_as_type.should eql java.lang.Object.java_class
47
57
  end
48
58
  end
49
59
  end
50
60
 
51
61
  describe "with a custom descriptor type" do
52
- it "registers that custom descriptor" do
62
+ before do
53
63
  @class.describe_as java.lang.Object, :with => java.lang.String
54
64
  @subclass = Class.new(@class)
55
- @plugin.should have_received(:register_describable).with(@subclass, java.lang.Object.java_class, java.lang.String.java_class)
65
+ end
66
+ it "registers that custom descriptor" do
67
+ @plugin.should have_received(:register_describable).with(@subclass)
56
68
  end
57
69
  it "must be a real java class" do
58
70
  lambda {@class.describe_as java.lang.Object, :with => Object}.should raise_error(Jenkins::Model::Describable::DescribableError)
59
71
  end
72
+ it "inherits the descriptor type" do
73
+ @subclass.descriptor_is.should eql java.lang.String.java_class
74
+ end
60
75
  end
61
76
  end
62
77
  end
@@ -61,34 +61,6 @@ describe Jenkins::Model do
61
61
  child.should be_transient(:bar)
62
62
  end
63
63
 
64
- describe "tracking descendants" do
65
- before do
66
- Model.clear
67
- end
68
-
69
- it "captures including classes" do
70
- cls = Class.new
71
- cls.send(:include, Model)
72
- Model.should be_descendant cls
73
- end
74
-
75
- it "captures classes that extend including classes" do
76
- cls = Class.new
77
- cls.send(:include, Model)
78
- Model.should be_descendant(Class.new(cls))
79
- end
80
-
81
- it "captures classes that include including modules" do
82
- m1 = Module.new
83
- m1.send(:include, Model)
84
- m2 = Module.new
85
- m2.send(:include, m1)
86
- cls = Class.new
87
- cls.send(:include, m2)
88
- Model.should be_descendant(Class.new(cls))
89
- end
90
- end
91
-
92
64
  private
93
65
 
94
66
  def new_model(&block)
@@ -0,0 +1,109 @@
1
+ require 'spec_helper'
2
+ require 'jenkins/plugin/behavior'
3
+
4
+ describe Jenkins::Plugin::Behavior do
5
+ before do
6
+ module OhBehave
7
+ extend Jenkins::Plugin::Behavior
8
+ @implementations = []
9
+ def self.implementations
10
+ @implementations
11
+ end
12
+ implemented do |impl|
13
+ @implementations << impl
14
+ end
15
+ module Foo
16
+ def foo; 'foo' end
17
+ end
18
+ module Bar
19
+ def bar; 'bar' end
20
+ end
21
+ module Baz
22
+ def baz; 'baz' end
23
+ end
24
+ module Qux
25
+ def qux; 'qux' end
26
+ end
27
+ module InstanceMethods
28
+ include Foo
29
+ include Bar
30
+ end
31
+ module ClassMethods
32
+ include Baz
33
+ include Qux
34
+ end
35
+ end
36
+ end
37
+ describe "when a behavior is included into a class" do
38
+ before do
39
+ @class = Class.new
40
+ def @class.to_s; 'Behaving' end
41
+ @class.send(:include, OhBehave)
42
+ end
43
+
44
+ its "methods in ClassMethods are available to the implementing class" do
45
+ @class.baz.should eql 'baz'
46
+ @class.qux.should eql 'qux'
47
+ end
48
+
49
+ its "methods in the InstanceMethods module are available to instances" do
50
+ @class.new.tap do |i|
51
+ i.foo.should eql 'foo'
52
+ i.bar.should eql 'bar'
53
+ end
54
+ end
55
+
56
+ its "implementation block is invoked" do
57
+ OhBehave.implementations.should be_member @class
58
+ end
59
+
60
+ describe "and then that class is subclassed" do
61
+ before do
62
+ @subclass = Class.new(@class)
63
+ def @subclass.to_s; 'BehavingSubclass' end
64
+ end
65
+
66
+ its "methods in ClassMethods are available to the subclass" do
67
+ @subclass.baz.should eql 'baz'
68
+ @subclass.qux.should eql 'qux'
69
+ end
70
+
71
+ its 'methods in InstanceMethods are available to subclass instances' do
72
+ @subclass.new.foo.should eql 'foo'
73
+ @subclass.new.bar.should eql 'bar'
74
+ end
75
+
76
+ its 'implementation block is invoked with the subclass' do
77
+ OhBehave.implementations.should be_member @subclass
78
+ end
79
+
80
+ describe ". If it is subclassed yet again" do
81
+ before do
82
+ @subsubclass = Class.new(@subclass)
83
+ def @subsubclass.to_s; "BehavingSubSubClass" end
84
+ end
85
+ its 'implementatin block is invoked with the sub-sub-class' do
86
+ OhBehave.implementations.should be_member @subsubclass
87
+ end
88
+ end
89
+ end
90
+ end
91
+ describe 'when a behavior is included into another module' do
92
+ before do
93
+ @module = Module.new
94
+ @module.send(:include, OhBehave)
95
+ @class = Class.new(Object)
96
+ @class.send(:include, @module)
97
+ end
98
+ it 'reaches classes the module includes' do
99
+ @class.baz.should eql 'baz'
100
+ @class.new.foo.should eql 'foo'
101
+ end
102
+ its 'implementation callback is invoked for classes including that module' do
103
+ OhBehave.implementations.should be_member @class
104
+ end
105
+ its 'implementation callback is NOT invoked for any intervening modules' do
106
+ OhBehave.implementations.should_not be_member @module
107
+ end
108
+ end
109
+ end
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'rspec-spies'
2
3
 
3
4
  describe "a class with #{Jenkins::Plugin::Proxy} mixed in" do
4
5
 
@@ -40,4 +41,17 @@ describe "a class with #{Jenkins::Plugin::Proxy} mixed in" do
40
41
  end
41
42
  end
42
43
 
44
+ describe "specifiying which ruby class it proxies" do
45
+ before do
46
+ @proxies = Jenkins::Plugin::Proxies
47
+ @proxies.stub(:register)
48
+ @class.class_eval do
49
+ proxy_for String
50
+ end
51
+ end
52
+
53
+ it 'registers it with the global proxy registry' do
54
+ @proxies.should have_received(:register).with(String, @class)
55
+ end
56
+ end
43
57
  end
@@ -3,6 +3,26 @@ require 'tmpdir'
3
3
 
4
4
  describe Jenkins::Plugin do
5
5
 
6
+ describe Jenkins::Plugin::Lifecycle do
7
+ before do |variable|
8
+ @plugin = Jenkins::Plugin.new mock(:name => 'org.jenkinsci.ruby.RubyPlugin')
9
+ @plugin.on.start do |plugin|
10
+ @start = plugin
11
+ end
12
+ @plugin.on.stop do |plugin|
13
+ @stop = plugin
14
+ end
15
+ @plugin.start
16
+ @plugin.stop
17
+ end
18
+ it "gets a callback on start" do
19
+ @start.should be @plugin
20
+ end
21
+ it "gets a callback on stop" do
22
+ @stop.should be @plugin
23
+ end
24
+ end
25
+
6
26
  describe "when plugin loads models" do
7
27
  include SpecHelper
8
28
 
@@ -1,6 +1,12 @@
1
1
  require 'java'
2
2
  require 'tmpdir'
3
3
 
4
+ module Jenkins
5
+ def self.rspec_ewwww_gross_hack?
6
+ true
7
+ end
8
+ end
9
+
4
10
  require 'jenkins/war'
5
11
  for path in Dir[File.join(ENV['HOME'], '.jenkins', 'wars', Jenkins::War::VERSION, "**/*.jar")]
6
12
  $CLASSPATH << path
@@ -10,7 +16,11 @@ $:.unshift Pathname(__FILE__).dirname.join('../lib')
10
16
 
11
17
  require 'jenkins/plugin/runtime'
12
18
  require 'jenkins/plugin/proxies/proxy_helper'
13
- require File.expand_path '../mockito-all-1.8.5.jar', __FILE__
19
+
20
+ def puts(msg = nil)
21
+ require 'erb'
22
+ super ERB::Util.h(msg) + "<br/>"
23
+ end
14
24
 
15
25
  module SpecHelper
16
26
  # Java does not support opening directory as a File: File.open(".")
@@ -43,8 +53,4 @@ module SpecHelper
43
53
  f << content
44
54
  end
45
55
  end
46
-
47
- def mockito(cls)
48
- Java.org.mockito.Mockito.mock(cls.java_class)
49
- end
50
56
  end