jenkins-plugin-runtime 0.1.18 → 0.1.20

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 (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