jenkins_pipeline_builder 0.6.0 → 0.7.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.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -11
  3. data/README.md +19 -29
  4. data/commit_build.sh +1 -4
  5. data/lib/jenkins_pipeline_builder.rb +9 -13
  6. data/lib/jenkins_pipeline_builder/cli/describe.rb +14 -5
  7. data/lib/jenkins_pipeline_builder/cli/helper.rb +2 -0
  8. data/lib/jenkins_pipeline_builder/cli/list.rb +11 -4
  9. data/lib/jenkins_pipeline_builder/extensions.rb +151 -40
  10. data/lib/jenkins_pipeline_builder/{builders.rb → extensions/builders.rb} +22 -15
  11. data/lib/jenkins_pipeline_builder/{job_builder.rb → extensions/job_attributes.rb} +37 -27
  12. data/lib/jenkins_pipeline_builder/{publishers.rb → extensions/publishers.rb} +55 -20
  13. data/lib/jenkins_pipeline_builder/{triggers.rb → extensions/triggers.rb} +18 -8
  14. data/lib/jenkins_pipeline_builder/{wrappers.rb → extensions/wrappers.rb} +23 -36
  15. data/lib/jenkins_pipeline_builder/generator.rb +29 -62
  16. data/lib/jenkins_pipeline_builder/module_registry.rb +21 -9
  17. data/lib/jenkins_pipeline_builder/pull_request.rb +1 -1
  18. data/lib/jenkins_pipeline_builder/version.rb +1 -1
  19. data/pipeline/Jenkins-Pipeline-Builder.yaml +3 -7
  20. data/pipeline/project.yaml +10 -0
  21. data/spec/lib/jenkins_pipeline_builder/compiler_spec.rb +9 -1
  22. data/spec/lib/jenkins_pipeline_builder/extensions/builders_spec.rb +53 -0
  23. data/spec/lib/jenkins_pipeline_builder/extensions/publishers_spec.rb +140 -0
  24. data/spec/lib/jenkins_pipeline_builder/extensions_spec.rb +113 -31
  25. data/spec/lib/jenkins_pipeline_builder/generator_spec.rb +12 -4
  26. data/spec/lib/jenkins_pipeline_builder/module_registry_spec.rb +202 -44
  27. data/spec/lib/jenkins_pipeline_builder/spec_helper.rb +5 -5
  28. data/spec/requests/pipeline_spec.rb +20 -0
  29. metadata +16 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7732d073bba8e738befc23bd6c71249ccbf23ff5
4
- data.tar.gz: 122b6fe751d205a6b108fab75ac549efa987444f
3
+ metadata.gz: 1b24c99f73cecb047e1f58cd328000f81ee3b31c
4
+ data.tar.gz: 43f6ce844efe1ed19940d3e8d0dfaab50b243d79
5
5
  SHA512:
6
- metadata.gz: 8a880f17364c6d7a44aefd11f6cadabb9b4aaf8107d539accc2c81ffd61c9cc33dafe277d2508e5d463c11b062ae88fc83708f7920aad5f360163fefd9631609
7
- data.tar.gz: b0e8b310565ba4327071029011a7a734d9383c04a1275a2587d753a70715cb5385355bbb7354233c71e93157b9eebcc9843ed078f37fd191c541b366a1ad2ee9
6
+ metadata.gz: 82bce578c0a059d5cbee047fcd984bbe765174ed58e96601c721b41eb806583e4301959822a6bbe1e729dbdce2636b99d30d9ae00ec877171b1b9b490ecd59c0
7
+ data.tar.gz: 60bc6c5d94f07227b5750813455267f80c05f2dc7a677bfb972829acd6f32d17e7673eb1b211a3ac849bc085b8d8f6d0682e023a4081e5b74bc2f8fd32848ef5
@@ -26,6 +26,7 @@ Style/LineLength:
26
26
  - 'spec/lib/jenkins_pipeline_builder/compiler_spec.rb'
27
27
  - 'spec/lib/jenkins_pipeline_builder/view_spec.rb'
