jpi 0.3.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.
- data/.gitignore +6 -0
- data/Gemfile +4 -0
- data/README.md +76 -0
- data/Rakefile +6 -0
- data/bin/jpi +5 -0
- data/features/create-new-plugin.feature +18 -0
- data/features/support/create_new_plugin_steps.rb +7 -0
- data/features/support/directory_structure.rb +49 -0
- data/features/support/work.rb +20 -0
- data/jpi.gemspec +28 -0
- data/lib/jenkins/jenkins-ci.org/credential.rb +39 -0
- data/lib/jenkins/plugin/cli.rb +66 -0
- data/lib/jenkins/plugin/cli/formatting.rb +54 -0
- data/lib/jenkins/plugin/cli/generate.rb +27 -0
- data/lib/jenkins/plugin/cli/new.rb +39 -0
- data/lib/jenkins/plugin/cli/templates/Gemfile.tt +4 -0
- data/lib/jenkins/plugin/cli/templates/build_step.tt +25 -0
- data/lib/jenkins/plugin/cli/templates/pluginspec.tt +28 -0
- data/lib/jenkins/plugin/tools/bundle.rb +30 -0
- data/lib/jenkins/plugin/tools/hpi.rb +107 -0
- data/lib/jenkins/plugin/tools/loadpath.rb +29 -0
- data/lib/jenkins/plugin/tools/manifest.rb +80 -0
- data/lib/jenkins/plugin/tools/package.rb +60 -0
- data/lib/jenkins/plugin/tools/release.rb +70 -0
- data/lib/jenkins/plugin/tools/resolver.rb +61 -0
- data/lib/jenkins/plugin/tools/server.rb +49 -0
- data/lib/jenkins/plugin/tools/templates/release-pom.xml.erb +54 -0
- data/lib/jenkins/plugin/version.rb +5 -0
- data/lib/jenkins/rake.rb +52 -0
- metadata +164 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# Jenkins plugins
|
2
|
+
|
3
|
+
Provide the facility to create, develop and release extensions for [Jenkins](http://jenkins-ci.org) with nothing but knowledge of the language, tools and best practices of the Ruby community.
|
4
|
+
|
5
|
+
[read more](http://blog.thefrontside.net/2011/05/12/what-it-take-to-bring-ruby-to-jenkins)...
|
6
|
+
|
7
|
+
# Get started
|
8
|
+
|
9
|
+
Using JRuby, install the plugin tools
|
10
|
+
|
11
|
+
$ gem install jpi
|
12
|
+
|
13
|
+
The gem provides the `jpi` executeable
|
14
|
+
|
15
|
+
$ jpi -h
|
16
|
+
|
17
|
+
jpi- tools to create, build, develop and release Jenkins plugins
|
18
|
+
|
19
|
+
Usage: jpi command [arguments] [options]
|
20
|
+
|
21
|
+
Commands:
|
22
|
+
jpi help [COMMAND] # get help for COMMAND, or for jpi itself
|
23
|
+
jpi new NAME # create a new plugin called NAME
|
24
|
+
jpi generate # generate code for extensions points
|
25
|
+
jpi build # build plugin into .hpi file suitable for distribution
|
26
|
+
jpi server # run a test server with plugin
|
27
|
+
jpi version # show jpi version information
|
28
|
+
|
29
|
+
The first thing you'll probably want to do is create a new ruby plugin.
|
30
|
+
|
31
|
+
$ jpi new one-great-plugin
|
32
|
+
create one-great-plugin/Gemfile
|
33
|
+
create one-great-plugin/one-great-plugin.pluginspec
|
34
|
+
|
35
|
+
This will create a minimal plugin project structure, to which you can add later.
|
36
|
+
Once you have your plugin created, you can run a server with it loaded
|
37
|
+
|
38
|
+
$ cd one-great-plugin
|
39
|
+
$ jpi server
|
40
|
+
|
41
|
+
Listening for transport dt_socket at address: 8000
|
42
|
+
webroot: System.getProperty("JENKINS_HOME")
|
43
|
+
[Winstone 2011/09/19 12:01:36] - Beginning extraction from war file
|
44
|
+
[Winstone 2011/09/19 12:01:37] - HTTP Listener started: port=8080
|
45
|
+
[Winstone 2011/09/19 12:01:37] - AJP13 Listener started: port=8009
|
46
|
+
[Winstone 2011/09/19 12:01:37] - Winstone Servlet Engine v0.9.10 running: controlPort=disabled
|
47
|
+
Sep 19, 2011 12:01:37 PM jenkins.model.Jenkins$6 onAttained
|
48
|
+
INFO: Started initialization
|
49
|
+
Sep 19, 2011 12:01:38 PM hudson.PluginManager$1$3$1 isDuplicate
|
50
|
+
Sep 19, 2011 12:01:39 PM jenkins.model.Jenkins$6 onAttained
|
51
|
+
INFO: Listed all plugins
|
52
|
+
Sep 19, 2011 12:01:39 PM ruby.RubyRuntimePlugin start
|
53
|
+
INFO: Injecting JRuby into XStream
|
54
|
+
Sep 19, 2011 12:01:49 PM jenkins.model.Jenkins$6 onAttained
|
55
|
+
INFO: Prepared all plugins
|
56
|
+
Sep 19, 2011 12:01:49 PM jenkins.model.Jenkins$6 onAttained
|
57
|
+
INFO: Started all plugins
|
58
|
+
Sep 19, 2011 12:01:49 PM jenkins.model.Jenkins$6 onAttained
|
59
|
+
INFO: Augmented all extensions
|
60
|
+
Sep 19, 2011 12:01:49 PM jenkins.model.Jenkins$6 onAttained
|
61
|
+
INFO: Loaded all jobs
|
62
|
+
Sep 19, 2011 12:01:51 PM jenkins.model.Jenkins$6 onAttained
|
63
|
+
INFO: Completed initialization
|
64
|
+
Sep 19, 2011 12:01:51 PM hudson.TcpSlaveAgentListener <init>
|
65
|
+
INFO: JNLP slave agent listener started on TCP port 52262
|
66
|
+
Sep 19, 2011 12:02:01 PM hudson.WebAppMain$2 run
|
67
|
+
INFO: Jenkins is fully up and running
|
68
|
+
|
69
|
+
Of course, this plugin isn't actually doing anything because we haven't defined any extension
|
70
|
+
points. Let's go ahead and create one of the most common extension points: a `Builder`
|
71
|
+
|
72
|
+
$ jpi generate builder logging
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
|
data/Rakefile
ADDED
data/bin/jpi
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
|
2
|
+
Feature: Generating a new Jenkins Ruby Plugin
|
3
|
+
|
4
|
+
Creating a new Ruby plugin for Jenkins needs to be as simple as running a single command
|
5
|
+
that will generate a project skeleton. This skeleton will come complete with git repository and all
|
6
|
+
the goodies that you need to do your plugin develompent.
|
7
|
+
|
8
|
+
Scenario: The directory skeleton is generated
|
9
|
+
When I run "jpi new newplugin"
|
10
|
+
# Then I should see this structure
|
11
|
+
# """
|
12
|
+
# [-] newplugin
|
13
|
+
# | [+] .git
|
14
|
+
# | .gitignore
|
15
|
+
# | Gemfile
|
16
|
+
# | Rakefile
|
17
|
+
# | newplugin.pluginspec
|
18
|
+
# """
|
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
class DirectoryStructure
|
3
|
+
def initialize(structure)
|
4
|
+
|
5
|
+
@root = context = DirChild.new('.')
|
6
|
+
|
7
|
+
structure.each_line do |line|
|
8
|
+
if line =~ /(\[[-+]\]|\|)?\s+(\.?\w+)$/
|
9
|
+
op, name = $1, $2
|
10
|
+
case op
|
11
|
+
when "[+]"
|
12
|
+
context.add(DirChild.new name)
|
13
|
+
when "[-]"
|
14
|
+
new_context = DirChild.new name
|
15
|
+
context.add(new_context)
|
16
|
+
context = new_context
|
17
|
+
when "|"
|
18
|
+
context.add(FileChild.new name)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def matches?(dir)
|
25
|
+
@root.matches?(dir)
|
26
|
+
end
|
27
|
+
|
28
|
+
Entry = Struct.new(:name)
|
29
|
+
|
30
|
+
class DirChild < Entry
|
31
|
+
def initialize(name)
|
32
|
+
super(name)
|
33
|
+
@entries = []
|
34
|
+
end
|
35
|
+
|
36
|
+
def add(entry)
|
37
|
+
@entries << entries
|
38
|
+
end
|
39
|
+
|
40
|
+
def matches?(realdir)
|
41
|
+
entries = Dir.new(realdir).entries
|
42
|
+
!@entries.detect {|e| !entries.map{|e| File.basename(e)}.member?(e)}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class FileChild < Entry
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Work
|
2
|
+
def run cmd
|
3
|
+
Dir.chdir(work_dir) do
|
4
|
+
root = Pathname(__FILE__).join('..', '..', '..')
|
5
|
+
full_cmd = "ruby -rubygems -I #{root.join('lib')} -S #{root.join('bin',cmd)}"
|
6
|
+
system(full_cmd) or fail "failed to run command #{cmd}"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def work_dir
|
11
|
+
@work_dir ||= File.expand_path("tmp/work")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Before do
|
16
|
+
FileUtils.rm_rf work_dir
|
17
|
+
FileUtils.mkdir_p work_dir
|
18
|
+
end
|
19
|
+
|
20
|
+
World(Work)
|
data/jpi.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "jenkins/plugin/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "jpi"
|
7
|
+
s.version = Jenkins::Plugin::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Charles Lowell", "Jørgen P. Tjernø", "Kohsuke Kawaguchi"]
|
10
|
+
s.email = ["cowboyd@thefrontside.net"]
|
11
|
+
s.homepage = "https://github.com/jenkinsci/jpi.rb"
|
12
|
+
s.summary = %q{Tools for creating and building Jenkins Ruby plugins}
|
13
|
+
s.description = %q{Allows you to generate a new Ruby plugin project, build it, test it in Jenkins and release it to the Jenkins Update Center.}
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_dependency "rubyzip"
|
21
|
+
s.add_dependency "thor"
|
22
|
+
s.add_dependency "jenkins-war", ">= 1.427"
|
23
|
+
s.add_dependency "bundler", "~> 1.1.rc2"
|
24
|
+
s.add_dependency "jenkins-plugin-runtime", "~> 0.1.13"
|
25
|
+
|
26
|
+
s.add_development_dependency "rspec", "~> 2.0"
|
27
|
+
s.add_development_dependency "cucumber", "~> 1.0"
|
28
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Jenkins
|
2
|
+
class CiOrg
|
3
|
+
# credential to access jenkins-ci.org
|
4
|
+
# TODO: move it elsewhere
|
5
|
+
class Credential
|
6
|
+
CREDENTIAL = File.expand_path("~/.jenkins-ci.org")
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@props = {}
|
10
|
+
|
11
|
+
if File.exists?(CREDENTIAL) then
|
12
|
+
File.open(CREDENTIAL,'r') do |f|
|
13
|
+
f.each_line do |l|
|
14
|
+
if l[0]=='#' then
|
15
|
+
return # comment
|
16
|
+
end
|
17
|
+
|
18
|
+
k,v = l.split("=",2)
|
19
|
+
@props[k]=v.strip
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# do we already have the credential?
|
26
|
+
def has_credential?
|
27
|
+
@props["userName"] && @props["password"]
|
28
|
+
end
|
29
|
+
|
30
|
+
def user_name
|
31
|
+
@props["userName"]
|
32
|
+
end
|
33
|
+
|
34
|
+
def password
|
35
|
+
@props["password"]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
|
2
|
+
require 'thor'
|
3
|
+
require 'jenkins/plugin/specification'
|
4
|
+
require 'jenkins/plugin/cli/formatting'
|
5
|
+
require 'jenkins/plugin/cli/new'
|
6
|
+
require 'jenkins/plugin/cli/generate'
|
7
|
+
|
8
|
+
|
9
|
+
module Jenkins
|
10
|
+
class Plugin
|
11
|
+
class CLI < Thor
|
12
|
+
extend Formatting
|
13
|
+
|
14
|
+
register New, "new", "new NAME", "create a new plugin called NAME"
|
15
|
+
register Generate, "generate", "generate [options] [arguments]", "add new classes/templates and views to your project"
|
16
|
+
map "g" => "generate"
|
17
|
+
|
18
|
+
|
19
|
+
desc "build", "build plugin into .hpi file suitable for distribution"
|
20
|
+
def build
|
21
|
+
require 'jenkins/plugin/tools/package'
|
22
|
+
pkg = Tools::Package.new(spec, "pkg")
|
23
|
+
pkg.build
|
24
|
+
pkg
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "server", "run a test server with plugin"
|
28
|
+
method_option :home, :desc => "set server work directory", :default => 'work'
|
29
|
+
method_option :port, :desc => "server http port (currently ignored)", :default => 8080
|
30
|
+
method_option :war, :desc => "specify a custom jenkins.war to run the plugin with"
|
31
|
+
def server
|
32
|
+
require 'jenkins/plugin/tools/server'
|
33
|
+
server = Tools::Server.new(spec, options[:home], options[:war])
|
34
|
+
server.run!
|
35
|
+
end
|
36
|
+
map "s" => "server"
|
37
|
+
|
38
|
+
desc "release", "release to jenkins-ci.org"
|
39
|
+
method_option :release, :desc => "deploy as a release (as opposed to a snapshot)", :type => :boolean
|
40
|
+
def release
|
41
|
+
require 'jenkins/plugin/tools/release'
|
42
|
+
|
43
|
+
Tools::Release.new(spec,build().file_name, !options[:release]).run
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "version", "show jpi version information"
|
47
|
+
def version
|
48
|
+
require 'jenkins/plugin/version'
|
49
|
+
shell.say Jenkins::Plugin::VERSION
|
50
|
+
end
|
51
|
+
map ["-v","--version"] => "version"
|
52
|
+
|
53
|
+
desc "help [COMMAND]", "get help for COMMAND, or for jpi itself"
|
54
|
+
def help(command = nil)
|
55
|
+
super
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def spec
|
61
|
+
Specification.find!
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
|
2
|
+
module Jenkins
|
3
|
+
class Plugin
|
4
|
+
class CLI < Thor
|
5
|
+
module Formatting
|
6
|
+
def task_help(shell, task_name)
|
7
|
+
meth = normalize_task_name(task_name)
|
8
|
+
task = all_tasks[meth]
|
9
|
+
handle_no_task_error(meth) unless task
|
10
|
+
|
11
|
+
shell.say "usage: #{banner(task)}"
|
12
|
+
shell.say
|
13
|
+
class_options_help(shell, nil => task.options.map { |_, o| o })
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def print_options(shell, options, grp = nil)
|
18
|
+
return if options.empty?
|
19
|
+
table = options.map do |option|
|
20
|
+
prototype = if option.default
|
21
|
+
" [#{option.default}]"
|
22
|
+
elsif option.type == :boolean
|
23
|
+
""
|
24
|
+
elsif option.required?
|
25
|
+
" #{option.banner}"
|
26
|
+
else
|
27
|
+
" [#{option.banner}]"
|
28
|
+
end
|
29
|
+
aliases = option.aliases.empty? ? "" : option.aliases.join(" ") + ","
|
30
|
+
[aliases, "--#{option.name}#{prototype}", "\t",option.description]
|
31
|
+
end
|
32
|
+
shell.print_table(table, :ident => 2)
|
33
|
+
shell.say
|
34
|
+
end
|
35
|
+
|
36
|
+
def help(shell, task)
|
37
|
+
list = printable_tasks
|
38
|
+
print shell.set_color("jpi", :black, true)
|
39
|
+
shell.say <<-USEAGE
|
40
|
+
- tools to create, build, develop and release Jenkins plugins
|
41
|
+
|
42
|
+
Usage: jpi command [arguments] [options]
|
43
|
+
|
44
|
+
USEAGE
|
45
|
+
|
46
|
+
shell.say "Commands:"
|
47
|
+
shell.print_table(list, :ident => 2, :truncate => true)
|
48
|
+
shell.say
|
49
|
+
class_options_help(shell)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
module Jenkins
|
3
|
+
class Plugin
|
4
|
+
class CLI
|
5
|
+
class Generate < Thor
|
6
|
+
include Thor::Actions
|
7
|
+
|
8
|
+
source_root File.dirname(__FILE__)
|
9
|
+
|
10
|
+
argument :name
|
11
|
+
|
12
|
+
desc "publisher", "publisher NAME", :desc => "generate a publish step definition"
|
13
|
+
def publisher
|
14
|
+
@step_class = "Publisher"
|
15
|
+
template('templates/build_step.tt', "models/#{name.downcase}_publisher.rb")
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "builder", "builder NAME", :desc => "generate a build step definition"
|
19
|
+
def builder
|
20
|
+
@step_class = "Builder"
|
21
|
+
template('templates/build_step.tt', "models/#{name.downcase}_builder.rb")
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
|
2
|
+
require 'thor/group'
|
3
|
+
|
4
|
+
module Jenkins
|
5
|
+
class Plugin
|
6
|
+
class CLI
|
7
|
+
class New < Thor::Group
|
8
|
+
include Thor::Actions
|
9
|
+
|
10
|
+
source_root File.dirname(__FILE__)
|
11
|
+
|
12
|
+
argument :name
|
13
|
+
|
14
|
+
def create_gemfile
|
15
|
+
template('templates/Gemfile.tt', "#{name}/Gemfile")
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_pluginspec
|
19
|
+
git_name = %x[git config user.name].chomp
|
20
|
+
git_email = %x[git config user.email].chomp
|
21
|
+
|
22
|
+
developer_id = git_email.split('@', 2).first || ''
|
23
|
+
|
24
|
+
# Fallback values.
|
25
|
+
git_name = 'TODO: Put your realname here' if git_name.empty?
|
26
|
+
git_email = 'email@example.com' if git_email.empty?
|
27
|
+
|
28
|
+
opts = {
|
29
|
+
:developer_id => developer_id.empty? ? 'TODO: Put your jenkins-ci.org username here.' : developer_id,
|
30
|
+
:developer_name => "#{git_name} <#{git_email}>"
|
31
|
+
}
|
32
|
+
|
33
|
+
template('templates/pluginspec.tt', "#{name}/#{name}.pluginspec", opts)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
class <%= name.capitalize %><%= @step_class %> < Jenkins::Tasks::<%= @step_class %>
|
3
|
+
|
4
|
+
display_name "<%= name.capitalize %> <%= @step_class.downcase %>"
|
5
|
+
|
6
|
+
##
|
7
|
+
# Runs before the build begins
|
8
|
+
#
|
9
|
+
# @param [Jenkins::Model::Build] build the build which will begin
|
10
|
+
# @param [Jenkins::Model::Listener] listener the listener for this build.
|
11
|
+
def prebuild(build, listener)
|
12
|
+
# do any setup that needs to be done before this build runs.
|
13
|
+
end
|
14
|
+
|
15
|
+
##
|
16
|
+
# Runs the step over the given build and reports the progress to the listener.
|
17
|
+
#
|
18
|
+
# @param [Jenkins::Model::Build] build on which to run this step
|
19
|
+
# @param [Jenkins::Launcher] launcher the launcher that can run code on the node running this build
|
20
|
+
# @param [Jenkins::Model::Listener] listener the listener for this build.
|
21
|
+
def perform(build, launcher, listener)
|
22
|
+
# actually perform the build step
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
Jenkins::Plugin::Specification.new do |plugin|
|
3
|
+
plugin.name = <%= name.inspect %>
|
4
|
+
plugin.display_name = <%= (name.capitalize + " Plugin").inspect %>
|
5
|
+
plugin.version = '0.0.1'
|
6
|
+
plugin.description = 'enter description here'
|
7
|
+
|
8
|
+
# You should create a wiki-page for your plugin when you publish it, see
|
9
|
+
# https://wiki.jenkins-ci.org/display/JENKINS/Hosting+Plugins#HostingPlugins-AddingaWikipage
|
10
|
+
# This line makes sure it's listed in your POM.
|
11
|
+
plugin.url = 'https://wiki.jenkins-ci.org/display/JENKINS/My+Plugin'
|
12
|
+
|
13
|
+
# The first argument is your user name for jenkins-ci.org.
|
14
|
+
plugin.developed_by <%= config[:developer_id].inspect %>, <%= config[:developer_name].inspect %>
|
15
|
+
|
16
|
+
# This specifies where your code is hosted.
|
17
|
+
# Alternatives include:
|
18
|
+
# :github => 'myuser/my-plugin' (without myuser it defaults to jenkinsci)
|
19
|
+
# :git => 'git://repo.or.cz/my-plugin.git'
|
20
|
+
# :svn => 'https://svn.jenkins-ci.org/trunk/hudson/plugins/my-plugin'
|
21
|
+
plugin.uses_repository :github => 'my-plugin'
|
22
|
+
|
23
|
+
# This is a required dependency for every ruby plugin.
|
24
|
+
plugin.depends_on 'ruby-runtime', '0.4'
|
25
|
+
|
26
|
+
# This is a sample dependency for a Jenkins plugin, 'git'.
|
27
|
+
plugin.depends_on 'git', '1.1.11'
|
28
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
module Jenkins
|
3
|
+
class Plugin
|
4
|
+
module Tools
|
5
|
+
class Bundle
|
6
|
+
|
7
|
+
def initialize(target)
|
8
|
+
@target = target
|
9
|
+
end
|
10
|
+
|
11
|
+
def install
|
12
|
+
require 'java'
|
13
|
+
require 'bundler'
|
14
|
+
puts "bundling..."
|
15
|
+
|
16
|
+
# We set these in ENV instead of passing the --without and --path
|
17
|
+
# options because the CLI options are remembered in .bundle/config and
|
18
|
+
# will interfere with regular usage of bundle exec / install.
|
19
|
+
Bundler.with_clean_env {
|
20
|
+
ENV['BUNDLE_APP_CONFIG'] = "#{@target}/vendor/bundle"
|
21
|
+
ENV['BUNDLE_WITHOUT'] = "development"
|
22
|
+
ENV['BUNDLE_PATH'] = "#{@target}/vendor/gems"
|
23
|
+
ENV.delete 'RUBYOPT'
|
24
|
+
system('bundle --standalone')
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'zip/zip'
|
2
|
+
require 'net/http'
|
3
|
+
require 'uri'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
module Jenkins
|
7
|
+
class Plugin
|
8
|
+
module Tools
|
9
|
+
# class for parsing hpi file and its manifests
|
10
|
+
class Hpi
|
11
|
+
attr_reader :file, :manifest
|
12
|
+
|
13
|
+
# take the path name to the plugin file
|
14
|
+
def initialize(file)
|
15
|
+
@file = file
|
16
|
+
|
17
|
+
# load and parse manifests
|
18
|
+
Zip::ZipFile.open(@file) do |zip|
|
19
|
+
zip.get_input_stream("META-INF/MANIFEST.MF") do |m|
|
20
|
+
# main section of the manifest
|
21
|
+
@manifest = parse_manifest(m.read)[0]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# parse dependencies into hash
|
26
|
+
@dependencies = {}
|
27
|
+
deps = @manifest["Plugin-Dependencies"]
|
28
|
+
if deps
|
29
|
+
deps.split(",").each do |token|
|
30
|
+
token = token.gsub(/;.+/,"") # trim off the optional portions
|
31
|
+
name,ver = token.split(":")
|
32
|
+
@dependencies[name] = ver
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# given the plugin short name and the version number,
|
38
|
+
# return the path name of the .hpi file by either locating the plugin locally or downloading it.
|
39
|
+
def self.resolve(short_name,version)
|
40
|
+
# this is where we expect the retrieved file to be
|
41
|
+
cache = File.expand_path "~/.jenkins/cache/plugins/#{short_name}/#{version}/#{short_name}.hpi"
|
42
|
+
|
43
|
+
return cache if File.exists?(cache)
|
44
|
+
|
45
|
+
# now we start looking for places to find them
|
46
|
+
|
47
|
+
# is it in the local maven2 repository?
|
48
|
+
maven = File.expand_path "~/.m2/repository/org/jenkins-ci/plugins/#{short_name}/#{version}/#{short_name}-#{version}.hpi"
|
49
|
+
return maven if File.exists?(maven)
|
50
|
+
|
51
|
+
# download from the community update center
|
52
|
+
FileUtils.mkdir_p(File.dirname(cache))
|
53
|
+
open(cache+".tmp","wb") do |f|
|
54
|
+
puts "Downloading #{short_name} #{version}"
|
55
|
+
url = "http://updates.jenkins-ci.org/download/plugins/#{short_name}/#{version}/#{short_name}.hpi?for=ruby-plugin"
|
56
|
+
puts " from #{url}"
|
57
|
+
f.write fetch(url).body
|
58
|
+
end
|
59
|
+
FileUtils.mv cache+".tmp", cache
|
60
|
+
|
61
|
+
return cache
|
62
|
+
end
|
63
|
+
|
64
|
+
# download with redirect support
|
65
|
+
def self.fetch(uri, limit = 10)
|
66
|
+
# You should choose better exception.
|
67
|
+
raise ArgumentError, 'HTTP redirect too deep' if limit == 0
|
68
|
+
|
69
|
+
response = Net::HTTP.get_response(URI.parse(uri))
|
70
|
+
case response
|
71
|
+
when Net::HTTPSuccess then response
|
72
|
+
when Net::HTTPRedirection then fetch(response['location'], limit - 1)
|
73
|
+
else
|
74
|
+
response.error!
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# parse manifest file text into a hash
|
79
|
+
def parse_manifest(txt)
|
80
|
+
# separators
|
81
|
+
nl = /\r\n|\n|\r[^\n]/
|
82
|
+
secsep = /(#{nl}){2}/
|
83
|
+
|
84
|
+
txt.split(secsep).reject { |s| s.chomp.length==0 }.map do |section|
|
85
|
+
lines = []
|
86
|
+
section.split(nl).each do |line|
|
87
|
+
if line[0]==0x20
|
88
|
+
lines.last << line[1..-1] # continuation of the previous line
|
89
|
+
else
|
90
|
+
lines << line
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# convert to hash
|
95
|
+
hash = {}
|
96
|
+
lines.each do |l|
|
97
|
+
(k,v) = l.split(/: /,2)
|
98
|
+
hash[k] = v
|
99
|
+
end
|
100
|
+
|
101
|
+
hash
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Jenkins
|
2
|
+
class Plugin
|
3
|
+
module Tools
|
4
|
+
class Loadpath
|
5
|
+
def initialize(*groups)
|
6
|
+
require 'bundler'
|
7
|
+
@groups = groups.empty? ? [:default] : groups
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_path
|
11
|
+
to_a.join(File::PATH_SEPARATOR)
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_a
|
15
|
+
[].tap do |paths|
|
16
|
+
specs = Bundler.definition.specs_for @groups.map {|g| g.to_sym}
|
17
|
+
for spec in specs
|
18
|
+
next if spec.name == "bundler"
|
19
|
+
for path in spec.require_paths
|
20
|
+
paths << File.join(spec.full_gem_path, path)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
|
2
|
+
#require 'jenkins/plugin/version'
|
3
|
+
|
4
|
+
require 'jenkins/plugin/version'
|
5
|
+
require 'etc'
|
6
|
+
|
7
|
+
module Jenkins
|
8
|
+
class Plugin
|
9
|
+
module Tools
|
10
|
+
class Manifest
|
11
|
+
|
12
|
+
def initialize(spec)
|
13
|
+
@spec = spec
|
14
|
+
end
|
15
|
+
|
16
|
+
def write_hpi(io)
|
17
|
+
w = Writer.new(io)
|
18
|
+
w.put "Manifest-Version", "1.0"
|
19
|
+
w.put "Created-By", Jenkins::Plugin::VERSION
|
20
|
+
w.put "Build-Ruby-Platform", RUBY_PLATFORM
|
21
|
+
w.put "Build-Ruby-Version", RUBY_VERSION
|
22
|
+
w.put "Built-By", Etc.getlogin()
|
23
|
+
|
24
|
+
w.put "Group-Id", "org.jenkins-ci.plugins"
|
25
|
+
w.put "Short-Name", @spec.name
|
26
|
+
w.put "Long-Name", @spec.display_name
|
27
|
+
w.put "Url", @spec.url if @spec.url
|
28
|
+
|
29
|
+
w.put "Plugin-Class", "ruby.RubyPlugin"
|
30
|
+
w.put "Plugin-Version", @spec.version
|
31
|
+
w.put "Jenkins-Version", "1.432"
|
32
|
+
|
33
|
+
w.put "Plugin-Dependencies", @spec.dependencies.map{|k,v| "#{k}:#{v}"}.join(",")
|
34
|
+
end
|
35
|
+
|
36
|
+
def write_hpl(io, loadpath)
|
37
|
+
write_hpi(io)
|
38
|
+
|
39
|
+
w = Writer.new(io)
|
40
|
+
w.put "Load-Path", loadpath.to_a.join(':')
|
41
|
+
w.put "Lib-Path", "#{Dir.pwd}/lib/"
|
42
|
+
w.put "Models-Path", "#{Dir.pwd}/models"
|
43
|
+
# Stapler expects view erb/haml scripts to be in the JVM ClassPath
|
44
|
+
w.put "Class-Path", "#{Dir.pwd}/views" if File.exists?("#{Dir.pwd}/views")
|
45
|
+
# Directory for static images, javascript, css, etc. of this plugin.
|
46
|
+
# The static resources are mapped under #CONTEXTPATH/plugin/SHORTNAME/
|
47
|
+
w.put "Resource-Path", "#{Dir.pwd}/static"
|
48
|
+
end
|
49
|
+
|
50
|
+
class Writer
|
51
|
+
|
52
|
+
MAX_LENGTH = 72.to_i
|
53
|
+
|
54
|
+
def initialize(io)
|
55
|
+
@io = io
|
56
|
+
end
|
57
|
+
|
58
|
+
def put(key, value)
|
59
|
+
@io.puts "#{key}: #{manifest_truncate(value)}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def manifest_truncate(message)
|
63
|
+
if message.length < MAX_LENGTH
|
64
|
+
return message
|
65
|
+
end
|
66
|
+
|
67
|
+
line = message[0 ... MAX_LENGTH] + "\n"
|
68
|
+
offset = MAX_LENGTH
|
69
|
+
|
70
|
+
while offset < message.length
|
71
|
+
line += " #{message[offset ... (offset + MAX_LENGTH - 1)]}\n"
|
72
|
+
offset += (MAX_LENGTH - 1)
|
73
|
+
end
|
74
|
+
return line
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'jenkins/plugin/tools/bundle'
|
2
|
+
require 'jenkins/plugin/tools/manifest'
|
3
|
+
require 'zip/zip'
|
4
|
+
|
5
|
+
module Jenkins
|
6
|
+
class Plugin
|
7
|
+
module Tools
|
8
|
+
class Package
|
9
|
+
|
10
|
+
def initialize(spec,target)
|
11
|
+
@target = target
|
12
|
+
@spec = spec
|
13
|
+
end
|
14
|
+
|
15
|
+
# where to generate the package?
|
16
|
+
def file_name
|
17
|
+
file_name = "#{@target}/#{@spec.name}.hpi"
|
18
|
+
end
|
19
|
+
|
20
|
+
def build
|
21
|
+
FileUtils.mkdir_p @target
|
22
|
+
|
23
|
+
Bundle.new(@target).install
|
24
|
+
|
25
|
+
manifest = Manifest.new(@spec)
|
26
|
+
|
27
|
+
File.delete file_name if File.exists?(file_name)
|
28
|
+
|
29
|
+
Zip::ZipFile.open(file_name, Zip::ZipFile::CREATE) do |zipfile|
|
30
|
+
zipfile.get_output_stream("META-INF/MANIFEST.MF") do |f|
|
31
|
+
manifest.write_hpi(f)
|
32
|
+
f.puts "Bundle-Path: vendor/gems"
|
33
|
+
end
|
34
|
+
zipfile.mkdir("WEB-INF/classes")
|
35
|
+
|
36
|
+
["lib","models","#{@target}/vendor"].each do |d|
|
37
|
+
Dir.glob("#{d}/**/*") do |f|
|
38
|
+
if !File.directory? f
|
39
|
+
p = f.gsub("#{@target}/",'')
|
40
|
+
if p !~ %r{/cache/}
|
41
|
+
zipfile.add("WEB-INF/classes/#{p}",f)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# stapler expects views to be directly in the classpath without any prefix
|
48
|
+
Dir.glob("views/**/*") do |f|
|
49
|
+
if !File.directory? f
|
50
|
+
zipfile.add("WEB-INF/classes/#{f[6..-1]}",f)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
puts "#{@spec.name} plugin #{@spec.version} built to #{file_name}"
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'jenkins/plugin/tools/bundle'
|
2
|
+
require 'jenkins/plugin/tools/manifest'
|
3
|
+
require 'jenkins/jenkins-ci.org/credential'
|
4
|
+
require 'net/http'
|
5
|
+
require 'erb'
|
6
|
+
|
7
|
+
module Jenkins
|
8
|
+
class Plugin
|
9
|
+
module Tools
|
10
|
+
# task for deploying a plugin
|
11
|
+
class Release
|
12
|
+
|
13
|
+
def initialize(spec,hpi,snapshot)
|
14
|
+
@spec = spec
|
15
|
+
@hpi = hpi # hpi file to release
|
16
|
+
@snapshot = snapshot # if true, deploy as a snapshot, otherwise as release
|
17
|
+
end
|
18
|
+
|
19
|
+
def check_error(rsp)
|
20
|
+
# in case of 401 Unauthorized, the server just resets the connection and Net::HTTP fails to parse the response,
|
21
|
+
# so we don't really get any meaningful error message.
|
22
|
+
rsp.value # TODO: is this how we check for the error?
|
23
|
+
end
|
24
|
+
|
25
|
+
def each_developer
|
26
|
+
@spec.developers.each do |id, name|
|
27
|
+
email = ''
|
28
|
+
if name =~ /^(.*)<([^>]+)>$/
|
29
|
+
name = $1
|
30
|
+
email = $2.strip
|
31
|
+
end
|
32
|
+
|
33
|
+
yield id, name.strip, email
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def run
|
38
|
+
cred = Jenkins::CiOrg::Credential.new
|
39
|
+
if !cred.has_credential? then
|
40
|
+
raise Exception.new("no credential available to connect to jenkins-ci.org. Please create ~/.jenkins-ci.org. See https://wiki.jenkins-ci.org/display/JENKINS/Dot+Jenkins+Ci+Dot+Org")
|
41
|
+
end
|
42
|
+
|
43
|
+
http = Net::HTTP.new("maven.jenkins-ci.org",8081)
|
44
|
+
|
45
|
+
puts @snapshot ? "deploying as a snapshot" : "deploying as a release"
|
46
|
+
puts "Generating POM"
|
47
|
+
version = @snapshot ? @spec.version+"-SNAPSHOT" : @spec.version
|
48
|
+
pom = ERB.new(File.read(File.dirname(__FILE__)+"/templates/release-pom.xml.erb")).result(binding)
|
49
|
+
|
50
|
+
path = "/content/repositories/#{@snapshot?'snapshots':'releases'}/org/jenkins-ci/ruby-plugins/#{@spec.name}/#{version}/#{@spec.name}-#{version}"
|
51
|
+
req = Net::HTTP::Put.new("#{path}.pom")
|
52
|
+
req.body = pom
|
53
|
+
req.basic_auth(cred.user_name,cred.password)
|
54
|
+
check_error(http.request(req))
|
55
|
+
|
56
|
+
puts "Uploading #{@hpi}"
|
57
|
+
File.open(@hpi,'r') do |f|
|
58
|
+
req = Net::HTTP::Put.new("#{path}.hpi")
|
59
|
+
req.body_stream = f
|
60
|
+
req.basic_auth(cred.user_name,cred.password)
|
61
|
+
req.content_length = File.size(@hpi)
|
62
|
+
check_error(http.request(req))
|
63
|
+
end
|
64
|
+
|
65
|
+
puts "See http://maven.jenkins-ci.org"+File.dirname(path)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Jenkins
|
4
|
+
class Plugin
|
5
|
+
module Tools
|
6
|
+
class Resolver
|
7
|
+
|
8
|
+
def initialize(spec, dir)
|
9
|
+
@spec = spec
|
10
|
+
@dir = dir
|
11
|
+
FileUtils.mkdir_p(dir) unless File.directory? @dir
|
12
|
+
end
|
13
|
+
|
14
|
+
def resolve!
|
15
|
+
@spec.dependencies.each do |name, version|
|
16
|
+
FileUtils.cp resolve(name, version), @dir
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def resolve(short_name,version)
|
21
|
+
# this is where we expect the retrieved file to be
|
22
|
+
cache = File.expand_path "~/.jenkins/cache/plugins/#{short_name}/#{version}/#{short_name}.hpi"
|
23
|
+
|
24
|
+
return cache if File.exists?(cache)
|
25
|
+
|
26
|
+
# now we start looking for places to find them
|
27
|
+
|
28
|
+
# is it in the local maven2 repository?
|
29
|
+
maven = File.expand_path "~/.m2/repository/org/jenkins-ci/plugins/#{short_name}/#{version}/#{short_name}-#{version}.hpi"
|
30
|
+
return maven if File.exists?(maven)
|
31
|
+
|
32
|
+
# download from the community update center
|
33
|
+
FileUtils.mkdir_p(File.dirname(cache))
|
34
|
+
open(cache+".tmp","wb") do |f|
|
35
|
+
puts "Downloading #{short_name} #{version}"
|
36
|
+
url = "http://updates.jenkins-ci.org/download/plugins/#{short_name}/#{version}/#{short_name}.hpi?for=ruby-plugin"
|
37
|
+
puts " from #{url}"
|
38
|
+
f.write fetch(url).body
|
39
|
+
end
|
40
|
+
FileUtils.mv cache+".tmp", cache
|
41
|
+
|
42
|
+
return cache
|
43
|
+
end
|
44
|
+
|
45
|
+
# download with redirect support
|
46
|
+
def fetch(uri, limit = 10)
|
47
|
+
# You should choose better exception.
|
48
|
+
raise ArgumentError, 'HTTP redirect too deep' if limit == 0
|
49
|
+
|
50
|
+
response = Net::HTTP.get_response(URI.parse(uri))
|
51
|
+
case response
|
52
|
+
when Net::HTTPSuccess then response
|
53
|
+
when Net::HTTPRedirection then fetch(response['location'], limit - 1)
|
54
|
+
else
|
55
|
+
response.error!
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'jenkins/plugin/tools/loadpath'
|
2
|
+
require 'jenkins/plugin/tools/resolver'
|
3
|
+
require 'jenkins/plugin/tools/manifest'
|
4
|
+
require 'jenkins/war'
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
module Jenkins
|
8
|
+
class Plugin
|
9
|
+
module Tools
|
10
|
+
class Server
|
11
|
+
|
12
|
+
def initialize(spec, workdir, war)
|
13
|
+
@spec = spec
|
14
|
+
@workdir = workdir
|
15
|
+
@plugindir = "#{workdir}/plugins"
|
16
|
+
@war = war || Jenkins::War::LOCATION
|
17
|
+
end
|
18
|
+
|
19
|
+
def run!
|
20
|
+
FileUtils.mkdir_p(@plugindir)
|
21
|
+
loadpath = Jenkins::Plugin::Tools::Loadpath.new
|
22
|
+
manifest = Jenkins::Plugin::Tools::Manifest.new(@spec)
|
23
|
+
resolver = Jenkins::Plugin::Tools::Resolver.new(@spec, @plugindir)
|
24
|
+
|
25
|
+
resolver.resolve!
|
26
|
+
# generate the plugin manifest
|
27
|
+
|
28
|
+
File.open("#{@plugindir}/#{@spec.name}.hpl",mode="w+") do |f|
|
29
|
+
manifest.write_hpl(f, loadpath)
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
# execute Jenkins
|
34
|
+
args = []
|
35
|
+
args << "java"
|
36
|
+
args << "-Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=n"
|
37
|
+
args << "-DJENKINS_HOME=#{@workdir}"
|
38
|
+
args << "-Dstapler.trace=true"
|
39
|
+
args << "-Ddebug.YUI=true"
|
40
|
+
# args << "-Djruby.debug.loadService=true"
|
41
|
+
# args << "-Djruby.debug.loadService.timing=true"
|
42
|
+
args << "-jar"
|
43
|
+
args << @war
|
44
|
+
exec *args
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
2
|
+
<modelVersion>4.0.0</modelVersion>
|
3
|
+
<parent>
|
4
|
+
<groupId>org.jenkins-ci.plugins</groupId>
|
5
|
+
<artifactId>plugin</artifactId>
|
6
|
+
<version>1.420</version>
|
7
|
+
</parent>
|
8
|
+
|
9
|
+
<groupId>org.jenkins-ci.ruby-plugins</groupId>
|
10
|
+
<artifactId><%= @spec.name %></artifactId>
|
11
|
+
<version><%= version %></version>
|
12
|
+
<name><%= @spec.display_name %></name>
|
13
|
+
<description><%= @spec.description %></description>
|
14
|
+
<packaging>hpi</packaging>
|
15
|
+
|
16
|
+
<% if @spec.url %>
|
17
|
+
<url><%= @spec.url %></url>
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
<repositories>
|
21
|
+
<repository>
|
22
|
+
<id>m.g.o-public</id>
|
23
|
+
<url>http://maven.glassfish.org/content/groups/public/</url>
|
24
|
+
</repository>
|
25
|
+
</repositories>
|
26
|
+
|
27
|
+
<developers>
|
28
|
+
<% each_developer do |id, name, email| %>
|
29
|
+
<developer>
|
30
|
+
<id><%= id %></id>
|
31
|
+
<name><%= name %></name>
|
32
|
+
<% if not email.empty? %>
|
33
|
+
<email><%= email %></email>
|
34
|
+
<% end %>
|
35
|
+
</developer>
|
36
|
+
<% end %>
|
37
|
+
</developers>
|
38
|
+
|
39
|
+
<dependencies>
|
40
|
+
<% @spec.dependencies.each do |k,v| %>
|
41
|
+
<dependency>
|
42
|
+
<groupId>org.jenkins-ci.plugins</groupId><!-- TODO: needs to figure out correct groupId -->
|
43
|
+
<artifactId><%= k %></artifactId>
|
44
|
+
<version><%= v %></version>
|
45
|
+
</dependency>
|
46
|
+
<% end %>
|
47
|
+
</dependencies>
|
48
|
+
|
49
|
+
<% if @spec.repository %>
|
50
|
+
<scm>
|
51
|
+
<connection>scm:<%= @spec.repository[:type] %>:<%= @spec.repository[:url] %></connection>
|
52
|
+
</scm>
|
53
|
+
<% end %>
|
54
|
+
</project>
|
data/lib/jenkins/rake.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'jenkins/plugin/version'
|
2
|
+
require 'jenkins/plugin/specification'
|
3
|
+
require 'jenkins/plugin/tools/hpi'
|
4
|
+
require 'jenkins/plugin/tools/loadpath'
|
5
|
+
require 'zip/zip'
|
6
|
+
|
7
|
+
module Jenkins
|
8
|
+
# given the IO handle, produce the basic manifest entries that are common between hpi and hpl formats
|
9
|
+
|
10
|
+
def self.spec
|
11
|
+
@spec ||= Jenkins::Plugin::Specification.load(Dir['*.pluginspec'].first)
|
12
|
+
end
|
13
|
+
|
14
|
+
class Rake
|
15
|
+
def self.install_tasks
|
16
|
+
self.new.install
|
17
|
+
end
|
18
|
+
|
19
|
+
include ::Rake::DSL if defined? ::Rake::DSL
|
20
|
+
|
21
|
+
def install
|
22
|
+
desc "Directory used as JENKINS_HOME during 'rake server'"
|
23
|
+
directory work = "work"
|
24
|
+
|
25
|
+
desc "remove built artifacts"
|
26
|
+
task :clean do
|
27
|
+
sh "rm -rf pkg"
|
28
|
+
sh "rm -rf vendor"
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "output the development servers loadpath"
|
32
|
+
task :loadpath do
|
33
|
+
loadpath = Jenkins::Plugin::Tools::Loadpath.new(:default)
|
34
|
+
puts loadpath.to_path
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "package up stuff into HPI file"
|
38
|
+
task :package do
|
39
|
+
require 'jenkins/plugin/tools/package'
|
40
|
+
Jenkins::Plugin::Tools::Package.new(Jenkins.spec,"pkg").build
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "run a Jenkins server with this plugin"
|
44
|
+
task :server do
|
45
|
+
require 'jenkins/plugin/tools/server'
|
46
|
+
|
47
|
+
server = Jenkins::Plugin::Tools::Server.new(Jenkins.spec, "work")
|
48
|
+
server.run!
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
metadata
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jpi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.3.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Charles Lowell
|
9
|
+
- "J\xC3\xB8rgen P. Tjern\xC3\xB8"
|
10
|
+
- Kohsuke Kawaguchi
|
11
|
+
autorequire:
|
12
|
+
bindir: bin
|
13
|
+
cert_chain: []
|
14
|
+
|
15
|
+
date: 2011-12-19 00:00:00 Z
|
16
|
+
dependencies:
|
17
|
+
- !ruby/object:Gem::Dependency
|
18
|
+
name: rubyzip
|
19
|
+
prerelease: false
|
20
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
21
|
+
none: false
|
22
|
+
requirements:
|
23
|
+
- - ">="
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: "0"
|
26
|
+
type: :runtime
|
27
|
+
version_requirements: *id001
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: thor
|
30
|
+
prerelease: false
|
31
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
32
|
+
none: false
|
33
|
+
requirements:
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: "0"
|
37
|
+
type: :runtime
|
38
|
+
version_requirements: *id002
|
39
|
+
- !ruby/object:Gem::Dependency
|
40
|
+
name: jenkins-war
|
41
|
+
prerelease: false
|
42
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: "1.427"
|
48
|
+
type: :runtime
|
49
|
+
version_requirements: *id003
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: bundler
|
52
|
+
prerelease: false
|
53
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ~>
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: 1.1.rc2
|
59
|
+
type: :runtime
|
60
|
+
version_requirements: *id004
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: jenkins-plugin-runtime
|
63
|
+
prerelease: false
|
64
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.1.13
|
70
|
+
type: :runtime
|
71
|
+
version_requirements: *id005
|
72
|
+
- !ruby/object:Gem::Dependency
|
73
|
+
name: rspec
|
74
|
+
prerelease: false
|
75
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ~>
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: "2.0"
|
81
|
+
type: :development
|
82
|
+
version_requirements: *id006
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: cucumber
|
85
|
+
prerelease: false
|
86
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ~>
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: "1.0"
|
92
|
+
type: :development
|
93
|
+
version_requirements: *id007
|
94
|
+
description: Allows you to generate a new Ruby plugin project, build it, test it in Jenkins and release it to the Jenkins Update Center.
|
95
|
+
email:
|
96
|
+
- cowboyd@thefrontside.net
|
97
|
+
executables:
|
98
|
+
- jpi
|
99
|
+
extensions: []
|
100
|
+
|
101
|
+
extra_rdoc_files: []
|
102
|
+
|
103
|
+
files:
|
104
|
+
- .gitignore
|
105
|
+
- Gemfile
|
106
|
+
- README.md
|
107
|
+
- Rakefile
|
108
|
+
- bin/jpi
|
109
|
+
- features/create-new-plugin.feature
|
110
|
+
- features/support/create_new_plugin_steps.rb
|
111
|
+
- features/support/directory_structure.rb
|
112
|
+
- features/support/work.rb
|
113
|
+
- jpi.gemspec
|
114
|
+
- lib/jenkins/jenkins-ci.org/credential.rb
|
115
|
+
- lib/jenkins/plugin/cli.rb
|
116
|
+
- lib/jenkins/plugin/cli/formatting.rb
|
117
|
+
- lib/jenkins/plugin/cli/generate.rb
|
118
|
+
- lib/jenkins/plugin/cli/new.rb
|
119
|
+
- lib/jenkins/plugin/cli/templates/Gemfile.tt
|
120
|
+
- lib/jenkins/plugin/cli/templates/build_step.tt
|
121
|
+
- lib/jenkins/plugin/cli/templates/pluginspec.tt
|
122
|
+
- lib/jenkins/plugin/tools/bundle.rb
|
123
|
+
- lib/jenkins/plugin/tools/hpi.rb
|
124
|
+
- lib/jenkins/plugin/tools/loadpath.rb
|
125
|
+
- lib/jenkins/plugin/tools/manifest.rb
|
126
|
+
- lib/jenkins/plugin/tools/package.rb
|
127
|
+
- lib/jenkins/plugin/tools/release.rb
|
128
|
+
- lib/jenkins/plugin/tools/resolver.rb
|
129
|
+
- lib/jenkins/plugin/tools/server.rb
|
130
|
+
- lib/jenkins/plugin/tools/templates/release-pom.xml.erb
|
131
|
+
- lib/jenkins/plugin/version.rb
|
132
|
+
- lib/jenkins/rake.rb
|
133
|
+
homepage: https://github.com/jenkinsci/jpi.rb
|
134
|
+
licenses: []
|
135
|
+
|
136
|
+
post_install_message:
|
137
|
+
rdoc_options: []
|
138
|
+
|
139
|
+
require_paths:
|
140
|
+
- lib
|
141
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
142
|
+
none: false
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: "0"
|
147
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
148
|
+
none: false
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: "0"
|
153
|
+
requirements: []
|
154
|
+
|
155
|
+
rubyforge_project:
|
156
|
+
rubygems_version: 1.8.9
|
157
|
+
signing_key:
|
158
|
+
specification_version: 3
|
159
|
+
summary: Tools for creating and building Jenkins Ruby plugins
|
160
|
+
test_files:
|
161
|
+
- features/create-new-plugin.feature
|
162
|
+
- features/support/create_new_plugin_steps.rb
|
163
|
+
- features/support/directory_structure.rb
|
164
|
+
- features/support/work.rb
|