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