jenkins_pipeline_builder 0.1.2 → 0.1.3
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 +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
|