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.
- data/README.md +12 -0
- data/Rakefile +2 -1
- data/jenkins-plugin-runtime.gemspec +2 -1
- data/lib/core_ext/exception.rb +36 -0
- data/lib/jenkins/cli/command.rb +167 -0
- data/lib/jenkins/cli/command_proxy.rb +62 -0
- data/lib/jenkins/filepath.rb +1 -6
- data/lib/jenkins/launcher.rb +4 -14
- data/lib/jenkins/model.rb +8 -41
- data/lib/jenkins/model/action.rb +1 -9
- data/lib/jenkins/model/build.rb +4 -5
- data/lib/jenkins/model/describable.rb +16 -30
- data/lib/jenkins/model/root_action.rb +2 -2
- data/lib/jenkins/plugin.rb +61 -12
- data/lib/jenkins/plugin/behavior.rb +96 -0
- data/lib/jenkins/plugin/proxies.rb +4 -0
- data/lib/jenkins/plugin/proxies/action.rb +10 -6
- data/lib/jenkins/plugin/proxies/build_step.rb +1 -0
- data/lib/jenkins/plugin/proxies/build_wrapper.rb +2 -5
- data/lib/jenkins/plugin/proxies/builder.rb +1 -5
- data/lib/jenkins/plugin/proxies/describable.rb +6 -0
- data/lib/jenkins/plugin/proxies/publisher.rb +1 -5
- data/lib/jenkins/plugin/proxies/root_action.rb +2 -17
- data/lib/jenkins/plugin/proxy.rb +27 -6
- data/lib/jenkins/plugin/runtime.rb +3 -0
- data/lib/jenkins/plugin/runtime/version.rb +1 -1
- data/lib/jenkins/plugin/wrapper.rb +29 -0
- data/spec/jenkins/cli/command_proxy_spec.rb +5 -0
- data/spec/jenkins/cli/command_spec.rb +5 -0
- data/spec/jenkins/launcher_spec.rb +0 -4
- data/spec/jenkins/model/action_spec.rb +2 -1
- data/spec/jenkins/model/build_spec.rb +2 -3
- data/spec/jenkins/model/describable_spec.rb +22 -7
- data/spec/jenkins/model_spec.rb +0 -28
- data/spec/jenkins/plugin/behavior_spec.rb +109 -0
- data/spec/jenkins/plugin/proxy_spec.rb +14 -0
- data/spec/jenkins/plugin_spec.rb +20 -0
- data/spec/spec_helper.rb +11 -5
- metadata +34 -13
- data/spec/mockito-all-1.8.5.jar +0 -0
data/lib/jenkins/plugin/proxy.rb
CHANGED
@@ -10,11 +10,12 @@ module Jenkins
|
|
10
10
|
#
|
11
11
|
# This module provides common functionality for all proxies.
|
12
12
|
module Proxy
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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'
|
@@ -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
|
@@ -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
|
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 =
|
9
|
-
@native.buildEnvironments
|
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
|
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
|
37
|
-
@plugin.should have_received(:register_describable).with(@subclass
|
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
|
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
|
-
|
62
|
+
before do
|
53
63
|
@class.describe_as java.lang.Object, :with => java.lang.String
|
54
64
|
@subclass = Class.new(@class)
|
55
|
-
|
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
|
data/spec/jenkins/model_spec.rb
CHANGED
@@ -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
|
data/spec/jenkins/plugin_spec.rb
CHANGED
@@ -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
|
|
data/spec/spec_helper.rb
CHANGED
@@ -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
|
-
|
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
|