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.
- 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/model/build.rb
CHANGED
@@ -7,15 +7,14 @@ module Jenkins
|
|
7
7
|
# all build steps, and can be used to configure, halt, message
|
8
8
|
# the current running build.
|
9
9
|
class Build
|
10
|
+
include Jenkins::Plugin::Wrapper
|
11
|
+
|
12
|
+
wrapper_for Java.hudson.model.AbstractBuild
|
10
13
|
|
11
14
|
# Raised to indicate that a build wrapper halted a build.
|
12
15
|
# Raising this does *not* set the build result to error.
|
13
16
|
class Halt < Exception; end
|
14
17
|
|
15
|
-
|
16
|
-
# the Hudson::Model::AbstractBuild represented by this build
|
17
|
-
attr_reader :native
|
18
|
-
|
19
18
|
# Hash of environment variables that will be added to each process
|
20
19
|
# started as part of this build. E.g.
|
21
20
|
#
|
@@ -30,7 +29,7 @@ module Jenkins
|
|
30
29
|
attr_reader :env
|
31
30
|
|
32
31
|
def initialize(native)
|
33
|
-
|
32
|
+
super(native)
|
34
33
|
@variables = {}
|
35
34
|
@env = {}
|
36
35
|
@native.buildEnvironments.add(EnvironmentVariables.new(@env))
|
@@ -29,17 +29,29 @@ module Jenkins
|
|
29
29
|
# This class should generally not be needed by plugin authors since it is part of the
|
30
30
|
# glue layer and not the public runtime API.
|
31
31
|
module Describable
|
32
|
+
extend Plugin::Behavior
|
32
33
|
DescribableError = Class.new(StandardError)
|
33
34
|
|
35
|
+
implemented do |cls|
|
36
|
+
Jenkins.plugin.register_describable cls if Jenkins.plugin
|
37
|
+
end
|
38
|
+
|
34
39
|
module DescribeAs
|
40
|
+
|
35
41
|
# Java class that represents the extension point, which gets eventually set to Descriptor.clazz
|
36
42
|
# :with will use this java class as the type of descriptor.
|
37
43
|
def describe_as cls, options = {}
|
38
44
|
@describe_as_type = verify_java_class(cls).java_class
|
39
45
|
@descriptor_is = verify_java_class(options[:with]).java_class if options[:with]
|
40
46
|
end
|
41
|
-
|
42
|
-
|
47
|
+
|
48
|
+
def describe_as_type
|
49
|
+
@describe_as_type ? @describe_as_type : (superclass.describe_as_type if superclass.respond_to?(:describe_as_type))
|
50
|
+
end
|
51
|
+
|
52
|
+
def descriptor_is
|
53
|
+
@descriptor_is ? @descriptor_is : (superclass.descriptor_is if superclass.respond_to?(:descriptor_is))
|
54
|
+
end
|
43
55
|
|
44
56
|
private
|
45
57
|
|
@@ -51,35 +63,9 @@ module Jenkins
|
|
51
63
|
end
|
52
64
|
end
|
53
65
|
|
54
|
-
|
55
|
-
|
56
|
-
def inherited(cls)
|
57
|
-
super(cls)
|
58
|
-
cls.extend Inherited
|
59
|
-
describe_as_type = @describe_as_type
|
60
|
-
descriptor_is = @descriptor_is
|
61
|
-
cls.class_eval do
|
62
|
-
@describe_as_type = describe_as_type
|
63
|
-
@descriptor_is = descriptor_is
|
64
|
-
end
|
65
|
-
if Jenkins::Plugin.instance
|
66
|
-
Jenkins::Plugin.instance.register_describable(cls, describe_as_type, descriptor_is)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
module Included
|
72
|
-
def included(mod)
|
73
|
-
super
|
74
|
-
if mod.is_a? Class
|
75
|
-
mod.extend DescribeAs
|
76
|
-
mod.extend Inherited
|
77
|
-
else
|
78
|
-
warn "tried to include Describable into a Module. Are you sure?"
|
79
|
-
end
|
80
|
-
end
|
66
|
+
module ClassMethods
|
67
|
+
include DescribeAs
|
81
68
|
end
|
82
|
-
self.extend Included
|
83
69
|
end
|
84
70
|
end
|
85
71
|
end
|
data/lib/jenkins/plugin.rb
CHANGED
@@ -28,6 +28,17 @@ module Jenkins
|
|
28
28
|
# the instance of jenkins.ruby.RubyPlugin with which this Plugin is associated
|
29
29
|
attr_reader :peer
|
30
30
|
|
31
|
+
# Add listeners for things that might happen to a plugin. E.g.
|
32
|
+
#
|
33
|
+
# plugin.on.start do |plugin|
|
34
|
+
# #do some setup
|
35
|
+
# end
|
36
|
+
# plugin.on.stop do |plugin|
|
37
|
+
# #do some teardown
|
38
|
+
# end
|
39
|
+
# @return [Lifecycle]
|
40
|
+
attr_reader :on
|
41
|
+
|
31
42
|
# Initializes this plugin by reading the models.rb
|
32
43
|
# file. This is a manual registration process
|
33
44
|
# Where ruby objects register themselves with the plugin
|
@@ -40,6 +51,7 @@ module Jenkins
|
|
40
51
|
@start = @stop = proc {}
|
41
52
|
@descriptors = {}
|
42
53
|
@proxies = Proxies.new(self)
|
54
|
+
@on = Lifecycle.new
|
43
55
|
end
|
44
56
|
|
45
57
|
# Initialize the singleton instance that will run for a
|
@@ -88,7 +100,7 @@ module Jenkins
|
|
88
100
|
# @param [...] arguments to pass to
|
89
101
|
|
90
102
|
def register_extension(class_or_instance, *args)
|
91
|
-
extension = class_or_instance.is_a?(Class) ? class_or_instance.new : class_or_instance
|
103
|
+
extension = class_or_instance.is_a?(Class) ? class_or_instance.new(*args) : class_or_instance
|
92
104
|
@peer.addExtension(export(extension))
|
93
105
|
end
|
94
106
|
|
@@ -98,15 +110,18 @@ module Jenkins
|
|
98
110
|
# This method is invoked automatically as part of the auto-registration
|
99
111
|
# process, and should not need to be invoked by plugin code.
|
100
112
|
#
|
101
|
-
#
|
102
|
-
#
|
103
|
-
# @param [Class]
|
104
|
-
#
|
105
|
-
def register_describable(
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
113
|
+
# Classes including `Describabble` will be autoregistered in this way.
|
114
|
+
#
|
115
|
+
# @param [Class] describable_class the class implementing the extension point
|
116
|
+
# @see [Model::Describable]
|
117
|
+
def register_describable(describable_class)
|
118
|
+
fail "#{describable_class} is not an instance of Describable" unless describable_class.is_a? Model::Describable
|
119
|
+
on.start do
|
120
|
+
descriptor_class = descriptor_class.descriptor_is || Jenkins::Model::Descriptor
|
121
|
+
descriptor = descriptor_class.new(ruby_class, self, describable_class.describe_as_type)
|
122
|
+
@descriptors[ruby_class] = descriptor
|
123
|
+
register_extension(descriptor)
|
124
|
+
end
|
110
125
|
end
|
111
126
|
|
112
127
|
# unique identifier for this plugin in the Jenkins server
|
@@ -118,14 +133,14 @@ module Jenkins
|
|
118
133
|
# currently does nothing, but plugin startup hooks would
|
119
134
|
# go here.
|
120
135
|
def start
|
121
|
-
@
|
136
|
+
@on.fire(:start, self)
|
122
137
|
end
|
123
138
|
|
124
139
|
# Called one by Jenkins (via RubyPlugin) when this plugin
|
125
140
|
# is shut down. Currently this does nothing, but plugin
|
126
141
|
# shutdown hooks would go here.
|
127
142
|
def stop
|
128
|
-
@
|
143
|
+
@on.fire(:stop, self)
|
129
144
|
end
|
130
145
|
|
131
146
|
# Reflect an Java object coming from Jenkins into the context of this plugin
|
@@ -159,6 +174,12 @@ module Jenkins
|
|
159
174
|
@proxies.linkout internal, external
|
160
175
|
end
|
161
176
|
|
177
|
+
# Load all of the Ruby code associated with this plugin. For
|
178
|
+
# historical purposes this is called "models", but really
|
179
|
+
# it should be something like extensions ext/ or maybe it's
|
180
|
+
# just one file associated with the plugin itself. Who knows?
|
181
|
+
# The jury is definitely still out on the best way to discover
|
182
|
+
# and load extension points.
|
162
183
|
def load_models
|
163
184
|
path = @java.getModelsPath().getPath()
|
164
185
|
# TODO: can we access to Jenkins console logger?
|
@@ -191,6 +212,34 @@ module Jenkins
|
|
191
212
|
load_file_in_dir(dir)
|
192
213
|
end
|
193
214
|
end
|
215
|
+
|
216
|
+
class Lifecycle
|
217
|
+
def initialize
|
218
|
+
@start = []
|
219
|
+
@stop = []
|
220
|
+
end
|
221
|
+
|
222
|
+
def start(&block)
|
223
|
+
@start << block if block
|
224
|
+
end
|
225
|
+
|
226
|
+
def stop(&block)
|
227
|
+
@stop << block if block
|
228
|
+
end
|
229
|
+
|
230
|
+
def fire(event, *args)
|
231
|
+
if listeners = instance_variable_get("@#{event}")
|
232
|
+
listeners.each do |l|
|
233
|
+
callback(l, *args)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
def callback(listener, *args)
|
238
|
+
listener.call(*args)
|
239
|
+
rescue Exception => e
|
240
|
+
$stderr.warn "#{e.class}: #{e.message}\n#{e.backtrace.join("\n")}"
|
241
|
+
end
|
242
|
+
end
|
194
243
|
end
|
195
244
|
|
196
245
|
# Make the singleton instance available from the top-level
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Jenkins
|
4
|
+
class Plugin
|
5
|
+
# A Behavior will receive a callback any time that it is
|
6
|
+
# included into a class or when a class that has been included
|
7
|
+
# is extended. This is needed for a couple reasons.
|
8
|
+
#
|
9
|
+
# One case is to enable Transient marking behavior. Every
|
10
|
+
# time a concrete model class is implemented, it needs the
|
11
|
+
# ability to define which of its attributes are transient,
|
12
|
+
# so that they will not be persisted with the Jenkins serialization.
|
13
|
+
# which attributes are tracked on a per-class basis, so we
|
14
|
+
# need a callback for each class in the inheritance hierachy.
|
15
|
+
#
|
16
|
+
# class Foo
|
17
|
+
# include Model
|
18
|
+
# transient :foo do
|
19
|
+
# @foo = 1 + 2
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
# class Bar < Foo
|
23
|
+
# transient :bar do # <- no need to include Model
|
24
|
+
# @bar = create_bar
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# Another is the case of auto registration. We want to be able
|
29
|
+
# to find out when extension points are implemented, and register
|
30
|
+
# them with the Jenkins Runtime
|
31
|
+
#
|
32
|
+
# module Descriptor
|
33
|
+
# implemented do |cls|
|
34
|
+
# Jenkins.plugin.on.start do |plugin|
|
35
|
+
# plugin.register_extension new(Jenkins.plugin, cls.ruby_type, cls.java_type)
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
# And of course, there is the case of proxies where we need to make sure that
|
40
|
+
# certain behaviors are always included into the proxy, and that if java classes
|
41
|
+
# need to be implemented, they are.
|
42
|
+
module Behavior
|
43
|
+
def included(mod)
|
44
|
+
if mod.is_a? Class
|
45
|
+
mod.extend Implementation unless mod.is_a? Implementation
|
46
|
+
else
|
47
|
+
mod.extend Behavior unless mod.is_a? Behavior
|
48
|
+
end
|
49
|
+
mod.behaves_as *@_behaviors
|
50
|
+
super(mod)
|
51
|
+
end
|
52
|
+
|
53
|
+
def implemented(cls = nil, &implemented_block)
|
54
|
+
if cls
|
55
|
+
@implemented_block.call cls if @implemented_block
|
56
|
+
else
|
57
|
+
@implemented_block = implemented_block
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.extended(mod)
|
62
|
+
super(mod)
|
63
|
+
mod.instance_eval do
|
64
|
+
@_behaviors = Set.new([self])
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
module BehavesAs
|
69
|
+
def behaves_as(*behaviors)
|
70
|
+
@_behaviors ||= Set.new
|
71
|
+
behaviors.each do |b|
|
72
|
+
unless @_behaviors.include? b
|
73
|
+
b.implemented self if self.is_a? Class
|
74
|
+
self.extend b::ClassMethods if b.const_defined? :ClassMethods
|
75
|
+
self.send(:include, b::InstanceMethods) if b.const_defined? :InstanceMethods
|
76
|
+
@_behaviors << b
|
77
|
+
end
|
78
|
+
end
|
79
|
+
return @_behaviors
|
80
|
+
end
|
81
|
+
end
|
82
|
+
include BehavesAs
|
83
|
+
|
84
|
+
module Implementation
|
85
|
+
include BehavesAs
|
86
|
+
|
87
|
+
def inherited(cls)
|
88
|
+
super.tap do
|
89
|
+
cls.extend Implementation unless cls.is_a? Implementation
|
90
|
+
cls.behaves_as *@_behaviors
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -175,3 +175,7 @@ require 'jenkins/model/describable'
|
|
175
175
|
["action", "build_wrapper", "builder", "publisher", "root_action"].each do |proxy|
|
176
176
|
require "jenkins/plugin/proxies/#{proxy}"
|
177
177
|
end
|
178
|
+
|
179
|
+
["cli/command"].each do |proxy|
|
180
|
+
require "jenkins/#{proxy}_proxy"
|
181
|
+
end
|
@@ -4,11 +4,17 @@ require 'jenkins/plugin/proxies/describable'
|
|
4
4
|
module Jenkins
|
5
5
|
class Plugin
|
6
6
|
class Proxies
|
7
|
-
|
8
|
-
include Java.hudson.model.Action
|
9
|
-
include Java.jenkins.ruby.Get
|
7
|
+
module Action
|
10
8
|
include Jenkins::Plugin::Proxy
|
11
|
-
|
9
|
+
implemented do |cls|
|
10
|
+
cls.class_eval do
|
11
|
+
include Java.hudson.model.Action
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def getDisplayName
|
16
|
+
@object.display_name
|
17
|
+
end
|
12
18
|
|
13
19
|
def getIconFileName
|
14
20
|
@object.icon
|
@@ -18,8 +24,6 @@ module Jenkins
|
|
18
24
|
@object.url_path
|
19
25
|
end
|
20
26
|
end
|
21
|
-
|
22
|
-
register Jenkins::Model::Action, Action
|
23
27
|
end
|
24
28
|
end
|
25
29
|
end
|
@@ -11,9 +11,8 @@ module Jenkins
|
|
11
11
|
# Ruby API Jenkins::Tasks::BuildWrapper
|
12
12
|
|
13
13
|
class BuildWrapper < Java.hudson.tasks.BuildWrapper
|
14
|
-
include
|
15
|
-
|
16
|
-
include Jenkins::Plugin::Proxy
|
14
|
+
include Describable
|
15
|
+
proxy_for Jenkins::Tasks::BuildWrapper
|
17
16
|
|
18
17
|
def setUp(build, launcher, listener)
|
19
18
|
@object.setup(import(build), import(launcher), import(listener))
|
@@ -45,8 +44,6 @@ module Jenkins
|
|
45
44
|
false
|
46
45
|
end
|
47
46
|
end
|
48
|
-
|
49
|
-
register Jenkins::Tasks::BuildWrapper, BuildWrapper
|
50
47
|
end
|
51
48
|
end
|
52
49
|
end
|
@@ -5,13 +5,9 @@ module Jenkins
|
|
5
5
|
class Plugin
|
6
6
|
class Proxies
|
7
7
|
class Builder < Java.hudson.tasks.Builder
|
8
|
-
include Jenkins::Plugin::Proxies::Describable
|
9
|
-
include Java.jenkins.ruby.Get
|
10
|
-
include Jenkins::Plugin::Proxy
|
11
8
|
include BuildStep
|
9
|
+
proxy_for Jenkins::Tasks::Builder
|
12
10
|
end
|
13
|
-
|
14
|
-
register Jenkins::Tasks::Builder, Builder
|
15
11
|
end
|
16
12
|
end
|
17
13
|
end
|
@@ -4,6 +4,12 @@ module Jenkins
|
|
4
4
|
# mix-in on top of the subtypes of the Describable Java class
|
5
5
|
# to add standard behaviour as a proxy to Ruby object
|
6
6
|
module Describable
|
7
|
+
include Jenkins::Plugin::Proxy
|
8
|
+
implemented do |cls|
|
9
|
+
cls.class_eval do
|
10
|
+
include Java.jenkins.ruby.Get
|
11
|
+
end
|
12
|
+
end
|
7
13
|
def getDescriptor
|
8
14
|
@plugin.descriptors[@object.class]
|
9
15
|
end
|
@@ -5,13 +5,9 @@ module Jenkins
|
|
5
5
|
class Plugin
|
6
6
|
class Proxies
|
7
7
|
class Publisher < Java.hudson.tasks.Publisher
|
8
|
-
include Jenkins::Plugin::Proxies::Describable
|
9
|
-
include Java.jenkins.ruby.Get
|
10
|
-
include Jenkins::Plugin::Proxy
|
11
8
|
include BuildStep
|
9
|
+
proxy_for Jenkins::Tasks::Publisher
|
12
10
|
end
|
13
|
-
|
14
|
-
register Jenkins::Tasks::Publisher, Publisher
|
15
11
|
end
|
16
12
|
end
|
17
13
|
end
|
@@ -4,25 +4,10 @@ module Jenkins
|
|
4
4
|
class Plugin
|
5
5
|
class Proxies
|
6
6
|
class RootAction
|
7
|
+
include Action
|
7
8
|
include Java.hudson.model.RootAction
|
8
|
-
|
9
|
-
include Jenkins::Plugin::Proxy
|
10
|
-
include Jenkins::Plugin::Proxies::Describable
|
11
|
-
|
12
|
-
def getDisplayName
|
13
|
-
@object.display_name
|
14
|
-
end
|
15
|
-
|
16
|
-
def getIconFileName
|
17
|
-
@object.icon
|
18
|
-
end
|
19
|
-
|
20
|
-
def getUrlName
|
21
|
-
@object.url_path
|
22
|
-
end
|
9
|
+
proxy_for Jenkins::Model::RootAction
|
23
10
|
end
|
24
|
-
|
25
|
-
register Jenkins::Model::RootAction, RootAction
|
26
11
|
end
|
27
12
|
end
|
28
13
|
end
|