jenkins-plugin-runtime 0.1.0

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 (41) hide show
  1. data/.gitignore +7 -0
  2. data/.travis.yml +2 -0
  3. data/Gemfile +4 -0
  4. data/Rakefile +21 -0
  5. data/jenkins-plugin-runtime.gemspec +30 -0
  6. data/lib/jenkins/launcher.rb +15 -0
  7. data/lib/jenkins/model.rb +91 -0
  8. data/lib/jenkins/model/action.rb +37 -0
  9. data/lib/jenkins/model/build.rb +21 -0
  10. data/lib/jenkins/model/describable.rb +75 -0
  11. data/lib/jenkins/model/descriptor.rb +40 -0
  12. data/lib/jenkins/model/listener.rb +47 -0
  13. data/lib/jenkins/plugin.rb +141 -0
  14. data/lib/jenkins/plugin/cli.rb +20 -0
  15. data/lib/jenkins/plugin/proxies.rb +131 -0
  16. data/lib/jenkins/plugin/proxies/build_wrapper.rb +50 -0
  17. data/lib/jenkins/plugin/proxies/builder.rb +22 -0
  18. data/lib/jenkins/plugin/proxy.rb +76 -0
  19. data/lib/jenkins/plugin/runtime.rb +13 -0
  20. data/lib/jenkins/plugin/runtime/version.rb +7 -0
  21. data/lib/jenkins/slaves/cloud.rb +9 -0
  22. data/lib/jenkins/tasks/build_wrapper.rb +39 -0
  23. data/lib/jenkins/tasks/builder.rb +33 -0
  24. data/spec/jenkins/launcher_spec.rb +8 -0
  25. data/spec/jenkins/model/action_spec.rb +36 -0
  26. data/spec/jenkins/model/build_spec.rb +8 -0
  27. data/spec/jenkins/model/describable_spec.rb +51 -0
  28. data/spec/jenkins/model/listener_spec.rb +31 -0
  29. data/spec/jenkins/model_spec.rb +100 -0
  30. data/spec/jenkins/plugin/proxies/build_wrapper_spec.rb +25 -0
  31. data/spec/jenkins/plugin/proxies/builder_spec.rb +24 -0
  32. data/spec/jenkins/plugin/proxies/proxy_helper.rb +24 -0
  33. data/spec/jenkins/plugin/proxies_spec.rb +148 -0
  34. data/spec/jenkins/plugin/proxy_spec.rb +43 -0
  35. data/spec/jenkins/plugin_spec.rb +7 -0
  36. data/spec/jenkins/tasks/build_wrapper_spec.rb +7 -0
  37. data/spec/jenkins/tasks/builder_spec.rb +8 -0
  38. data/spec/spec_helper.rb +11 -0
  39. data/src/jenkins/ruby/DoDynamic.java +18 -0
  40. data/src/jenkins/ruby/Get.java +18 -0
  41. metadata +175 -0
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jenkins::Model::Build do
4
+
5
+ it "can be instantiated" do
6
+ Jenkins::Model::Build.new(mock(Java.hudson.model.AbstractBuild))
7
+ end
8
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+ require 'rspec-spies'
3
+ describe Jenkins::Model::Describable do
4
+
5
+ before do
6
+ @plugin = mock(Jenkins::Plugin)
7
+ Jenkins::Plugin.stub(:instance).and_return(@plugin)
8
+ end
9
+
10
+ describe "when mixed into a class" do
11
+ before do
12
+ @class = Class.new
13
+ @class.send(:include, Jenkins::Model::Describable)
14
+ @plugin.stub(:register_describable)
15
+ end
16
+
17
+
18
+ it "can't be described as plain old object" do
19
+ lambda {@class.describe_as Object}.should raise_error(Jenkins::Model::Describable::DescribableError)
20
+ end
21
+
22
+ it "can't be described as plain old java object" do
23
+ lambda {@class.describe_as java.lang.Object.new}.should raise_error(Jenkins::Model::Describable::DescribableError)
24
+ end
25
+
26
+ it "must be described as a java.lang.Class" do
27
+ lambda {@class.describe_as java.lang.Object}.should_not raise_error
28
+ end
29
+
30
+ describe "a subclass of that class" do
31
+ before do
32
+ @class.describe_as java.lang.Object
33
+ @subclass = Class.new(@class)
34
+ end
35
+
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)
38
+ end
39
+
40
+ describe ". a sub-subclass" do
41
+ before do
42
+ @subsubclass = Class.new(@subclass)
43
+ end
44
+
45
+ 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)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jenkins::Model::Listener do
4
+
5
+ before do
6
+ @output = java.io.ByteArrayOutputStream.new
7
+ @java = Java.hudson.util.StreamTaskListener.new(@output)
8
+ @listener = Jenkins::Model::Listener.new(@java)
9
+ end
10
+
11
+ it "logs messages" do
12
+ @listener.log('Hi')
13
+ @output.toString.should eql "Hi"
14
+ end
15
+
16
+ it "logs errors" do
17
+ @listener.error('Oh no!')
18
+ @output.toString.should match /^ERROR: Oh no!/
19
+ end
20
+
21
+ it "logs fatal errors" do
22
+ @listener.fatal('boom!')
23
+ @output.toString.should match /^FATAL: boom!/
24
+ end
25
+
26
+ it "logs hyperlinks" do
27
+ @java.should_receive(:hyperlink).with("/foo/bar", "click here")
28
+ @listener.hyperlink("/foo/bar", "click here")
29
+ end
30
+ end
31
+
@@ -0,0 +1,100 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jenkins::Model do
4
+ Model = Jenkins::Model
5
+
6
+ it "has a display name which is settable via the class, and accessable via the class and instance" do
7
+ cls = new_model do
8
+ display_name "One-Off Class"
9
+ end
10
+ cls.display_name.should eql "One-Off Class"
11
+ cls.new.display_name.should eql "One-Off Class"
12
+ end
13
+
14
+ it "passes down display_name capabilities to subclasses" do
15
+ parent = new_model
16
+ child = Class.new(parent)
17
+ child.class_eval do
18
+ display_name "Child"
19
+ end
20
+ child.display_name.should eql "Child"
21
+ end
22
+
23
+ it "passes down display_name capabilities to submodules" do
24
+ submodule = Module.new
25
+ submodule.send(:include, Jenkins::Model)
26
+ cls = Class.new
27
+ cls.send(:include, submodule)
28
+ cls.display_name "SubAwesome"
29
+ cls.display_name.should eql "SubAwesome"
30
+ cls.new.display_name.should eql "SubAwesome"
31
+ end
32
+
33
+ it "has a default display name of the class name" do
34
+ cls = new_model do
35
+ def self.name
36
+ "AwesomeClass"
37
+ end
38
+ end
39
+ cls.display_name.should eql "AwesomeClass"
40
+ end
41
+
42
+ it "keeps a list of which of its properties are transient" do
43
+ cls = new_model do
44
+ transient :foo, :bar
45
+ end
46
+ cls.should be_transient(:foo)
47
+ cls.should be_transient(:bar)
48
+ cls.should_not be_transient(:baz)
49
+ end
50
+
51
+ it "includes parent classes's transient properties, but doesn't affect the parent property list" do
52
+ parent = new_model do
53
+ transient :foo
54
+ end
55
+ child = Class.new(parent)
56
+ child.class_eval do
57
+ transient :bar
58
+ end
59
+ parent.should_not be_transient(:bar)
60
+ child.should be_transient(:foo)
61
+ child.should be_transient(:bar)
62
+ end
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
+ private
93
+
94
+ def new_model(&block)
95
+ cls = Class.new
96
+ cls.send(:include, Jenkins::Model)
97
+ cls.class_eval(&block) if block_given?
98
+ return cls
99
+ end
100
+ end
@@ -0,0 +1,25 @@
1
+
2
+ require 'spec_helper'
3
+
4
+ describe Jenkins::Plugin::Proxies::BuildWrapper do
5
+ include ProxyHelper
6
+
7
+ subject {Jenkins::Plugin::Proxies::BuildWrapper}
8
+ it {should be_transient(:plugin)}
9
+
10
+ before do
11
+ @object = mock(Jenkins::Tasks::BuildWrapper)
12
+ @wrapper = Jenkins::Plugin::Proxies::BuildWrapper.new(@plugin, @object)
13
+ end
14
+
15
+ it "passes in an env file which will be called to " do
16
+ env = nil
17
+ @object.should_receive(:setup).with(@build, @launcher, @listener, an_instance_of(Hash)) do |*args|
18
+ env = args.last
19
+ end
20
+ environment = @wrapper.setUp(@jBuild, @jLauncher, @jListener)
21
+
22
+ @object.should_receive(:teardown).with(@build, @listener, env)
23
+ environment.tearDown(@jBuild, @jListener)
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jenkins::Plugin::Proxies::Builder do
4
+ include ProxyHelper
5
+
6
+ before do
7
+ @object = mock(Jenkins::Tasks::Builder)
8
+ @builder = Jenkins::Plugin::Proxies::Builder.new(@plugin, @object)
9
+ end
10
+
11
+ describe "prebuild" do
12
+ it "calls through to its implementation" do
13
+ @object.should_receive(:prebuild).with(@build, @launcher, @listener)
14
+ @builder.prebuild(@jBuild, @jLauncher, @jListener)
15
+ end
16
+ end
17
+
18
+ describe "perform" do
19
+ it "calls through to its implementation" do
20
+ @object.should_receive(:perform).with(@build, @launcher, @listener)
21
+ @builder.perform(@jBuild, @jLauncher, @jListener)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+
2
+ module ProxyHelper
3
+
4
+ def self.included(mod)
5
+ super
6
+ mod.class_eval do
7
+ before do
8
+ @plugin = mock(Jenkins::Plugin, :name => "test-plugin")
9
+
10
+ @jBuild = mock(Java.hudson.model.AbstractBuild)
11
+ @jLauncher = mock(Java.hudson.Launcher)
12
+ @jListener = mock(Java.hudson.model.BuildListener)
13
+
14
+ @build = mock(Jenkins::Model::Build)
15
+ @launcher = mock(Jenkins::Launcher)
16
+ @listener = mock(Jenkins::Model::Listener)
17
+
18
+ @plugin.stub(:import).with(@jBuild).and_return(@build)
19
+ @plugin.stub(:import).with(@jLauncher).and_return(@launcher)
20
+ @plugin.stub(:import).with(@jListener).and_return(@listener)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,148 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jenkins::Plugin::Proxies do
4
+ Proxies = Jenkins::Plugin::Proxies
5
+ before do
6
+ Proxies.clear
7
+ @plugin = mock(Jenkins::Plugin)
8
+ @proxies = Jenkins::Plugin::Proxies.new(@plugin)
9
+ end
10
+
11
+ describe "exporting a native ruby object" do
12
+
13
+ before do
14
+ @class = Class.new
15
+ @object = @class.new
16
+ end
17
+
18
+ describe "when no wrapper exists for it" do
19
+
20
+ describe "and there is a matching proxy class registered" do
21
+ before do
22
+ @proxy_class = Class.new
23
+ @proxy_class.class_eval do
24
+ attr_reader :plugin, :object
25
+ def initialize(plugin, object)
26
+ @plugin, @object = plugin, object
27
+ end
28
+ end
29
+ Jenkins::Plugin::Proxies.register @class, @proxy_class
30
+ @export = @proxies.export(@object)
31
+ end
32
+
33
+ it "instantiates the proxy" do
34
+ @export.should be_kind_of(@proxy_class)
35
+ end
36
+
37
+ it "passes in the plugin and the wrapped object" do
38
+ @export.plugin.should be(@plugin)
39
+ @export.object.should be(@object)
40
+ end
41
+ end
42
+
43
+ describe "and there is not an appropriate proxy class registered for it" do
44
+ it "raises an exception on import" do
45
+ expect {@proxies.export(@object)}.should raise_error
46
+ end
47
+ end
48
+ end
49
+
50
+ describe "when a wrapper has already existed" do
51
+ before do
52
+ @proxy = Object.new
53
+ @proxies.link @object, @proxy
54
+ end
55
+
56
+ it "finds the same proxy on export" do
57
+ @proxies.export(@object).should be(@proxy)
58
+ end
59
+
60
+ it "finds associated Ruby object on import" do
61
+ @proxies.import(@proxy).should be(@object)
62
+ end
63
+ end
64
+
65
+ describe "proxy matching" do
66
+ describe "when there are two related classes" do
67
+ before do
68
+ @A = Class.new
69
+ @B = Class.new(@A)
70
+ @A.class_eval do
71
+ attr_reader :native
72
+ def initialize(native = nil)
73
+ @native = native
74
+ end
75
+ end
76
+ end
77
+
78
+ describe "and there is a proxy registered for the subclass but not the superclass" do
79
+ before do
80
+ @p = proxy_class
81
+ Proxies.register @B, @p
82
+ end
83
+
84
+ it "will create a proxy for the subclass" do
85
+ @proxies.export(@B.new).should be_kind_of(@p)
86
+ end
87
+
88
+ it "will create a native for the external class" do
89
+ internal = @proxies.import(@p.new)
90
+ internal.should be_kind_of(@B)
91
+ end
92
+
93
+ it "will fail to create a proxy for the superclass" do
94
+ expect {@proxies.export @A.new}.should raise_error(Jenkins::Plugin::ExportError)
95
+ end
96
+ end
97
+
98
+ describe "and there is a proxy registered for the superclass but not the superclass" do
99
+ before do
100
+ @p = proxy_class
101
+ Proxies.register @A, @p
102
+ end
103
+ it "will create a proxy for the superclass" do
104
+ @proxies.export(@A.new).should be_kind_of(@p)
105
+ @proxies.import(@p.new).should be_kind_of(@A)
106
+ end
107
+
108
+ it "will create a proxy for the subclass" do
109
+ @proxies.export(@B.new).should be_kind_of(@p)
110
+ end
111
+ end
112
+
113
+ describe "and there is proxy registered for both classes" do
114
+
115
+ before do
116
+ @pA = proxy_class
117
+ @pB = proxy_class
118
+ Proxies.register @A, @pA
119
+ Proxies.register @B, @pB
120
+ end
121
+ it "will create a proxy for the subclass with its registered proxy class" do
122
+ @proxies.export(@A.new).should be_kind_of(@pA)
123
+ @proxies.import(@pA.new).should be_kind_of(@A)
124
+ end
125
+
126
+ it "will create a proxy for the superclass with its registered proxy class" do
127
+ @proxies.export(@B.new).should be_kind_of(@pB)
128
+ @proxies.import(@pB.new).should be_kind_of(@B)
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ end
135
+
136
+ private
137
+
138
+ def proxy_class
139
+ cls = Class.new
140
+ cls.class_eval do
141
+ attr_reader :plugin, :object
142
+ def initialize(plugin = nil, object = nil)
143
+ @plugin, @object = plugin, object
144
+ end
145
+ end
146
+ return cls
147
+ end
148
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe "a class with #{Jenkins::Plugin::Proxy} mixed in" do
4
+
5
+ before do
6
+ @class = Class.new
7
+ @class.send(:include, Jenkins::Plugin::Proxy)
8
+ end
9
+
10
+ it "treats the plugin as transient" do
11
+ @class.transient?(:plugin).should be_true
12
+ end
13
+
14
+ it "leaves other fields alone" do
15
+ @class.transient?(:object).should be_false
16
+ end
17
+
18
+ describe "unmarshalling" do
19
+ before do
20
+ @class.class_eval do
21
+ attr_reader :plugin
22
+ end
23
+ @plugin = mock(Jenkins::Plugin)
24
+ @impl = impl = Object.new
25
+ @proxy = @class.allocate
26
+ @proxy.instance_eval do
27
+ @pluginid = "test-plugin"
28
+ @object = impl
29
+ end
30
+ @jenkins = mock(Java.jenkins.model.Jenkins)
31
+ @java_plugin = mock(:RubyPlugin, :getNativeRubyPlugin => @plugin)
32
+ @jenkins.stub(:getPlugin).with("test-plugin").and_return(@java_plugin)
33
+ Java.jenkins.model.Jenkins.stub(:getInstance).and_return(@jenkins)
34
+ end
35
+
36
+ it "reconstructs the @plugin field" do
37
+ @plugin.should_receive(:link).with(@impl, @proxy)
38
+ @proxy.read_completed
39
+ @proxy.plugin.should be(@plugin)
40
+ end
41
+ end
42
+
43
+ end