jenkins_pipeline_builder 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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