jenkins_pipeline_builder 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/Rakefile +68 -0
- data/bin/generate +28 -0
- data/config/login.yml +24 -0
- data/jenkins_pipeline_builder.gemspec +42 -0
- data/lib/jenksin_pipeline_builder.rb +39 -0
- data/lib/jenksin_pipeline_builder/builders.rb +72 -0
- data/lib/jenksin_pipeline_builder/cli/base.rb +69 -0
- data/lib/jenksin_pipeline_builder/cli/helper.rb +68 -0
- data/lib/jenksin_pipeline_builder/cli/pipeline.rb +40 -0
- data/lib/jenksin_pipeline_builder/cli/view.rb +40 -0
- data/lib/jenksin_pipeline_builder/compiler.rb +81 -0
- data/lib/jenksin_pipeline_builder/generator.rb +346 -0
- data/lib/jenksin_pipeline_builder/job_builder.rb +82 -0
- data/lib/jenksin_pipeline_builder/module_registry.rb +82 -0
- data/lib/jenksin_pipeline_builder/publishers.rb +113 -0
- data/lib/jenksin_pipeline_builder/triggers.rb +38 -0
- data/lib/jenksin_pipeline_builder/utils.rb +46 -0
- data/lib/jenksin_pipeline_builder/version.rb +25 -0
- data/lib/jenksin_pipeline_builder/view.rb +259 -0
- data/lib/jenksin_pipeline_builder/wrappers.rb +91 -0
- data/lib/jenksin_pipeline_builder/xml_helper.rb +40 -0
- data/spec/func_tests/spec_helper.rb +18 -0
- data/spec/func_tests/view_spec.rb +93 -0
- data/spec/unit_tests/compiler_spec.rb +19 -0
- data/spec/unit_tests/fixtures/files/Job-Build-Flow.xml +57 -0
- data/spec/unit_tests/fixtures/files/Job-Build-Flow.yaml +22 -0
- data/spec/unit_tests/fixtures/files/Job-Build-Maven.xml +90 -0
- data/spec/unit_tests/fixtures/files/Job-Build-Maven.yaml +26 -0
- data/spec/unit_tests/fixtures/files/Job-DSL.yaml +14 -0
- data/spec/unit_tests/fixtures/files/Job-DSL1.xml +27 -0
- data/spec/unit_tests/fixtures/files/Job-DSL2.xml +25 -0
- data/spec/unit_tests/fixtures/files/Job-Gem-Build.xml +142 -0
- data/spec/unit_tests/fixtures/files/Job-Gem-Build.yaml +41 -0
- data/spec/unit_tests/fixtures/files/Job-Generate-From-Template.xml +32 -0
- data/spec/unit_tests/fixtures/files/Job-Generate-From-Template.yaml +8 -0
- data/spec/unit_tests/fixtures/files/Job-Multi-Project.xml +117 -0
- data/spec/unit_tests/fixtures/files/Job-Multi-Project.yaml +36 -0
- data/spec/unit_tests/fixtures/files/project.yaml +15 -0
- data/spec/unit_tests/generator_spec.rb +67 -0
- data/spec/unit_tests/module_registry_spec.rb +19 -0
- data/spec/unit_tests/resolve_dependencies_spec.rb +230 -0
- data/spec/unit_tests/spec_helper.rb +29 -0
- metadata +75 -6
@@ -0,0 +1,82 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Igor Moochnick
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
|
23
|
+
module JenkinsPipelineBuilder
|
24
|
+
class JobBuilder
|
25
|
+
def self.change_description(description, n_xml)
|
26
|
+
desc = n_xml.xpath("//description").first
|
27
|
+
desc.content = "#{description}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.apply_scm_params(params, n_xml)
|
31
|
+
XmlHelper.update_node_text(n_xml, '//scm/localBranch', params[:local_branch]) if params[:local_branch]
|
32
|
+
XmlHelper.update_node_text(n_xml, '//scm/recursiveSubmodules', params[:recursive_update]) if params[:recursive_update]
|
33
|
+
XmlHelper.update_node_text(n_xml, '//scm/wipeOutWorkspace', params[:wipe_workspace]) if params[:wipe_workspace]
|
34
|
+
XmlHelper.update_node_text(n_xml, '//scm/excludedUsers', params[:excuded_users]) if params[:excuded_users]
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.hipchat_notifier(params, n_xml)
|
38
|
+
raise "No HipChat room specified" unless params[:room]
|
39
|
+
|
40
|
+
properties = n_xml.xpath("//properties").first
|
41
|
+
Nokogiri::XML::Builder.with(properties) do |xml|
|
42
|
+
xml.send('jenkins.plugins.hipchat.HipChatNotifier_-HipChatJobProperty') {
|
43
|
+
xml.room params[:room]
|
44
|
+
xml.startNotification params[:'start-notify'] || false
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.build_parameters(params, n_xml)
|
50
|
+
n_builders = n_xml.xpath('//properties').first
|
51
|
+
Nokogiri::XML::Builder.with(n_builders) do |xml|
|
52
|
+
xml.send('hudson.model.ParametersDefinitionProperty') {
|
53
|
+
xml.parameterDefinitions {
|
54
|
+
param_proc = lambda do |xml, name, type, default, description|
|
55
|
+
xml.send(type) {
|
56
|
+
xml.name name
|
57
|
+
xml.description description
|
58
|
+
xml.defaultValue default
|
59
|
+
}
|
60
|
+
end
|
61
|
+
params.each do |param|
|
62
|
+
case param[:type]
|
63
|
+
when 'string'
|
64
|
+
paramType = 'hudson.model.StringParameterDefinition'
|
65
|
+
when 'bool'
|
66
|
+
paramType = 'hudson.model.BooleanParameterDefinition'
|
67
|
+
when 'text'
|
68
|
+
paramType = 'hudson.model.TextParameterDefinition'
|
69
|
+
when 'password'
|
70
|
+
paramType = 'hudson.model.PasswordParameterDefinition'
|
71
|
+
else
|
72
|
+
paramType = 'hudson.model.StringParameterDefinition'
|
73
|
+
end
|
74
|
+
|
75
|
+
param_proc.call xml, param[:name], paramType, param[:default], param[:description]
|
76
|
+
end
|
77
|
+
}
|
78
|
+
}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Igor Moochnick
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
|
23
|
+
module JenkinsPipelineBuilder
|
24
|
+
class ModuleRegistry
|
25
|
+
attr_accessor :registry
|
26
|
+
|
27
|
+
def initialize(registry)
|
28
|
+
@registry = registry
|
29
|
+
end
|
30
|
+
|
31
|
+
def get(path)
|
32
|
+
parts = path.split('/')
|
33
|
+
self.get_by_path_collection(parts, @registry)
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_by_path_collection(path, registry)
|
37
|
+
item = registry[path.shift.to_sym]
|
38
|
+
if path.count == 0
|
39
|
+
return item
|
40
|
+
end
|
41
|
+
|
42
|
+
get_by_path_collection(path, item)
|
43
|
+
end
|
44
|
+
|
45
|
+
def traverse_registry_path(path, params, n_xml)
|
46
|
+
registry = get(path)
|
47
|
+
traverse_registry(registry, params, n_xml)
|
48
|
+
end
|
49
|
+
|
50
|
+
def traverse_registry(registry, params, n_xml)
|
51
|
+
params.each do |key, value|
|
52
|
+
execute_registry_item(registry, key, value, n_xml)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def traverse_registry_param_array(registry, params, n_xml)
|
57
|
+
params.each do |item|
|
58
|
+
key = item.keys.first
|
59
|
+
next if key.nil?
|
60
|
+
execute_registry_item(registry, key, item[key], n_xml)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def execute_registry_item(registry, key, value, n_xml)
|
65
|
+
registry_item = registry[key]
|
66
|
+
if registry_item.kind_of?(Hash)
|
67
|
+
sub_registry = registry_item[:registry]
|
68
|
+
method = registry_item[:method]
|
69
|
+
method.call(sub_registry, value, n_xml)
|
70
|
+
elsif registry_item.kind_of?(Method)
|
71
|
+
registry_item.call(value, n_xml) unless registry_item.nil?
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def run_registry_on_path(path, registry, params, n_xml)
|
76
|
+
n_builders = n_xml.xpath(path).first
|
77
|
+
Nokogiri::XML::Builder.with(n_builders) do |xml|
|
78
|
+
traverse_registry_param_array(registry, params, xml)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Igor Moochnick
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
|
23
|
+
module JenkinsPipelineBuilder
|
24
|
+
class Publishers
|
25
|
+
def self.description_setter(params, xml)
|
26
|
+
xml.send('hudson.plugins.descriptionsetter.DescriptionSetterPublisher') {
|
27
|
+
xml.regexp params[:regexp]
|
28
|
+
xml.regexpForFailed params[:regexp]
|
29
|
+
xml.description params[:description]
|
30
|
+
xml.descriptionForFailed params[:description]
|
31
|
+
xml.setForMatrix false
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.push_to_projects(params, xml)
|
36
|
+
xml.send('hudson.plugins.parameterizedtrigger.BuildTrigger') {
|
37
|
+
xml.configs {
|
38
|
+
xml.send('hudson.plugins.parameterizedtrigger.BuildTriggerConfig') {
|
39
|
+
xml.configs {
|
40
|
+
params[:data] = [ { params: "" } ] unless params[:data]
|
41
|
+
params[:data].each do |config|
|
42
|
+
if config[:params]
|
43
|
+
xml.send('hudson.plugins.parameterizedtrigger.PredefinedBuildParameters') {
|
44
|
+
xml.properties config[:params]
|
45
|
+
}
|
46
|
+
end
|
47
|
+
if config[:file]
|
48
|
+
xml.send('hudson.plugins.parameterizedtrigger.FileBuildParameters') {
|
49
|
+
xml.propertiesFile config[:file]
|
50
|
+
xml.failTriggerOnMissing false
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
}
|
55
|
+
xml.projects params[:project]
|
56
|
+
xml.condition 'SUCCESS'
|
57
|
+
xml.triggerWithNoParameters false
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.push_to_hipchat(params, xml)
|
64
|
+
params = {} if params == true
|
65
|
+
xml.send('jenkins.plugins.hipchat.HipChatNotifier') {
|
66
|
+
xml.jenkinsUrl params[:jenkinsUrl] || ''
|
67
|
+
xml.authToken params[:authToken] || ''
|
68
|
+
xml.room params[:room] || ''
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.push_to_git(params, xml)
|
73
|
+
xml.send('hudson.plugins.git.GitPublisher') {
|
74
|
+
xml.configVersion params[:configVersion] || 2
|
75
|
+
xml.pushMerge params[:'push-merge'] || false
|
76
|
+
xml.pushOnlyIfSuccess params[:'push-only-if-success'] || false
|
77
|
+
xml.branchesToPush {
|
78
|
+
xml.send('hudson.plugins.git.GitPublisher_-BranchToPush') {
|
79
|
+
xml.targetRepoName params[:targetRepoName] || 'origin'
|
80
|
+
xml.branchName params[:branchName] || 'master'
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.publish_junit(params, xml)
|
87
|
+
xml.send('hudson.tasks.junit.JUnitResultArchiver') {
|
88
|
+
xml.testResults params[:test_results] || ''
|
89
|
+
xml.keepLongStdio false
|
90
|
+
xml.testDataPublishers
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.coverage_metric(name, params, xml)
|
95
|
+
xml.send('hudson.plugins.rubyMetrics.rcov.model.MetricTarget') {
|
96
|
+
xml.metric name
|
97
|
+
xml.healthy params[:healthy]
|
98
|
+
xml.unhealthy params[:unhealthy]
|
99
|
+
xml.unstable params[:unstable]
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.publish_rcov(params, xml)
|
104
|
+
xml.send('hudson.plugins.rubyMetrics.rcov.RcovPublisher') {
|
105
|
+
xml.reportDir params[:report_dir]
|
106
|
+
xml.targets {
|
107
|
+
coverage_metric('TOTAL_COVERAGE', params[:total], xml)
|
108
|
+
coverage_metric('CODE_COVERAGE', params[:code], xml)
|
109
|
+
}
|
110
|
+
}
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Igor Moochnick
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
|
23
|
+
module JenkinsPipelineBuilder
|
24
|
+
class Triggers
|
25
|
+
def self.enable_git_push(git_push, xml)
|
26
|
+
xml.send('com.cloudbees.jenkins.GitHubPushTrigger') {
|
27
|
+
xml.spec
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.enable_scm_polling(scm_polling, xml)
|
32
|
+
xml.send('hudson.triggers.SCMTrigger') {
|
33
|
+
xml.spec scm_polling
|
34
|
+
xml.ignorePostCommitHooks false
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Igor Moochnick
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
|
23
|
+
module JenkinsPipelineBuilder
|
24
|
+
class ::Hash
|
25
|
+
def deep_merge(second)
|
26
|
+
merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
|
27
|
+
self.merge(second, &merger)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Utils
|
32
|
+
# Code was duplicated from jeknins_api_client
|
33
|
+
def self.symbolize_keys_deep!(h)
|
34
|
+
return unless h.kind_of?(Hash)
|
35
|
+
h.keys.each do |k|
|
36
|
+
ks = k.respond_to?(:to_sym) ? k.to_sym : k
|
37
|
+
h[ks] = h.delete k # Preserve order even when k == ks
|
38
|
+
symbolize_keys_deep! h[ks] if h[ks].kind_of? Hash
|
39
|
+
if h[ks].kind_of? Array
|
40
|
+
#puts "Array #{h[ks]}"
|
41
|
+
h[ks].each { |item| symbolize_keys_deep!(item) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Igor Moochnick
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
|
23
|
+
module JenkinsPipelineBuilder
|
24
|
+
VERSION = "0.1.3"
|
25
|
+
end
|
@@ -0,0 +1,259 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Igor Moochnick
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
|
23
|
+
module JenkinsPipelineBuilder
|
24
|
+
class View
|
25
|
+
# Initializes a new View object.
|
26
|
+
#
|
27
|
+
# @param generator [Generator] the client object
|
28
|
+
#
|
29
|
+
# @return [View] the view object
|
30
|
+
#
|
31
|
+
def initialize(generator)
|
32
|
+
@generator = generator
|
33
|
+
@client = generator.client
|
34
|
+
@logger = @client.logger
|
35
|
+
end
|
36
|
+
|
37
|
+
def generate(path)
|
38
|
+
yaml = YAML.load_file(path)
|
39
|
+
|
40
|
+
yaml.each do |item|
|
41
|
+
Utils.symbolize_keys_deep!(item)
|
42
|
+
create(item[:view]) if item[:view]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_mode(type)
|
47
|
+
case type
|
48
|
+
when 'listview'
|
49
|
+
'hudson.model.ListView'
|
50
|
+
when 'myview'
|
51
|
+
'hudson.model.MyView'
|
52
|
+
when 'nestedView'
|
53
|
+
'hudson.plugins.nested_view.NestedView'
|
54
|
+
when 'categorizedView'
|
55
|
+
'org.jenkinsci.plugins.categorizedview.CategorizedJobsView'
|
56
|
+
when 'dashboardView'
|
57
|
+
'hudson.plugins.view.dashboard.Dashboard'
|
58
|
+
when 'multijobView'
|
59
|
+
'com.tikal.jenkins.plugins.multijob.views.MultiJobView'
|
60
|
+
else
|
61
|
+
raise "Type #{type} is not supported by Jenkins."
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Creates a new empty view of the given type
|
66
|
+
#
|
67
|
+
# @param [String] view_name Name of the view to be created
|
68
|
+
# @param [String] type Type of view to be created. Valid options:
|
69
|
+
# listview, myview. Default: listview
|
70
|
+
#
|
71
|
+
def create_base_view(view_name, type = 'listview', parent_view_name = nil)
|
72
|
+
@logger.info "Creating a view '#{view_name}' of type '#{type}'"
|
73
|
+
mode = get_mode(type)
|
74
|
+
initial_post_params = {
|
75
|
+
'name' => view_name,
|
76
|
+
'mode' => mode,
|
77
|
+
'json' => {
|
78
|
+
'name' => view_name,
|
79
|
+
'mode' => mode
|
80
|
+
}.to_json
|
81
|
+
}
|
82
|
+
|
83
|
+
if @generator.debug
|
84
|
+
pp initial_post_params
|
85
|
+
return
|
86
|
+
end
|
87
|
+
|
88
|
+
view_path = parent_view_name.nil? ? '' : "/view/#{path_encode parent_view_name}"
|
89
|
+
view_path += '/createView'
|
90
|
+
|
91
|
+
@client.api_post_request(view_path, initial_post_params)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Creates a listview by accepting the given parameters hash
|
95
|
+
#
|
96
|
+
# @param [Hash] params options to create the new view
|
97
|
+
# @option params [String] :name Name of the view
|
98
|
+
# @option params [String] :type Description of the view
|
99
|
+
# @option params [String] :description Description of the view
|
100
|
+
# @option params [String] :status_filter Filter jobs based on the status.
|
101
|
+
# Valid options: all_selected_jobs, enabled_jobs_only,
|
102
|
+
# disabled_jobs_only. Default: all_selected_jobs
|
103
|
+
# @option params [Boolean] :filter_queue true or false
|
104
|
+
# @option params [Boolean] :filter_executors true or false
|
105
|
+
# @option params [String] :regex Regular expression to filter jobs that
|
106
|
+
# are to be added to the view
|
107
|
+
#
|
108
|
+
# @raise [ArgumentError] if the required parameter +:name+ is not
|
109
|
+
# specified
|
110
|
+
#
|
111
|
+
def create(params)
|
112
|
+
# Name is a required parameter. Raise an error if not specified
|
113
|
+
raise ArgumentError, "Name is required for creating view" \
|
114
|
+
unless params.is_a?(Hash) && params[:name]
|
115
|
+
unless @generator.debug
|
116
|
+
if @client.view.exists?(params[:name])
|
117
|
+
@client.view.delete(params[:name])
|
118
|
+
end
|
119
|
+
end
|
120
|
+
params[:type] = 'listview' unless params[:type]
|
121
|
+
create_base_view(params[:name], params[:type], params[:parent_view])
|
122
|
+
@logger.debug "Creating a #{params[:type]} view with params: #{params.inspect}"
|
123
|
+
status_filter = case params[:status_filter]
|
124
|
+
when "all_selected_jobs"
|
125
|
+
""
|
126
|
+
when "enabled_jobs_only"
|
127
|
+
"1"
|
128
|
+
when "disabled_jobs_only"
|
129
|
+
"2"
|
130
|
+
else
|
131
|
+
""
|
132
|
+
end
|
133
|
+
|
134
|
+
json = {
|
135
|
+
"name" => params[:name],
|
136
|
+
"description" => params[:description],
|
137
|
+
"mode" => get_mode(params[:type]),
|
138
|
+
"statusFilter" => "",
|
139
|
+
"columns" => get_columns(params[:type])
|
140
|
+
}
|
141
|
+
json.merge!("groupingRules" => params[:groupingRules]) if params[:groupingRules]
|
142
|
+
post_params = {
|
143
|
+
"name" => params[:name],
|
144
|
+
"mode" => get_mode(params[:type]),
|
145
|
+
"description" => params[:description],
|
146
|
+
"statusFilter" => status_filter,
|
147
|
+
"json" => json.to_json
|
148
|
+
}
|
149
|
+
post_params.merge!("filterQueue" => "on") if params[:filter_queue]
|
150
|
+
post_params.merge!("filterExecutors" => "on") if params[:filter_executors]
|
151
|
+
post_params.merge!("useincluderegex" => "on",
|
152
|
+
"includeRegex" => params[:regex]) if params[:regex]
|
153
|
+
|
154
|
+
if @generator.debug
|
155
|
+
pp post_params
|
156
|
+
return
|
157
|
+
end
|
158
|
+
|
159
|
+
view_path = params[:parent_view].nil? ? '' : "/view/#{path_encode params[:parent_view]}"
|
160
|
+
view_path += "/view/#{path_encode params[:name]}/configSubmit"
|
161
|
+
|
162
|
+
@client.api_post_request(view_path, post_params)
|
163
|
+
end
|
164
|
+
|
165
|
+
def get_columns(type)
|
166
|
+
columns_repository = {
|
167
|
+
'Status' =>
|
168
|
+
{
|
169
|
+
'stapler-class' => 'hudson.views.StatusColumn',
|
170
|
+
'kind' => 'hudson.views.StatusColumn'
|
171
|
+
},
|
172
|
+
'Weather' =>
|
173
|
+
{
|
174
|
+
"stapler-class" => "hudson.views.WeatherColumn",
|
175
|
+
"kind" => "hudson.views.WeatherColumn"
|
176
|
+
},
|
177
|
+
'Name' =>
|
178
|
+
{
|
179
|
+
"stapler-class" => "hudson.views.JobColumn",
|
180
|
+
"kind" => "hudson.views.JobColumn"
|
181
|
+
},
|
182
|
+
'Last Success' =>
|
183
|
+
{
|
184
|
+
"stapler-class" => "hudson.views.LastSuccessColumn",
|
185
|
+
"kind" => "hudson.views.LastSuccessColumn"
|
186
|
+
},
|
187
|
+
'Last Failure' =>
|
188
|
+
{
|
189
|
+
"stapler-class" => "hudson.views.LastFailureColumn",
|
190
|
+
"kind" => "hudson.views.LastFailureColumn"
|
191
|
+
},
|
192
|
+
'Last Duration' =>
|
193
|
+
{
|
194
|
+
"stapler-class" => "hudson.views.LastDurationColumn",
|
195
|
+
"kind" => "hudson.views.LastDurationColumn"
|
196
|
+
},
|
197
|
+
'Build Button' =>
|
198
|
+
{
|
199
|
+
'stapler-class' => 'hudson.views.BuildButtonColumn',
|
200
|
+
'kind' => 'hudson.views.BuildButtonColumn'
|
201
|
+
},
|
202
|
+
'Categorized - Job' =>
|
203
|
+
{
|
204
|
+
'stapler-class' => 'org.jenkinsci.plugins.categorizedview.IndentedJobColumn',
|
205
|
+
'kind' => 'org.jenkinsci.plugins.categorizedview.IndentedJobColumn'
|
206
|
+
}
|
207
|
+
}
|
208
|
+
|
209
|
+
column_names = case type
|
210
|
+
when 'categorizedView'
|
211
|
+
['Status', 'Weather', 'Categorized - Job', 'Last Success', 'Last Failure', 'Last Duration', 'Build Button']
|
212
|
+
else
|
213
|
+
['Status', 'Weather', 'Name', 'Last Success', 'Last Failure', 'Last Duration', 'Build Button']
|
214
|
+
end
|
215
|
+
|
216
|
+
result = []
|
217
|
+
column_names.each do |name|
|
218
|
+
result << columns_repository[name]
|
219
|
+
end
|
220
|
+
return result
|
221
|
+
end
|
222
|
+
|
223
|
+
def path_encode(path)
|
224
|
+
URI.escape(path.encode(Encoding::UTF_8))
|
225
|
+
end
|
226
|
+
|
227
|
+
# This method lists all views
|
228
|
+
#
|
229
|
+
# @param [String] parent_view a name of the parent view
|
230
|
+
# @param [String] filter a regex to filter view names
|
231
|
+
# @param [Bool] ignorecase whether to be case sensitive or not
|
232
|
+
#
|
233
|
+
def list_children(parent_view = nil, filter = "", ignorecase = true)
|
234
|
+
@logger.info "Obtaining children views of parent #{parent_view} based on filter '#{filter}'"
|
235
|
+
view_names = []
|
236
|
+
path = parent_view.nil? ? '' : "/view/#{path_encode parent_view}"
|
237
|
+
response_json = @client.api_get_request(path)
|
238
|
+
response_json["views"].each { |view|
|
239
|
+
if ignorecase
|
240
|
+
view_names << view["name"] if view["name"] =~ /#{filter}/i
|
241
|
+
else
|
242
|
+
view_names << view["name"] if view["name"] =~ /#{filter}/
|
243
|
+
end
|
244
|
+
}
|
245
|
+
view_names
|
246
|
+
end
|
247
|
+
|
248
|
+
# Delete a view
|
249
|
+
#
|
250
|
+
# @param [String] view_name
|
251
|
+
#
|
252
|
+
def delete(view_name, parent_view = nil)
|
253
|
+
@logger.info "Deleting view '#{view_name}'"
|
254
|
+
path = parent_view.nil? ? '' : "/view/#{path_encode parent_view}"
|
255
|
+
path += "/view/#{path_encode view_name}/doDelete"
|
256
|
+
@client.api_post_request(path)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|