28
28
  - 'spec/lib/jenkins_pipeline_builder/pull_request_spec.rb'
29
+ - 'lib/jenkins_pipeline_builder/extensions/*'
29
30
 
30
31
  # Configuration parameters: CountComments.
31
32
  Style/MethodLength:
@@ -37,18 +38,9 @@ Style/Documentation:
37
38
  # Configuration parameters: EnforcedStyle, SupportedStyles.
38
39
  Style/Next:
39
40
  Exclude:
40
- - 'lib/jenkins_pipeline_builder/publishers.rb'
41
- - 'lib/jenkins_pipeline_builder/triggers.rb'
42
- - 'lib/jenkins_pipeline_builder/wrappers.rb'
43
- - 'lib/jenkins_pipeline_builder/builders.rb'
44
- - 'lib/jenkins_pipeline_builder/job_builder.rb'
41
+ - 'lib/jenkins_pipeline_builder/extensions/*'
45
42
 
46
43
  # Configuration parameters: EnforcedStyle, SupportedStyles.
47
44
  Style/VariableName:
48
45
  Exclude:
49
- - 'lib/jenkins_pipeline_builder/publishers.rb'
50
- - 'lib/jenkins_pipeline_builder/triggers.rb'
51
- - 'lib/jenkins_pipeline_builder/wrappers.rb'
52
- - 'lib/jenkins_pipeline_builder/builders.rb'
53
- - 'lib/jenkins_pipeline_builder/job_builder.rb'
54
- #######
46
+ - 'lib/jenkins_pipeline_builder/extensions/*'
data/README.md CHANGED
@@ -15,7 +15,7 @@ amazing progress done by the Open Stack community with their [jenkins-job-builde
15
15
  The YAML structure very closely resembles the OpenStack Job Builder, but, in comparison to Python version, is 100%
16
16
  pure Ruby and uses Jenkins API Client and has additional functionlity of building different types of Jenkins views.
17
17
 
18
- # JenkinsPipeline::Generator
18
+ # JenkinsPipelineBuilder
19
19
 
20
20
  USAGE:
21
21
  ------
@@ -76,6 +76,8 @@ NOTE: you can run the pipeline in NOOP (debug-only) mode by addind -d parameter,
76
76
 
77
77
  generate pipeline -d -c config/login.yml bootstrap ./pipeline
78
78
 
79
+ The command comes with fairly extensive help. For example you can list all of the registered extension types with `generate list` and a list of all extensions of a type with `generate list type`
80
+
79
81
  DSL:
80
82
  ----
81
83
 
@@ -282,7 +284,7 @@ When running a project through this module, the project {{name}} is appended wit
282
284
  job_type: pull_request_generator
283
285
  git_url: 'https://www.github.com/'
284
286
  git_repo: 'jenkins_pipeline_builder'
285
- git_org: 'IgorShare'
287
+ git_org: 'constantcontact'
286
288
  jobs:
287
289
  - '{{name}}-Job1':
288
290
  publishers:
@@ -338,39 +340,27 @@ Extending the Pipeline Builder
338
340
 
339
341
  Have a feature you want to test out before adding it to the source? Now you can create a quick "extension" to the pipeline builder to add new or overwrite existing functionality.
340
342
 
341
- To add an extension, create an "extensions" directiroy inside of "pipeline" and create a file named "myExtension.rb" (or any name). Use `JenkinsPipelineBuilder.extend` to register your extension.
342
-
343
- When registering, you must use one of the following register methods, depending on what category your change falls into:
344
- * register_job_attribute
345
- * register_builder
346
- * register_publisher
347
- * register_wrapper
348
- * register_trigger
343
+ To add an extension, create an "extensions" directiroy inside of "pipeline" and create a file named "my_extension.rb" (or any name). Then just `require 'jenkins_pipeline_builder/extensions'` and you can begin using the extension DSL. All of the plugins use this DSL and provide an excellent source of examples. You can find them in lib/jenkins_pipeline_builder/extensions.
349
344
 
350
345
  For help figuring out what category your change is, examine the config.xml for a job that uses your feature. If it is a first child of the root "project" node, your change is a job_attribute. Otherwise it should be either a builder, publisher, wrapper, or trigger, depending what child node it is found in the XML tree.
351
346
 
352
347
  Here is an example of extending the pipeline builder with a new publisher:
353
348
 
354
349
  ```ruby
355
- JenkinsPipelineBuilder.extend do |registry|
356
- registry.register_publisher :yaml_name, "Jenkins UI Name", "Description of this feature" { |params, xml| apply_extension(params, xml) }
357
-
358
- def apply_extension(params, xml)
359
- xml.send("new_element") {
360
- xml.property params[:value]
361
- }
362
- end
363
- end
364
- ```
365
-
366
- OR
367
-
368
- ```ruby
369
- JenkinsPipelineBuilder.extend do |registry|
370
- registry.register_publisher :yaml_name, "Jenkins UI Name", "Description of this feature" do |params, xml|
371
- xml.send("new_element") {
372
- xml.property params[:value]
373
- }
350
+ publisher do
351
+ name :yaml_name
352
+ plugin_id 123
353
+ min_version '0.4'
354
+ jenkins_name "Jenkins UI Name"
355
+ description "Description of this feature"
356
+
357
+ xml do |params, xml|
358
+ send("new_element") do
359
+ property params[:value]
360
+ if params[:thing]
361
+ thing 'true'
362
+ end
363
+ end
374
364
  end
375
365
  end
376
366
  ```
@@ -1,7 +1,4 @@
1
1
  #!/bin/bash
2
2
  bundle --version || gem install bundler --no-ri --no-rdoc
3
3
  bundle install
4
- rm -f *.gem
5
- bundle exec rake spec || exit $?
6
- bundle exec gem build jenkins_pipeline_builder.gemspec || exit $?
7
- bundle exec gem bump
4
+ bundle exec rake spec || exit $?
@@ -40,32 +40,28 @@ module JenkinsPipelineBuilder
40
40
 
41
41
  def credentials=(creds)
42
42
  @credentials = creds
43
- @client =
44
- @_client = JenkinsApi::Client.new(credentials)
45
- generator.logger = @_client.logger
43
+ @client = JenkinsApi::Client.new(credentials)
44
+ generator.logger = @client.logger
46
45
  @credentials
47
46
  end
48
47
 
49
48
  def logger
50
- @_client.logger
49
+ client.logger
51
50
  end
52
51
 
53
52
  def registry
54
53
  generator.module_registry
55
54
  end
56
-
57
- def load_registry
58
- load 'jenkins_pipeline_builder/builders.rb'
59
- load 'jenkins_pipeline_builder/job_builder.rb'
60
- load 'jenkins_pipeline_builder/wrappers.rb'
61
- load 'jenkins_pipeline_builder/publishers.rb'
62
- load 'jenkins_pipeline_builder/triggers.rb'
63
- end
64
55
  end
65
56
  end
66
57
  JenkinsPipelineBuilder.generator
67
58
  require 'jenkins_pipeline_builder/extensions'
68
- JenkinsPipelineBuilder.load_registry
59
+ require 'jenkins_pipeline_builder/extensions/builders'
60
+ require 'jenkins_pipeline_builder/extensions/job_attributes'
61
+ require 'jenkins_pipeline_builder/extensions/wrappers'
62
+ require 'jenkins_pipeline_builder/extensions/publishers'
63
+ require 'jenkins_pipeline_builder/extensions/triggers'
64
+
69
65
  require 'jenkins_pipeline_builder/cli/helper'
70
66
  require 'jenkins_pipeline_builder/cli/view'
71
67
  require 'jenkins_pipeline_builder/cli/pipeline'
@@ -22,15 +22,22 @@
22
22
 
23
23
  module JenkinsPipelineBuilder
24
24
  module CLI
25
- JenkinsPipelineBuilder.registry.entries.keys.each do |entry|
25
+ entries = JenkinsPipelineBuilder.registry.entries.keys
26
+ entries << :job_attributes
27
+ entries.each do |entry|
26
28
  klass_name = entry.to_s.classify
27
29
  # rubocop:disable Style/AccessModifierIndentation
28
30
  klass = Class.new(Thor) do
29
31
 
30
- extensions = JenkinsPipelineBuilder.registry.registry[:job][entry]
31
- extensions.each do |key, exts|
32
+ if entry == :job_attributes
33
+ extensions = JenkinsPipelineBuilder.registry.registry[:job].select { |_, x| x.is_a? ExtensionSet }
34
+ else
35
+ extensions = JenkinsPipelineBuilder.registry.registry[:job][entry]
36
+ end
37
+
38
+ extensions.each do |key, extset|
32
39
  # TODO: don't just take the first
33
- ext = exts.first
40
+ ext = extset.extensions.first
34
41
  desc key, "Details for #{ext.name}"
35
42
  define_method(ext.name) do
36
43
  display_module(ext)
@@ -47,7 +54,9 @@ module JenkinsPipelineBuilder
47
54
  Module.const_set(klass_name, klass)
48
55
  end
49
56
  class Describe < Thor
50
- JenkinsPipelineBuilder.registry.entries.each do |entry, _path|
57
+ entries = JenkinsPipelineBuilder.registry.entries.keys
58
+ entries << :job_attributes
59
+ entries.each do |entry, _path|
51
60
  klass_name = entry.to_s.classify
52
61
  singular_model = entry.to_s.singularize
53
62
 
@@ -49,6 +49,8 @@ module JenkinsPipelineBuilder
49
49
  creds = YAML.load_file(
50
50
  File.expand_path("#{ENV['HOME']}/.jenkins_api_client/login.yml", __FILE__)
51
51
  )
52
+ elsif options[:debug]
53
+ creds = { username: :foo, password: :bar, server_ip: :baz }
52
54
  else
53
55
  msg = 'Credentials are not set. Please pass them as parameters or'
54
56
  msg << ' set them in the default credentials file'
@@ -26,15 +26,22 @@ module JenkinsPipelineBuilder
26
26
  JenkinsPipelineBuilder.registry.entries.keys.each do |entry|
27
27
  desc entry, "List all #{entry}"
28
28
  define_method(entry) do
29
- extensions = JenkinsPipelineBuilder.registry.registry[:job][entry]
30
- extensions.each { |name, ext| display_module(name, ext) }
29
+ entries = JenkinsPipelineBuilder.registry.registry[:job][entry]
30
+ entries.each do |name, set|
31
+ ext = set.extensions.first
32
+ display_module(name, ext)
33
+ end
31
34
  end
32
35
  end
33
36
 
34
37
  desc 'job_attributes', 'List all job attributes'
35
38
  def job_attributes
36
- extensions = JenkinsPipelineBuilder.registry.registry[:job]
37
- extensions.each { |name, ext| display_module(name, ext) }
39
+ entries = JenkinsPipelineBuilder.registry.registry[:job]
40
+ entries.each do |name, set|
41
+ next unless set.is_a? ExtensionSet
42
+ ext = set.extensions.first
43
+ display_module(name, ext)
44
+ end
38
45
  end
39
46
 
40
47
  private
@@ -23,74 +23,185 @@ require 'jenkins_pipeline_builder'
23
23
  JenkinsPipelineBuilder.registry.entries.each do |type, path|
24
24
  singular_type = type.to_s.singularize
25
25
  define_method singular_type do |&block|
26
- ext = JenkinsPipelineBuilder::Extension.new
27
- ext.instance_eval(&block)
28
- ext.path path
29
- ext.type singular_type
30
- unless ext.valid?
31
- name = ext.name || 'A plugin with no name provided'
26
+ set = JenkinsPipelineBuilder::ExtensionSet.new
27
+ set.instance_eval(&block)
28
+ set.blocks.each do |version, settings|
29
+ ext = JenkinsPipelineBuilder::Extension.new
30
+ ext.min_version version
31
+ ext.type singular_type
32
+ set.settings.merge(settings).each do |key, value|
33
+ ext.send key, value
34
+ end
35
+ ext.path path unless ext.path
36
+ set.extensions << ext
37
+ end
38
+ unless set.valid?
39
+ name = set.name || 'A plugin with no name provided'
32
40
  puts "Encountered errors while registering #{name}"
33
- puts ext.errors.map { |k, v| "#{k}: #{v}" }.join(', ')
41
+ puts set.errors.map { |k, v| "#{k}: #{v}" }.join(', ')
34
42
  return false
35
43
  end
36
- JenkinsPipelineBuilder.registry.register([:job, type], ext)
37
- puts "Successfully registered #{ext.name} for versions #{ext.min_version} and higher" if ext.announced
44
+ JenkinsPipelineBuilder.registry.register([:job, type], set)
45
+ versions = set.extensions.map { |ext| ext.min_version }
46
+ puts "Successfully registered #{set.name} for versions #{versions}" if set.announced
38
47
  end
39
48
  end
40
49
 
41
50
  def job_attribute(&block)
42
- ext = JenkinsPipelineBuilder::Extension.new
43
- ext.instance_eval(&block)
44
- ext.type :job_attribute
45
- unless ext.valid?
46
- name = ext.name || 'A plugin with no name provided'
51
+ set = JenkinsPipelineBuilder::ExtensionSet.new
52
+ set.instance_eval(&block)
53
+ set.blocks.each do |version, settings|
54
+ ext = JenkinsPipelineBuilder::Extension.new
55
+ ext.min_version version
56
+ ext.type :job_attribute
57
+ set.settings.merge(settings).each do |key, value|
58
+ ext.send key, value
59
+ end
60
+ set.extensions << ext
61
+ end
62
+ unless set.valid?
63
+ name = set.name || 'A plugin with no name provided'
47
64
  puts "Encountered errors while registering #{name}"
48
- puts ext.errors.map { |k, v| "#{k}: #{v}" }.join(', ')
65
+ puts set.errors.map { |k, v| "#{k}: #{v}" }.join(', ')
49
66
  return false
50
67
  end
51
- JenkinsPipelineBuilder.registry.register([:job], ext)
52
- puts "Successfully registered #{ext.name} for versions #{ext.min_version} and higher" if ext.announced
68
+ JenkinsPipelineBuilder.registry.register([:job], set)
69
+ puts "Successfully registered #{set.name} for versions #{set.min_version} and higher" if set.announced
70
+ end
71
+
72
+ module JenkinsPipelineBuilder
73
+ class ExtensionSet
74
+ SET_METHODS = [
75
+ :name,
76
+ :plugin_id,
77
+ :jenkins_name,
78
+ :description,
79
+ :announced,
80
+ :type
81
+ ]
82
+ SET_METHODS.each do |method_name|
83
+ define_method method_name do |value = nil|
84
+ return settings[method_name] if value.nil?
85
+ settings[method_name] = value
86
+ end
87
+ end
88
+
89
+ attr_accessor :blocks, :extensions, :settings
90
+
91
+ def initialize
92
+ @blocks = {}
93
+ @settings = {}
94
+ @extensions = []
95
+ end
96
+
97
+ def installed_version=(version)
98
+ version = version.match(/\d+\.\d+/)
99
+ @version = Gem::Version.new version
100
+ end
101
+
102
+ def installed_version
103
+ return @version if @version
104
+ reg = JenkinsPipelineBuilder.registry
105
+ version = reg.versions[settings[:plugin_id]]
106
+ puts reg.versions.inspect if version.nil?
107
+ fail "Plugin #{settings[:name]} is not installed (plugin_id: #{settings[:plugin_id]})" if version.nil?
108
+ self.installed_version = version
109
+ @version
110
+ end
111
+
112
+ def extension
113
+ # TODO: Support multiple xml sections for the native to jenkins plugins
114
+ return extensions.first if settings[:plugin_id] == 'builtin'
115
+
116
+ versions = extensions.each_with_object({}) do |ext, hash|
117
+ hash[Gem::Version.new(ext.min_version)] = ext
118
+ end
119
+ versions.keys.sort!.reverse!.each do |version|
120
+ return versions[version] if version <= installed_version
121
+ end
122
+
123
+ fail "Can't find version of #{name} lte #{installed_version}, versions available are #{versions.keys.map(&:to_s)}"
124
+ end
125
+
126
+ def merge(other_set)
127
+ mismatch = []
128
+ SET_METHODS.each do |method_name|
129
+ val1 = settings[method_name]
130
+ val2 = other_set.settings[method_name]
131
+ mismatch << "The values for #{method_name} do not match '#{val1}' : '#{val2}'" unless val1 == val2
132
+ end
133
+ mismatch.each do |error|
134
+ puts error
135
+ end
136
+ fail 'Values did not match, cannot merge exception sets' if mismatch.any?
137
+
138
+ blocks.merge other_set.blocks
139
+ end
140
+
141
+ def xml(path: false, version: '0', &block)
142
+ unless block
143
+ fail "no block found for version #{version}" unless blocks.key version
144
+ return blocks[version][:block]
145
+ end
146
+ if blocks[version]
147
+ blocks[version].merge!(xml: block, path: path)
148
+ else
149
+ blocks[version] = { xml: block, path: path }
150
+ end
151
+ end
152
+
153
+ [:after, :before].each do |method_name|
154
+ define_method method_name do |version: '0', &block|
155
+ return instance_variable_get(method_name) unless block
156
+ blocks[version] = {} unless blocks[version]
157
+ blocks[version][method_name] = block
158
+ end
159
+ end
160
+
161
+ def valid?
162
+ errors.empty?
163
+ end
164
+
165
+ def errors
166
+ errors = {}
167
+ errors['ExtensionSet'] = 'no extensions successfully registered' if extensions.empty?
168
+ extensions.each do |ext|
169
+ ver = ext.min_version || 'unknown'
170
+ errors["#{ext.name} version #{ver}"] = ext.errors unless ext.valid?
171
+ end
172
+ errors
173
+ end
174
+ end
53
175
  end
54
176
 
55
177
  module JenkinsPipelineBuilder
56
178
  class Extension
57
- DSL_METHODS = {
179
+ EXT_METHODS = {
58
180
  name: false,
59
181
  plugin_id: false,
60
- min_version: false,
61
182
  jenkins_name: 'No jenkins display name set',
62
183
  description: 'No description set',
63
- path: false,
64
184
  announced: true,
65
- type: false
185
+ min_version: false,
186
+ path: false,
187
+ type: false,
188
+ before: false,
189
+ after: false,
190
+ xml: false
66
191
  }
67
- DSL_METHODS.keys.each do |method_name|
192
+ EXT_METHODS.keys.each do |method_name|
68
193
  define_method method_name do |value = nil|
69
194
  return instance_variable_get("@#{method_name}") if value.nil?
70
195
  instance_variable_set("@#{method_name}", value)
71
196
  end
72
197
  end
73
198
 
74
- def xml(path = false, &block)
75
- @path = path if path
76
- return @xml unless block
77
- @xml = block
78
- end
79
-
80
- def after(&block)
81
- return @after unless block
82
- @after = block
83
- end
84
-
85
- def before(&block)
86
- return @before unless block
87
- @before = block
88
- end
89
-
90
199
  def initialize
91
- DSL_METHODS.each do |key, value|
200
+ EXT_METHODS.each do |key, value|
92
201
  instance_variable_set("@#{key}", value) if value
93
202
  end
203
+ before false
204
+ after false
94
205
  end
95
206
 
96
207
  def valid?
@@ -99,7 +210,7 @@ module JenkinsPipelineBuilder
99
210
 
100
211
  def errors
101
212
  errors = {}
102
- DSL_METHODS.keys.each do |name|
213
+ EXT_METHODS.keys.each do |name|
103
214
  errors[name] = 'Must be set' if send(name).nil?
104
215
  end
105
216
  errors