jenkins_pipeline_builder 0.10.16 → 0.11.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.
- checksums.yaml +8 -8
- data/.rubocop.yml +4 -4
- data/lib/jenkins_pipeline_builder.rb +5 -0
- data/lib/jenkins_pipeline_builder/compiler.rb +27 -24
- data/lib/jenkins_pipeline_builder/extension_dsl.rb +1 -0
- data/lib/jenkins_pipeline_builder/extension_set.rb +8 -8
- data/lib/jenkins_pipeline_builder/extensions.rb +12 -24
- data/lib/jenkins_pipeline_builder/extensions/builders.rb +36 -27
- data/lib/jenkins_pipeline_builder/extensions/helpers/builders/blocking_downstream_helper.rb +18 -0
- data/lib/jenkins_pipeline_builder/extensions/helpers/builders/maven3_helper.rb +11 -0
- data/lib/jenkins_pipeline_builder/extensions/helpers/extension_helper.rb +26 -0
- data/lib/jenkins_pipeline_builder/extensions/helpers/job_attributes/parameters_helper.rb +18 -0
- data/lib/jenkins_pipeline_builder/extensions/helpers/publishers/cobertura_report_helper.rb +40 -0
- data/lib/jenkins_pipeline_builder/extensions/helpers/publishers/email_ext_helper.rb +148 -0
- data/lib/jenkins_pipeline_builder/extensions/helpers/triggers/upstream_helper.rb +21 -0
- data/lib/jenkins_pipeline_builder/extensions/job_attributes.rb +1 -15
- data/lib/jenkins_pipeline_builder/extensions/publishers.rb +263 -6
- data/lib/jenkins_pipeline_builder/extensions/triggers.rb +3 -17
- data/lib/jenkins_pipeline_builder/extensions/wrappers.rb +3 -3
- data/lib/jenkins_pipeline_builder/generator.rb +10 -11
- data/lib/jenkins_pipeline_builder/job.rb +29 -25
- data/lib/jenkins_pipeline_builder/job_collection.rb +31 -21
- data/lib/jenkins_pipeline_builder/module_registry.rb +5 -1
- data/lib/jenkins_pipeline_builder/project.rb +28 -0
- data/lib/jenkins_pipeline_builder/pull_request_generator.rb +8 -8
- data/lib/jenkins_pipeline_builder/version.rb +1 -1
- data/spec/lib/jenkins_pipeline_builder/extension_dsl_spec.rb +43 -0
- data/spec/lib/jenkins_pipeline_builder/extension_set_spec.rb +110 -0
- data/spec/lib/jenkins_pipeline_builder/extensions/builders_spec.rb +56 -0
- data/spec/lib/jenkins_pipeline_builder/extensions/job_attributes_spec.rb +85 -0
- data/spec/lib/jenkins_pipeline_builder/extensions/publishers_spec.rb +81 -9
- data/spec/lib/jenkins_pipeline_builder/extensions/registered_spec.rb +134 -0
- data/spec/lib/jenkins_pipeline_builder/extensions/triggers_spec.rb +88 -0
- data/spec/lib/jenkins_pipeline_builder/extensions_spec.rb +0 -97
- data/spec/lib/jenkins_pipeline_builder/fixtures/job_collection/extensions/extension.rb +11 -0
- data/spec/lib/jenkins_pipeline_builder/fixtures/job_collection/extensions/helpers/my_test_thing_helper.rb +5 -0
- data/spec/lib/jenkins_pipeline_builder/job_collection_spec.rb +46 -0
- data/spec/lib/jenkins_pipeline_builder/module_registry_spec.rb +1 -110
- data/spec/lib/jenkins_pipeline_builder/spec_helper.rb +12 -0
- metadata +24 -2
@@ -76,27 +76,13 @@ trigger do
|
|
76
76
|
announced false
|
77
77
|
|
78
78
|
xml do |params|
|
79
|
-
case params[:status]
|
80
|
-
when 'unstable'
|
81
|
-
name = 'UNSTABLE'
|
82
|
-
ordinal = '1'
|
83
|
-
color = 'yellow'
|
84
|
-
when 'failed'
|
85
|
-
name = 'FAILURE'
|
86
|
-
ordinal = '2'
|
87
|
-
color = 'RED'
|
88
|
-
else
|
89
|
-
name = 'SUCCESS'
|
90
|
-
ordinal = '0'
|
91
|
-
color = 'BLUE'
|
92
|
-
end
|
93
79
|
send('jenkins.triggers.ReverseBuildTrigger') do
|
94
80
|
spec
|
95
81
|
upstreamProjects params[:projects]
|
96
82
|
send('threshold') do
|
97
|
-
name name
|
98
|
-
ordinal ordinal
|
99
|
-
color color
|
83
|
+
name params.name
|
84
|
+
ordinal params.ordinal
|
85
|
+
color params.color
|
100
86
|
completeBuild true
|
101
87
|
end
|
102
88
|
end
|
@@ -92,11 +92,11 @@ wrapper do
|
|
92
92
|
|
93
93
|
xml do |wrapper|
|
94
94
|
EnvInjectPasswordWrapper do
|
95
|
-
if wrapper.
|
96
|
-
passwords = wrapper
|
97
|
-
else
|
95
|
+
if wrapper.respond_to? :keys
|
98
96
|
injectGlobalPasswords wrapper[:inject_global_passwords]
|
99
97
|
passwords = wrapper[:passwords]
|
98
|
+
else
|
99
|
+
passwords = wrapper
|
100
100
|
end
|
101
101
|
break unless passwords
|
102
102
|
passwordEntries do
|
@@ -69,13 +69,7 @@ module JenkinsPipelineBuilder
|
|
69
69
|
errors = {}
|
70
70
|
job_collection.projects.each do |project|
|
71
71
|
next unless project[:name] == project_name || project_name.nil?
|
72
|
-
|
73
|
-
|
74
|
-
pull_request_generator = JenkinsPipelineBuilder::PullRequestGenerator.new project, self
|
75
|
-
|
76
|
-
unless pull_request_generator.valid?
|
77
|
-
errors[pull_request_generator.pull_generator[:name]] = pull_request_generator.errors
|
78
|
-
end
|
72
|
+
errors.merge! process_pull_request_project project
|
79
73
|
|
80
74
|
end
|
81
75
|
errors.each do |k, v|
|
@@ -132,12 +126,17 @@ module JenkinsPipelineBuilder
|
|
132
126
|
[true, project]
|
133
127
|
end
|
134
128
|
|
135
|
-
#
|
136
|
-
# BEGIN PRIVATE METHODS
|
137
|
-
#
|
138
|
-
|
139
129
|
private
|
140
130
|
|
131
|
+
def process_pull_request_project(project)
|
132
|
+
logger.info "Using Project #{project}"
|
133
|
+
|
134
|
+
pull_request_generator = JenkinsPipelineBuilder::PullRequestGenerator.new project, self
|
135
|
+
|
136
|
+
return {} if pull_request_generator.valid?
|
137
|
+
{ pull_request_generator.pull_generator[:name] => pull_request_generator.errors }
|
138
|
+
end
|
139
|
+
|
141
140
|
def prepare_jobs(jobs)
|
142
141
|
jobs.map! do |job|
|
143
142
|
job.is_a?(String) ? { job.to_sym => {} } : job
|
@@ -18,13 +18,7 @@ module JenkinsPipelineBuilder
|
|
18
18
|
success, payload = to_xml
|
19
19
|
return success, payload unless success
|
20
20
|
xml = payload
|
21
|
-
if JenkinsPipelineBuilder.debug || JenkinsPipelineBuilder.file_mode
|
22
|
-
logger.info "Will create job #{job}"
|
23
|
-
logger.info "#{xml}" if @debug
|
24
|
-
FileUtils.mkdir_p(out_dir) unless File.exist?(out_dir)
|
25
|
-
File.open("#{out_dir}/#{name}.xml", 'w') { |f| f.write xml }
|
26
|
-
return [true, nil]
|
27
|
-
end
|
21
|
+
return local_output(xml) if JenkinsPipelineBuilder.debug || JenkinsPipelineBuilder.file_mode
|
28
22
|
|
29
23
|
if JenkinsPipelineBuilder.client.job.exists?(name)
|
30
24
|
JenkinsPipelineBuilder.client.job.update(name, xml)
|
@@ -39,28 +33,38 @@ module JenkinsPipelineBuilder
|
|
39
33
|
|
40
34
|
logger.info "Creating Yaml Job #{job}"
|
41
35
|
job[:job_type] = 'free_style' unless job[:job_type]
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
when 'multi_project'
|
47
|
-
# TODO: Add multi_job as another, more logically named option
|
48
|
-
@xml = setup_freestyle_base(job)
|
49
|
-
payload = adjust_multi_project
|
50
|
-
when 'build_flow'
|
51
|
-
@xml = setup_freestyle_base(job)
|
52
|
-
payload = add_job_dsl
|
53
|
-
when 'free_style', 'pull_request_generator'
|
54
|
-
payload = setup_freestyle_base job
|
55
|
-
else
|
56
|
-
return false, "Job type: #{job[:job_type]} is not one of job_dsl, multi_project, build_flow or free_style"
|
57
|
-
end
|
36
|
+
type = job[:job_type]
|
37
|
+
return false, "Job type: #{type} is not one of #{job_methods.join(', ')}" unless known_type? type
|
38
|
+
@xml = setup_freestyle_base(job)
|
39
|
+
payload = send("update_#{type}")
|
58
40
|
|
59
41
|
[true, payload]
|
60
42
|
end
|
61
43
|
|
62
44
|
private
|
63
45
|
|
46
|
+
[:free_style, :pull_request_generator].each do |method_name|
|
47
|
+
define_method "update_#{method_name}" do
|
48
|
+
@xml
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def known_type?(type)
|
53
|
+
job_methods.include? type
|
54
|
+
end
|
55
|
+
|
56
|
+
def job_methods
|
57
|
+
%w(job_dsl multi_project build_flow free_style pull_request_generator)
|
58
|
+
end
|
59
|
+
|
60
|
+
def local_output(xml)
|
61
|
+
logger.info "Will create job #{job}"
|
62
|
+
logger.info "#{xml}" if @debug
|
63
|
+
FileUtils.mkdir_p(out_dir) unless File.exist?(out_dir)
|
64
|
+
File.open("#{out_dir}/#{name}.xml", 'w') { |f| f.write xml }
|
65
|
+
[true, nil]
|
66
|
+
end
|
67
|
+
|
64
68
|
def out_dir
|
65
69
|
'out/xml'
|
66
70
|
end
|
@@ -88,14 +92,14 @@ module JenkinsPipelineBuilder
|
|
88
92
|
end
|
89
93
|
end
|
90
94
|
|
91
|
-
def
|
95
|
+
def update_multi_project
|
92
96
|
n_xml = Nokogiri::XML(@xml)
|
93
97
|
root = n_xml.root
|
94
98
|
root.name = 'com.tikal.jenkins.plugins.multijob.MultiJobProject'
|
95
99
|
n_xml.to_xml
|
96
100
|
end
|
97
101
|
|
98
|
-
def
|
102
|
+
def update_build_flow
|
99
103
|
n_xml = Nokogiri::XML(@xml)
|
100
104
|
n_xml.root.name = 'com.cloudbees.plugins.flow.BuildFlow'
|
101
105
|
Nokogiri::XML::Builder.with(n_xml.root) do |b_xml|
|
@@ -74,29 +74,39 @@ module JenkinsPipelineBuilder
|
|
74
74
|
end
|
75
75
|
logger.info "Loading file #{path}"
|
76
76
|
hash.each do |section|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
77
|
+
load_section section, remote
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def load_section(section, remote)
|
82
|
+
Utils.symbolize_keys_deep!(section)
|
83
|
+
key = section.keys.first
|
84
|
+
value = section[key]
|
85
|
+
if key == :dependencies
|
86
|
+
logger.info 'Resolving Dependencies for remote project'
|
87
|
+
remote_dependencies.load value
|
88
|
+
return
|
89
|
+
end
|
90
|
+
name = value[:name]
|
91
|
+
process_collection! name, key, value, remote
|
92
|
+
end
|
93
|
+
|
94
|
+
# TODO: This should be cleaned up a bit. I'm sure we can get rid of
|
95
|
+
# the elsif and we should be more clear on the order of loading of things
|
96
|
+
def process_collection!(name, key, value, remote)
|
97
|
+
if collection.key?(name)
|
98
|
+
existing_remote = collection[name.to_s][:remote]
|
99
|
+
# skip if the existing item is local and the new item is remote
|
100
|
+
if remote && !existing_remote
|
101
|
+
return
|
91
102
|
# override if the existing item is remote and the new is local
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
end
|
103
|
+
elsif existing_remote && !remote
|
104
|
+
logger.info "Duplicate item with name '#{name}' was detected from the remote folder."
|
105
|
+
else
|
106
|
+
fail "Duplicate item with name '#{name}' was detected."
|
97
107
|
end
|
98
|
-
collection[name.to_s] = { name: name.to_s, type: key, value: value, remote: remote }
|
99
108
|
end
|
109
|
+
collection[name.to_s] = { name: name.to_s, type: key, value: value, remote: remote }
|
100
110
|
end
|
101
111
|
|
102
112
|
def load_extensions(path)
|
@@ -105,7 +115,7 @@ module JenkinsPipelineBuilder
|
|
105
115
|
return unless File.directory?(path)
|
106
116
|
logger.info "Loading extensions from folder #{path}"
|
107
117
|
logger.info Dir.glob("#{path}/*.rb").inspect
|
108
|
-
Dir.glob("#{path}
|
118
|
+
Dir.glob("#{path}/**/*.rb").each do |file|
|
109
119
|
logger.info "Loaded #{file}"
|
110
120
|
require file
|
111
121
|
end
|
@@ -33,8 +33,12 @@ module JenkinsPipelineBuilder
|
|
33
33
|
@versions ||= JenkinsPipelineBuilder.client.plugin.list_installed
|
34
34
|
end
|
35
35
|
|
36
|
-
def clear_versions
|
36
|
+
def clear_versions(sets = registry.values)
|
37
37
|
@versions = nil
|
38
|
+
sets.each do |entry|
|
39
|
+
entry.clear_installed_version if entry.is_a? ExtensionSet
|
40
|
+
clear_versions entry.values if entry.respond_to? :values
|
41
|
+
end
|
38
42
|
end
|
39
43
|
|
40
44
|
def logger
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module JenkinsPipelineBuilder
|
2
|
+
class Project
|
3
|
+
attr_reader :input
|
4
|
+
attr_accessor :errors
|
5
|
+
def initialize(name, input)
|
6
|
+
@name = name
|
7
|
+
@input = input
|
8
|
+
@errors = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def publish
|
12
|
+
success, payload = resolve_project(input)
|
13
|
+
if success
|
14
|
+
logger.info 'successfully resolved project'
|
15
|
+
compiled_project = payload
|
16
|
+
else
|
17
|
+
return { project_name: 'Failed to resolve' }
|
18
|
+
end
|
19
|
+
|
20
|
+
self.errors = publish_jobs(compiled_project[:value][:jobs]) if compiled_project[:value][:jobs]
|
21
|
+
return unless compiled_project[:value][:views]
|
22
|
+
compiled_project[:value][:views].each do |v|
|
23
|
+
compiled_view = v[:result]
|
24
|
+
view.create(compiled_view)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -29,17 +29,13 @@ module JenkinsPipelineBuilder
|
|
29
29
|
def initialize(project, generator)
|
30
30
|
@project = project
|
31
31
|
@generator = generator
|
32
|
-
|
33
32
|
@purge = []
|
34
33
|
@create = []
|
35
|
-
|
36
34
|
@errors = {}
|
35
|
+
|
37
36
|
@pull_generator = find
|
38
|
-
|
39
|
-
unless
|
40
|
-
@errors[@pull_generator[:name]] = payload
|
41
|
-
return false
|
42
|
-
end
|
37
|
+
payload = compile_generator
|
38
|
+
return unless payload
|
43
39
|
@jobs = filter_jobs
|
44
40
|
|
45
41
|
# old init
|
@@ -113,7 +109,11 @@ module JenkinsPipelineBuilder
|
|
113
109
|
settings = defaults.nil? ? {} : defaults[:value] || {}
|
114
110
|
compiler = Compiler.new generator
|
115
111
|
settings = compiler.get_settings_bag(project, settings)
|
116
|
-
generator.resolve_job_by_name(pull_generator[:name], settings)
|
112
|
+
success, payload = generator.resolve_job_by_name(pull_generator[:name], settings)
|
113
|
+
return payload if success
|
114
|
+
|
115
|
+
@errors[@pull_generator[:name]] = payload
|
116
|
+
false
|
117
117
|
end
|
118
118
|
|
119
119
|
def find
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe 'extension dsl' do
|
4
|
+
before :all do
|
5
|
+
JenkinsPipelineBuilder.credentials = {
|
6
|
+
server_ip: '127.0.0.1',
|
7
|
+
server_port: 8080,
|
8
|
+
username: 'username',
|
9
|
+
password: 'password',
|
10
|
+
log_location: '/dev/null'
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
after :each do
|
15
|
+
JenkinsPipelineBuilder.registry.clear_versions
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'overrides included extensions with local ones' do
|
19
|
+
builder do
|
20
|
+
name :shell_command
|
21
|
+
plugin_id 'builtin'
|
22
|
+
description 'Lets you run shell commands as a build step.'
|
23
|
+
jenkins_name 'Execute shell'
|
24
|
+
announced false
|
25
|
+
|
26
|
+
xml do |param|
|
27
|
+
newShell do
|
28
|
+
command param
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
allow(JenkinsPipelineBuilder.client).to receive(:plugin).and_return double(
|
34
|
+
list_installed: { 'parameterized-trigger' => '20.0' })
|
35
|
+
|
36
|
+
@n_xml = Nokogiri::XML::Builder.new { |xml| xml.builders }.doc
|
37
|
+
params = { builders: { shell_command: 'asdf' } }
|
38
|
+
JenkinsPipelineBuilder.registry.traverse_registry_path('job', params, @n_xml)
|
39
|
+
|
40
|
+
builder = @n_xml.root.children.first
|
41
|
+
expect(builder.name).to match 'newShell'
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe JenkinsPipelineBuilder::ExtensionSet do
|
4
|
+
subject(:set) { JenkinsPipelineBuilder::ExtensionSet.new('foo') {} }
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
set.name 'example'
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'xml' do
|
11
|
+
it 'returns the block for the correct version'
|
12
|
+
it 'sets the min_version if a parameter is provided' do
|
13
|
+
set.xml version: '0.2' do
|
14
|
+
true
|
15
|
+
end
|
16
|
+
expect(set.blocks).to have_key '0.2'
|
17
|
+
end
|
18
|
+
it 'uses the path if provided' do
|
19
|
+
set.xml path: 'foo' do
|
20
|
+
true
|
21
|
+
end
|
22
|
+
expect(set.blocks['0'][:path]).to eq 'foo'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context '#installed_version' do
|
27
|
+
it 'parses three digits' do
|
28
|
+
set.installed_version = '0.1.2'
|
29
|
+
expect(set.installed_version.version).to eq '0.1.2'
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'parses only two digits' do
|
33
|
+
set.installed_version = '0.1'
|
34
|
+
expect(set.installed_version.version).to eq '0.1'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context '#extension' do
|
39
|
+
def new_ext(version = '0.0')
|
40
|
+
ext = JenkinsPipelineBuilder::Extension.new
|
41
|
+
ext.name 'foo'
|
42
|
+
ext.plugin_id 'foo'
|
43
|
+
ext.min_version version
|
44
|
+
ext.xml -> { true }
|
45
|
+
ext.type 'foo'
|
46
|
+
ext.path 'foo'
|
47
|
+
ext
|
48
|
+
end
|
49
|
+
|
50
|
+
def ext_versions(versions)
|
51
|
+
versions.each do |v|
|
52
|
+
ext = new_ext(v)
|
53
|
+
expect(ext).to be_valid
|
54
|
+
set.extensions << ext
|
55
|
+
end
|
56
|
+
|
57
|
+
expect(set).to be_valid
|
58
|
+
expect(set.extensions.size).to eq versions.size
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'returns an extension' do
|
62
|
+
ext_versions ['0.0']
|
63
|
+
set.installed_version = '0.1'
|
64
|
+
expect(set.extension).to be_kind_of JenkinsPipelineBuilder::Extension
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'returns the highest that is lower than the installed version' do
|
68
|
+
ext_versions ['0.0', '0.2']
|
69
|
+
|
70
|
+
set.installed_version = '0.1'
|
71
|
+
|
72
|
+
expect(set.extension.min_version).to eq '0.0'
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'returns highest available if the installed version is higher' do
|
76
|
+
ext_versions ['0.0', '0.2']
|
77
|
+
|
78
|
+
set.installed_version = '0.3'
|
79
|
+
|
80
|
+
expect(set.extension.min_version).to eq '0.2'
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'works for complicated version comparions' do
|
84
|
+
ext_versions ['10.5', '9.2', '100.4']
|
85
|
+
|
86
|
+
set.installed_version = '11.3'
|
87
|
+
|
88
|
+
expect(set.extension.min_version).to eq '10.5'
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'raises an error if the registered versions are too high' do
|
92
|
+
ext_versions ['10.5', '9.2']
|
93
|
+
|
94
|
+
set.installed_version = '1.3'
|
95
|
+
|
96
|
+
expect { set.extension.min_version }.to raise_error
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'works for snapshot/beta stuff' do
|
100
|
+
ext_versions ['1.9', '2.3']
|
101
|
+
|
102
|
+
set.installed_version = '2.0-SNAPSHOT (private-06/06/2014 09:51-bgaulin)'
|
103
|
+
# Other examples
|
104
|
+
# set.installed_version = '2.0-beta-1'
|
105
|
+
# set.installed_version = '2.0+build.93'
|
106
|
+
# set.installed_version = '2.0.8'
|
107
|
+
expect(set.extension.min_version).to eq '1.9'
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|