jenkins-plugin-runtime 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/jenkins/filepath.rb +133 -0
- data/lib/jenkins/launcher.rb +103 -6
- data/lib/jenkins/model/action.rb +11 -17
- data/lib/jenkins/model/build.rb +7 -6
- data/lib/jenkins/model/describable.rb +1 -1
- data/lib/jenkins/model/descriptor.rb +25 -1
- data/lib/jenkins/model/listener.rb +48 -23
- data/lib/jenkins/model/root_action.rb +4 -4
- data/lib/jenkins/plugin.rb +27 -8
- data/lib/jenkins/plugin/proxies.rb +5 -2
- data/lib/jenkins/plugin/proxies/action.rb +31 -0
- data/lib/jenkins/plugin/proxies/build_step.rb +32 -0
- data/lib/jenkins/plugin/proxies/builder.rb +2 -9
- data/lib/jenkins/plugin/proxies/publisher.rb +25 -0
- data/lib/jenkins/plugin/proxies/root_action.rb +35 -0
- data/lib/jenkins/plugin/runtime/version.rb +1 -1
- data/lib/jenkins/tasks/build_step.rb +23 -0
- data/lib/jenkins/tasks/builder.rb +6 -25
- data/lib/jenkins/tasks/publisher.rb +18 -0
- data/spec/jenkins/filepath_spec.rb +123 -0
- data/spec/jenkins/launcher_spec.rb +210 -0
- data/spec/jenkins/model/action_spec.rb +2 -3
- data/spec/jenkins/model/build_spec.rb +22 -3
- data/spec/jenkins/model/listener_spec.rb +9 -7
- data/spec/jenkins/plugin/proxies/builder_spec.rb +11 -0
- data/spec/jenkins/plugin/proxies/publisher_spec.rb +35 -0
- data/spec/jenkins/plugin/proxies/root_action_spec.rb +31 -0
- data/spec/jenkins/plugin/proxies_spec.rb +17 -1
- data/spec/jenkins/plugin_spec.rb +65 -0
- data/spec/spec_helper.rb +34 -0
- metadata +15 -2
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module Jenkins
|
4
|
+
class FilePath
|
5
|
+
Stat = Struct.new(:size, :mode, :mtime)
|
6
|
+
|
7
|
+
attr_reader :natvie
|
8
|
+
|
9
|
+
def initialize(native)
|
10
|
+
@native = native
|
11
|
+
end
|
12
|
+
|
13
|
+
# Ruby's Pathname internace
|
14
|
+
|
15
|
+
def +(name)
|
16
|
+
FilePath.new(@native.child(name))
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
@native.getRemote()
|
21
|
+
end
|
22
|
+
|
23
|
+
def realpath
|
24
|
+
@native.absolutize().getRemote()
|
25
|
+
end
|
26
|
+
|
27
|
+
def read(*args)
|
28
|
+
@native.read.to_io.read(*args)
|
29
|
+
end
|
30
|
+
|
31
|
+
# TODO: atime jnr-posix?
|
32
|
+
# TODO: ctime jnr-posix?
|
33
|
+
|
34
|
+
def mtime
|
35
|
+
Time.at(@native.lastModified().to_f / 1000)
|
36
|
+
end
|
37
|
+
|
38
|
+
def chmod(mask)
|
39
|
+
@native.chmod(mask)
|
40
|
+
end
|
41
|
+
|
42
|
+
# TODO: chown
|
43
|
+
# TODO: open
|
44
|
+
|
45
|
+
def rename(to)
|
46
|
+
@native.renameTo(create_filepath(to))
|
47
|
+
end
|
48
|
+
|
49
|
+
def stat
|
50
|
+
Stat.new(size, @native.mode(), mtime)
|
51
|
+
end
|
52
|
+
|
53
|
+
# TODO: utime
|
54
|
+
|
55
|
+
def basename
|
56
|
+
FilePath.new(create_filepath(@native.getName()))
|
57
|
+
end
|
58
|
+
|
59
|
+
# TODO: dirname
|
60
|
+
# TODO: extname
|
61
|
+
|
62
|
+
def exist?
|
63
|
+
@native.exists()
|
64
|
+
end
|
65
|
+
|
66
|
+
def directory?
|
67
|
+
@native.isDirectory()
|
68
|
+
end
|
69
|
+
|
70
|
+
def file?
|
71
|
+
!directory?
|
72
|
+
end
|
73
|
+
|
74
|
+
def size
|
75
|
+
@native.length()
|
76
|
+
end
|
77
|
+
|
78
|
+
def entries
|
79
|
+
@native.list().map { |native|
|
80
|
+
FilePath.new(native)
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
def mkdir
|
85
|
+
@native.mkdirs
|
86
|
+
end
|
87
|
+
|
88
|
+
# TODO: rmdir
|
89
|
+
# TODO: opendir
|
90
|
+
|
91
|
+
def each_entry(&block)
|
92
|
+
entries.each do |child|
|
93
|
+
yield child
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def delete
|
98
|
+
@native.delete()
|
99
|
+
end
|
100
|
+
alias unlink delete
|
101
|
+
|
102
|
+
def rmtree
|
103
|
+
@native.deleteRecursive()
|
104
|
+
end
|
105
|
+
|
106
|
+
# TODO: hudson.FilePath does not handle FilePath(".").parent since it scans
|
107
|
+
# the last "/" for file, the 2nd last "/" for directory. Can Jenkins handle
|
108
|
+
# new FilePatn(ch, "../..") correctly?
|
109
|
+
def parent
|
110
|
+
parent = Pathname.new(to_s).parent.to_s
|
111
|
+
FilePath.new(Java.hudson.FilePath.new(@native.getChannel(), parent))
|
112
|
+
end
|
113
|
+
|
114
|
+
# Original interface
|
115
|
+
|
116
|
+
def touch(time)
|
117
|
+
@native.touch(time.to_i * 1000)
|
118
|
+
end
|
119
|
+
|
120
|
+
def remote?
|
121
|
+
@native.isRemote()
|
122
|
+
end
|
123
|
+
|
124
|
+
# TODO: createTempDir
|
125
|
+
# TODO: createTempFile
|
126
|
+
|
127
|
+
private
|
128
|
+
|
129
|
+
def create_filepath(path)
|
130
|
+
Java.hudson.FilePath.new(@native.getChannel(), path)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
data/lib/jenkins/launcher.rb
CHANGED
@@ -1,8 +1,40 @@
|
|
1
|
-
|
2
1
|
module Jenkins
|
3
2
|
|
4
3
|
# Launch processes on build slaves. No functionality is currently exposed
|
5
4
|
class Launcher
|
5
|
+
class Proc
|
6
|
+
attr_reader :natvie
|
7
|
+
|
8
|
+
def initialize(native)
|
9
|
+
@native = native
|
10
|
+
end
|
11
|
+
|
12
|
+
def alive?
|
13
|
+
@native.isAlive()
|
14
|
+
end
|
15
|
+
|
16
|
+
def join
|
17
|
+
@native.join()
|
18
|
+
end
|
19
|
+
|
20
|
+
def kill
|
21
|
+
@native.kill()
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def stdin
|
26
|
+
@native.getStdin().to_io
|
27
|
+
end
|
28
|
+
|
29
|
+
def stdout
|
30
|
+
@native.getStdout().to_io
|
31
|
+
end
|
32
|
+
|
33
|
+
def stderr
|
34
|
+
@native.getStderr().to_io
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
6
38
|
# the native hudson.Launcher object
|
7
39
|
attr_reader :native
|
8
40
|
|
@@ -10,11 +42,76 @@ module Jenkins
|
|
10
42
|
@native = native
|
11
43
|
end
|
12
44
|
|
13
|
-
#
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
45
|
+
# execute([env,] command... [,options]) -> fixnum
|
46
|
+
def execute(*args)
|
47
|
+
spawn(*args).join
|
48
|
+
end
|
49
|
+
|
50
|
+
# spawn([env,] command... [,options]) -> proc
|
51
|
+
def spawn(*args)
|
52
|
+
env, cmd, options = scan_args(args)
|
53
|
+
|
54
|
+
starter = @native.launch()
|
55
|
+
starter.envs(env)
|
56
|
+
if opt_chdir = options[:chdir]
|
57
|
+
starter.pwd(opt_chdir.to_s)
|
58
|
+
end
|
59
|
+
if opt_in = options[:in]
|
60
|
+
starter.stdin(opt_in.to_inputstream)
|
61
|
+
end
|
62
|
+
if opt_out = options[:out]
|
63
|
+
if opt_out.is_a?(Jenkins::Model::Listener)
|
64
|
+
starter.stdout(Jenkins::Plugin.instance.export(opt_out))
|
65
|
+
else
|
66
|
+
starter.stdout(opt_out.to_outputstream)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
if opt_err = options[:err]
|
70
|
+
starter.stderr(opt_err.to_outputstream)
|
71
|
+
end
|
72
|
+
case cmd
|
73
|
+
when Array
|
74
|
+
starter.cmds(cmd)
|
75
|
+
else
|
76
|
+
begin
|
77
|
+
# when we are on 1.432, we can use cmdAsSingleString
|
78
|
+
starter.cmdAsSingleString(cmd.to_s)
|
79
|
+
rescue NoMethodError
|
80
|
+
# http://d.hatena.ne.jp/sikakura/20110324/1300977208 is doing
|
81
|
+
# Arrays.asList(str.split(" ")) which should be wrong.
|
82
|
+
require 'shellwords'
|
83
|
+
starter.cmds(*Shellwords.split(cmd.to_s))
|
84
|
+
end
|
85
|
+
end
|
86
|
+
Proc.new(starter.start())
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def scan_args(args)
|
92
|
+
if args.last
|
93
|
+
if Hash === args.last
|
94
|
+
opt = args.pop
|
95
|
+
elsif args.last.respond_to?(:to_hash)
|
96
|
+
opt = args.pop.to_hash
|
97
|
+
end
|
98
|
+
end
|
99
|
+
if args.first
|
100
|
+
if Hash === args.first
|
101
|
+
env = args.shift
|
102
|
+
elsif args.first.respond_to?(:to_hash)
|
103
|
+
env = args.shift.to_hash
|
104
|
+
end
|
105
|
+
if env
|
106
|
+
env = env.inject({}) { |r, (key, value)| r[key.to_s] = value.to_s; r }
|
107
|
+
end
|
108
|
+
end
|
109
|
+
if args.length == 1
|
110
|
+
cmd = args.first
|
111
|
+
else
|
112
|
+
cmd = args
|
113
|
+
end
|
114
|
+
[env || {}, cmd, opt || {}]
|
18
115
|
end
|
19
116
|
|
20
117
|
Plugin::Proxies.register self, Java.hudson.Launcher
|
data/lib/jenkins/model/action.rb
CHANGED
@@ -1,23 +1,14 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
require 'jenkins/model'
|
3
3
|
|
4
4
|
module Jenkins
|
5
5
|
module Model
|
6
|
-
module Action
|
7
|
-
include Model
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
else
|
15
|
-
cls.extend(ClassMethods)
|
16
|
-
cls.send(:include, InstanceMethods)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
extend Included
|
7
|
+
# TODO: I turned Action into Class from Module but it should be a bad idea.
|
8
|
+
# The change may be reverted. I used class Action for implementing a model
|
9
|
+
# as a describable but I really should do is implementing describable.
|
10
|
+
class Action
|
11
|
+
include Model
|
21
12
|
|
22
13
|
module InstanceMethods
|
23
14
|
def icon
|
@@ -28,7 +19,7 @@ module Jenkins
|
|
28
19
|
self.class.url_path
|
29
20
|
end
|
30
21
|
end
|
31
|
-
|
22
|
+
|
32
23
|
module ClassMethods
|
33
24
|
def icon(filename = nil)
|
34
25
|
filename.nil? ? @icon : @icon = filename.to_s
|
@@ -38,6 +29,9 @@ module Jenkins
|
|
38
29
|
path.nil? ? @url_path : @url_path = path.to_s
|
39
30
|
end
|
40
31
|
end
|
32
|
+
|
33
|
+
include InstanceMethods
|
34
|
+
extend ClassMethods
|
41
35
|
end
|
42
36
|
end
|
43
|
-
end
|
37
|
+
end
|
data/lib/jenkins/model/build.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'jenkins/filepath'
|
1
2
|
|
2
3
|
module Jenkins
|
3
4
|
module Model
|
@@ -13,16 +14,16 @@ module Jenkins
|
|
13
14
|
@native = native
|
14
15
|
end
|
15
16
|
|
17
|
+
def workspace
|
18
|
+
FilePath.new(@native.getWorkspace())
|
19
|
+
end
|
20
|
+
|
16
21
|
def build_var
|
17
22
|
@native.getBuildVariables()
|
18
23
|
end
|
19
24
|
|
20
|
-
def env
|
21
|
-
|
22
|
-
# TODO: not tested. dump to listener?
|
23
|
-
listener = Plugin.instance.export(listener)
|
24
|
-
end
|
25
|
-
@native.getEnvironment(listener)
|
25
|
+
def env
|
26
|
+
@native.getEnvironment(nil)
|
26
27
|
end
|
27
28
|
|
28
29
|
Jenkins::Plugin::Proxies.register self, Java.hudson.model.AbstractBuild
|
@@ -6,7 +6,7 @@ module Jenkins
|
|
6
6
|
class Descriptor < Java.hudson.model.Descriptor
|
7
7
|
|
8
8
|
def initialize(impl, plugin, java_type)
|
9
|
-
super(
|
9
|
+
super(java_type)
|
10
10
|
@impl, @plugin, @java_type = impl, plugin, java_type
|
11
11
|
end
|
12
12
|
|
@@ -14,10 +14,30 @@ module Jenkins
|
|
14
14
|
@impl.display_name
|
15
15
|
end
|
16
16
|
|
17
|
+
def getId()
|
18
|
+
"#{@plugin.name}-#{@impl.name}"
|
19
|
+
end
|
20
|
+
|
17
21
|
def getT()
|
18
22
|
@java_type
|
19
23
|
end
|
20
24
|
|
25
|
+
# TODO: We removed @name from Descriptor (see playground) so we need to use another name.
|
26
|
+
# Just use class name which is in CamelCase.
|
27
|
+
def getConfigPage
|
28
|
+
"/#{name_to_path}/config".tap { |path|
|
29
|
+
puts "getConfigPage -> #{path}"
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
# TODO: We removed @name from Descriptor (see playground) so we need to use another name.
|
34
|
+
# Just use class name which is in CamelCase.
|
35
|
+
def getGlobalConfigPage
|
36
|
+
"/#{name_to_path}/global".tap { |path|
|
37
|
+
puts "getGlobalConfigPage -> #{path}"
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
21
41
|
def newInstance(request, form)
|
22
42
|
properties = JSON.parse(form.toString(2))
|
23
43
|
properties.delete("kind")
|
@@ -34,6 +54,10 @@ module Jenkins
|
|
34
54
|
rescue ArgumentError
|
35
55
|
@impl.new
|
36
56
|
end
|
57
|
+
|
58
|
+
def name_to_path
|
59
|
+
@impl.name.split('::').join('/')
|
60
|
+
end
|
37
61
|
end
|
38
62
|
|
39
63
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'logger'
|
1
2
|
|
2
3
|
module Jenkins
|
3
4
|
module Model
|
@@ -6,42 +7,66 @@ module Jenkins
|
|
6
7
|
class Listener
|
7
8
|
|
8
9
|
# the underlying hudson.model.TaskListener object
|
9
|
-
attr_reader :
|
10
|
+
attr_reader :natvie
|
11
|
+
attr_accessor :level
|
10
12
|
|
11
13
|
def initialize(native = nil)
|
12
14
|
@native = native
|
15
|
+
@level = Logger::DEBUG
|
13
16
|
end
|
14
17
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
def
|
20
|
-
|
18
|
+
def debug?; @level <= DEBUG; end
|
19
|
+
def info?; @level <= INFO; end
|
20
|
+
def warn?; @level <= WARN; end
|
21
|
+
def error?; @level <= ERROR; end
|
22
|
+
def fatal?; @level <= FATAL; end
|
23
|
+
|
24
|
+
def debug(msg = nil, &block); add(Logger::DEBUG, msg, &block); end
|
25
|
+
def info(msg = nil, &block); add(Logger::INFO, msg, &block); end
|
26
|
+
def warn(msg = nil, &block); add(Logger::WARN, msg, &block); end
|
27
|
+
def error(msg = nil, &block); add(Logger::ERROR, msg, &block); end
|
28
|
+
def fatal(msg = nil, &block); add(Logger::FATAL, msg, &block); end
|
29
|
+
def unknown(msg = nil, &block); add(Logger::UNKNOWN, msg, &block); end
|
30
|
+
|
31
|
+
def <<(msg)
|
32
|
+
logger.write(msg.to_s)
|
21
33
|
end
|
22
34
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
35
|
+
private
|
36
|
+
|
37
|
+
def add(severity, msg = nil, &block)
|
38
|
+
severity ||= Logger::UNKNOWN
|
39
|
+
if msg.nil? && block_given?
|
40
|
+
msg = yield
|
41
|
+
end
|
42
|
+
str = msg2str(msg) + "\n"
|
43
|
+
return true if severity < @level
|
44
|
+
case severity
|
45
|
+
when Logger::DEBUG, Logger::INFO
|
46
|
+
logger.write(str)
|
47
|
+
when Logger::WARN, Logger::ERROR
|
48
|
+
@native.error(str)
|
49
|
+
else
|
50
|
+
@native.fatalError(str)
|
51
|
+
end
|
28
52
|
end
|
29
53
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
54
|
+
def msg2str(msg)
|
55
|
+
case msg
|
56
|
+
when ::String
|
57
|
+
msg
|
58
|
+
when ::Exception
|
59
|
+
"#{msg.message} (#{msg.class})\n" << (msg.backtrace || []).join("\n")
|
60
|
+
else
|
61
|
+
msg.inspect
|
62
|
+
end
|
35
63
|
end
|
36
64
|
|
37
|
-
|
38
|
-
|
39
|
-
# @param [String] msg the fatal error message
|
40
|
-
def fatal(msg)
|
41
|
-
@native.fatalError(msg.to_s)
|
65
|
+
def logger
|
66
|
+
@native.getLogger()
|
42
67
|
end
|
43
68
|
|
44
69
|
Jenkins::Plugin::Proxies.register self, Java.hudson.util.AbstractTaskListener
|
45
70
|
end
|
46
71
|
end
|
47
|
-
end
|
72
|
+
end
|