pdk 1.16.0 → 1.17.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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/lib/pdk.rb +25 -18
  4. data/lib/pdk/answer_file.rb +2 -93
  5. data/lib/pdk/cli.rb +1 -5
  6. data/lib/pdk/cli/config.rb +3 -1
  7. data/lib/pdk/cli/config/get.rb +3 -1
  8. data/lib/pdk/cli/convert.rb +1 -1
  9. data/lib/pdk/cli/exec/command.rb +13 -0
  10. data/lib/pdk/cli/exec_group.rb +78 -43
  11. data/lib/pdk/cli/get.rb +20 -0
  12. data/lib/pdk/cli/get/config.rb +24 -0
  13. data/lib/pdk/cli/util.rb +6 -3
  14. data/lib/pdk/cli/validate.rb +26 -44
  15. data/lib/pdk/config.rb +178 -4
  16. data/lib/pdk/config/ini_file.rb +183 -0
  17. data/lib/pdk/config/ini_file_setting.rb +39 -0
  18. data/lib/pdk/config/namespace.rb +25 -5
  19. data/lib/pdk/config/setting.rb +3 -2
  20. data/lib/pdk/context.rb +96 -0
  21. data/lib/pdk/context/control_repo.rb +60 -0
  22. data/lib/pdk/context/module.rb +28 -0
  23. data/lib/pdk/context/none.rb +22 -0
  24. data/lib/pdk/control_repo.rb +40 -0
  25. data/lib/pdk/generate/module.rb +8 -12
  26. data/lib/pdk/module/release.rb +2 -8
  27. data/lib/pdk/util.rb +35 -5
  28. data/lib/pdk/util/bundler.rb +1 -0
  29. data/lib/pdk/util/changelog_generator.rb +6 -1
  30. data/lib/pdk/util/template_uri.rb +4 -3
  31. data/lib/pdk/validate.rb +72 -25
  32. data/lib/pdk/validate/external_command_validator.rb +208 -0
  33. data/lib/pdk/validate/internal_ruby_validator.rb +100 -0
  34. data/lib/pdk/validate/invokable_validator.rb +216 -0
  35. data/lib/pdk/validate/metadata/metadata_json_lint_validator.rb +86 -0
  36. data/lib/pdk/validate/metadata/metadata_syntax_validator.rb +78 -0
  37. data/lib/pdk/validate/metadata/metadata_validator_group.rb +20 -0
  38. data/lib/pdk/validate/puppet/puppet_epp_validator.rb +133 -0
  39. data/lib/pdk/validate/puppet/puppet_lint_validator.rb +66 -0
  40. data/lib/pdk/validate/puppet/puppet_syntax_validator.rb +137 -0
  41. data/lib/pdk/validate/puppet/puppet_validator_group.rb +21 -0
  42. data/lib/pdk/validate/ruby/ruby_rubocop_validator.rb +80 -0
  43. data/lib/pdk/validate/ruby/ruby_validator_group.rb +19 -0
  44. data/lib/pdk/validate/tasks/tasks_metadata_lint_validator.rb +88 -0
  45. data/lib/pdk/validate/tasks/tasks_name_validator.rb +50 -0
  46. data/lib/pdk/validate/tasks/tasks_validator_group.rb +20 -0
  47. data/lib/pdk/validate/validator.rb +111 -0
  48. data/lib/pdk/validate/validator_group.rb +103 -0
  49. data/lib/pdk/validate/yaml/yaml_syntax_validator.rb +95 -0
  50. data/lib/pdk/validate/yaml/yaml_validator_group.rb +19 -0
  51. data/lib/pdk/version.rb +1 -1
  52. data/locales/pdk.pot +161 -125
  53. metadata +29 -17
  54. data/lib/pdk/validate/base_validator.rb +0 -215
  55. data/lib/pdk/validate/metadata/metadata_json_lint.rb +0 -82
  56. data/lib/pdk/validate/metadata/metadata_syntax.rb +0 -111
  57. data/lib/pdk/validate/metadata_validator.rb +0 -26
  58. data/lib/pdk/validate/puppet/puppet_epp.rb +0 -135
  59. data/lib/pdk/validate/puppet/puppet_lint.rb +0 -64
  60. data/lib/pdk/validate/puppet/puppet_syntax.rb +0 -135
  61. data/lib/pdk/validate/puppet_validator.rb +0 -26
  62. data/lib/pdk/validate/ruby/rubocop.rb +0 -72
  63. data/lib/pdk/validate/ruby_validator.rb +0 -26
  64. data/lib/pdk/validate/tasks/metadata_lint.rb +0 -130
  65. data/lib/pdk/validate/tasks/name.rb +0 -90
  66. data/lib/pdk/validate/tasks_validator.rb +0 -29
  67. data/lib/pdk/validate/yaml/syntax.rb +0 -125
  68. data/lib/pdk/validate/yaml_validator.rb +0 -28
@@ -146,6 +146,15 @@ module PDK
146
146
  end
147
147
  module_function :configdir
148
148
 
149
+ def system_configdir
150
+ return @system_configdir unless @system_configdir.nil?
151
+ return @system_configdir = File.join('opt', 'puppetlabs', 'pdk', 'config') unless Gem.win_platform?
152
+
153
+ return @system_configdir = File.join(PDK::Util::Env['ProgramData'], 'PuppetLabs', 'PDK') unless PDK::Util::Env['ProgramData'].nil?
154
+ @system_configdir = File.join(PDK::Util::Env['AllUsersProfile'], 'PuppetLabs', 'PDK')
155
+ end
156
+ module_function :system_configdir
157
+
149
158
  # Returns path to the root of the module being worked on.
150
159
  #
151
160
  # @return [String, nil] Fully qualified base path to module, or nil if
@@ -248,16 +257,18 @@ module PDK
248
257
  module_function :targets_relative_to_pwd
249
258
 
250
259
  # TO-DO: Refactor replacement of lib/pdk/module/build.rb:metadata to use this function instead
251
- def module_metadata
260
+ # @param module_path [String] The path to the root of the module. Default is determine the module root automatically
261
+ def module_metadata(module_path = nil)
252
262
  require 'pdk/module/metadata'
253
-
254
- PDK::Module::Metadata.from_file(File.join(module_root, 'metadata.json')).data
263
+ module_path ||= module_root
264
+ PDK::Module::Metadata.from_file(File.join(module_path, 'metadata.json')).data
255
265
  end
256
266
  module_function :module_metadata
257
267
 
258
268
  # TO-DO: Refactor replacement of lib/pdk/module/build.rb:module_pdk_compatible? to use this function instead
259
- def module_pdk_compatible?
260
- ['pdk-version', 'template-url'].any? { |key| module_metadata.key?(key) }
269
+ # @param module_path [String] The path to the root of the module. Default is determine the module root automatically
270
+ def module_pdk_compatible?(module_path = nil)
271
+ ['pdk-version', 'template-url'].any? { |key| module_metadata(module_path).key?(key) }
261
272
  end
262
273
  module_function :module_pdk_compatible?
263
274
 
@@ -274,5 +285,24 @@ module PDK
274
285
  nil
275
286
  end
276
287
  module_function :module_pdk_version
288
+
289
+ # Does a deep copy instead of a shallow copy of an object.
290
+ #
291
+ # @param object [Object] The object to duplicate
292
+ #
293
+ # @return [Object] duplicate of the original object
294
+ # the current working dir does not appear to be within a module.
295
+ def deep_duplicate(object)
296
+ if object.is_a?(Array)
297
+ object.map { |item| deep_duplicate(item) }
298
+ elsif object.is_a?(Hash)
299
+ hash = object.dup
300
+ hash.each_pair { |key, value| hash[key] = deep_duplicate(value) }
301
+ hash
302
+ else
303
+ object
304
+ end
305
+ end
306
+ module_function :deep_duplicate
277
307
  end
278
308
  end
@@ -210,6 +210,7 @@ module PDK
210
210
  end
211
211
 
212
212
  def binstubs!(gems)
213
+ raise PDK::CLI::FatalError, _('Unable to install requested binstubs as the Gemfile is missing') if gemfile.nil?
213
214
  binstub_dir = File.join(File.dirname(gemfile), 'bin')
214
215
  return true if gems.all? { |gem| PDK::Util::Filesystem.file?(File.join(binstub_dir, gem)) }
215
216
 
@@ -5,11 +5,16 @@ module PDK
5
5
  module ChangelogGenerator
6
6
  # Taken from the version regex in https://forgeapi.puppet.com/schemas/module.json
7
7
  VERSION_REGEX = %r{^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$}
8
+ GEM = 'github_changelog_generator'.freeze
8
9
 
9
10
  # Raises if the github_changelog_generator is not available
10
11
  def self.github_changelog_generator_available!
11
12
  require 'bundler'
12
- raise PDK::CLI::ExitWithError, _('Unable to generate the changelog as the github_changelog_generator gem is not installed') unless Bundler.rubygems.find_name('github_changelog_generator').any?
13
+ return if ::Bundler.rubygems.find_name(GEM).any?
14
+
15
+ raise PDK::CLI::ExitWithError, _(
16
+ 'Unable to generate the changelog as the %{gem} gem is not installed',
17
+ ) % { gem: GEM }
13
18
  end
14
19
 
15
20
  # Runs the Changelog Generator gem (in the module's context) to automatically create a CHANGLELOG.MD file
@@ -218,10 +218,11 @@ module PDK
218
218
  else
219
219
  nil
220
220
  end
221
- answers_uri = if [PACKAGED_TEMPLATE_KEYWORD, DEPRECATED_TEMPLATE_URL].include?(PDK.answers['template-url'])
221
+ default_template_url = PDK.config.get_within_scopes('module_defaults.template-url')
222
+ answers_uri = if [PACKAGED_TEMPLATE_KEYWORD, DEPRECATED_TEMPLATE_URL].include?(default_template_url)
222
223
  Addressable::URI.parse(default_template_uri)
223
- elsif PDK.answers['template-url']
224
- new(uri_safe(PDK.answers['template-url'])).uri
224
+ elsif default_template_url
225
+ new(uri_safe(default_template_url)).uri
225
226
  else
226
227
  nil
227
228
  end
@@ -2,37 +2,84 @@ require 'pdk'
2
2
 
3
3
  module PDK
4
4
  module Validate
5
- # TODO: Fix validator namespacing
6
- autoload :BaseValidator, 'pdk/validate/base_validator'
7
- autoload :MetadataJSONLint, 'pdk/validate/metadata/metadata_json_lint'
8
- autoload :MetadataSyntax, 'pdk/validate/metadata/metadata_syntax'
9
- autoload :MetadataValidator, 'pdk/validate/metadata_validator'
10
- autoload :PuppetEPP, 'pdk/validate/puppet/puppet_epp'
11
- autoload :PuppetLint, 'pdk/validate/puppet/puppet_lint'
12
- autoload :PuppetSyntax, 'pdk/validate/puppet/puppet_syntax'
13
- autoload :PuppetValidator, 'pdk/validate/puppet_validator'
14
- autoload :Rubocop, 'pdk/validate/ruby/rubocop'
15
- autoload :RubyValidator, 'pdk/validate/ruby_validator'
16
- autoload :TasksValidator, 'pdk/validate/tasks_validator'
17
- autoload :YAMLValidator, 'pdk/validate/yaml_validator'
5
+ autoload :ExternalCommandValidator, 'pdk/validate/external_command_validator'
6
+ autoload :InternalRubyValidator, 'pdk/validate/internal_ruby_validator'
7
+ autoload :InvokableValidator, 'pdk/validate/invokable_validator'
8
+ autoload :Validator, 'pdk/validate/validator'
9
+ autoload :ValidatorGroup, 'pdk/validate/validator_group'
18
10
 
19
- class Tasks
20
- autoload :Name, 'pdk/validate/tasks/name'
21
- autoload :MetadataLint, 'pdk/validate/tasks/metadata_lint'
11
+ module Metadata
12
+ autoload :MetadataJSONLintValidator, 'pdk/validate/metadata/metadata_json_lint_validator'
13
+ autoload :MetadataSyntaxValidator, 'pdk/validate/metadata/metadata_syntax_validator'
14
+ autoload :MetadataValidatorGroup, 'pdk/validate/metadata/metadata_validator_group'
22
15
  end
23
16
 
24
- class YAML
25
- autoload :Syntax, 'pdk/validate/yaml/syntax'
17
+ module YAML
18
+ autoload :YAMLSyntaxValidator, 'pdk/validate/yaml/yaml_syntax_validator'
19
+ autoload :YAMLValidatorGroup, 'pdk/validate/yaml/yaml_validator_group'
20
+ end
21
+
22
+ module Ruby
23
+ autoload :RubyRubocopValidator, 'pdk/validate/ruby/ruby_rubocop_validator'
24
+ autoload :RubyValidatorGroup, 'pdk/validate/ruby/ruby_validator_group'
25
+ end
26
+
27
+ module Tasks
28
+ autoload :TasksNameValidator, 'pdk/validate/tasks/tasks_name_validator'
29
+ autoload :TasksMetadataLintValidator, 'pdk/validate/tasks/tasks_metadata_lint_validator'
30
+ autoload :TasksValidatorGroup, 'pdk/validate/tasks/tasks_validator_group'
31
+ end
32
+
33
+ module Puppet
34
+ autoload :PuppetEPPValidator, 'pdk/validate/puppet/puppet_epp_validator'
35
+ autoload :PuppetLintValidator, 'pdk/validate/puppet/puppet_lint_validator'
36
+ autoload :PuppetSyntaxValidator, 'pdk/validate/puppet/puppet_syntax_validator'
37
+ autoload :PuppetValidatorGroup, 'pdk/validate/puppet/puppet_validator_group'
26
38
  end
27
39
 
28
40
  def self.validators
29
- @validators ||= [
30
- MetadataValidator,
31
- YAMLValidator,
32
- PuppetValidator,
33
- RubyValidator,
34
- TasksValidator,
35
- ].freeze
41
+ validator_hash.values
42
+ end
43
+
44
+ def self.validator_names
45
+ validator_hash.keys
46
+ end
47
+
48
+ # @api private
49
+ def self.validator_hash
50
+ # TODO: This isn't the most performant... But with only 5 items, it's fine
51
+ @validator_hash ||= [
52
+ Metadata::MetadataValidatorGroup,
53
+ Puppet::PuppetValidatorGroup,
54
+ Ruby::RubyValidatorGroup,
55
+ Tasks::TasksValidatorGroup,
56
+ YAML::YAMLValidatorGroup,
57
+ ].map { |klass| [klass.new.name, klass] }.to_h.freeze
58
+ end
59
+
60
+ def self.invoke_validators_by_name(context, names, parallel = false, options = {})
61
+ instances = names.select { |name| validator_names.include?(name) }
62
+ .map { |name| validator_hash[name].new(context, options) }
63
+ .each { |instance| instance.prepare_invoke! }
64
+ report = PDK::Report.new
65
+
66
+ # Nothing to validate then nothing to do.
67
+ return [0, report] if instances.empty?
68
+
69
+ require 'pdk/cli/exec_group'
70
+ exec_group = PDK::CLI::ExecGroup.create(
71
+ _('Validating module using %{num_of_threads} threads' % { num_of_threads: instances.count }),
72
+ { parallel: parallel },
73
+ options,
74
+ )
75
+
76
+ instances.each do |validator|
77
+ exec_group.register do
78
+ validator.invoke(report)
79
+ end
80
+ end
81
+
82
+ [exec_group.exit_code, report]
36
83
  end
37
84
 
38
85
  class ParseOutputError < StandardError; end
@@ -0,0 +1,208 @@
1
+ require 'pdk'
2
+
3
+ module PDK
4
+ module Validate
5
+ # An abstract validator that runs external commands within a Ruby Bundled environment
6
+ # e.g. `puppet-lint`, or `puppet validate`
7
+ #
8
+ # At a a minimum child classes should implment the `name`, `cmd`, `pattern` and `parse_output` methods
9
+ #
10
+ # An example concrete implementation could look like:
11
+ #
12
+ # module PDK
13
+ # module Validate
14
+ # module Ruby
15
+ # class RubyRubocopValidator < ExternalCommandValidator
16
+ # def name
17
+ # 'rubocop'
18
+ # end
19
+ #
20
+ # def cmd
21
+ # 'rubocop'
22
+ # end
23
+ #
24
+ # def pattern
25
+ # '**/**.rb'
26
+ # end
27
+ #
28
+ # def parse_options(targets)
29
+ # ['--format', 'json']
30
+ # end
31
+ #
32
+ # def parse_output(report, result, _targets)
33
+ # ... ruby code ...
34
+ # report.add_event(
35
+ # line: offense['location']['line'],
36
+ # column: offense['location']['column'],
37
+ # message: offense['message'],
38
+ # severity: offense['corrected'] ? 'corrected' : offense['severity'],
39
+ # test: offense['cop_name'],
40
+ # state: :failure,
41
+ # )
42
+ # end
43
+ # end
44
+ # end
45
+ # end
46
+ # end
47
+ #
48
+ # @see PDK::Validate::InvokableValidator
49
+ class ExternalCommandValidator < InvokableValidator
50
+ # @return Array[PDK::CLI::Exec::Command] This is a private implementation attribute used for unit testing
51
+ # @api private
52
+ attr_reader :commands
53
+
54
+ # @see PDK::Validate::Validator.spinner
55
+ def spinner
56
+ # The validator has sub-commands with their own spinners.
57
+ nil
58
+ end
59
+
60
+ # Calculates the text of the spinner based on the target list
61
+ # @return [String]
62
+ # @abstract
63
+ def spinner_text_for_targets(targets); end
64
+
65
+ # The name of the command to be run for validation
66
+ # @return [String]
67
+ # @abstract
68
+ def cmd; end
69
+
70
+ # Alternate paths which the command (cmd) may exist in. Typically other ruby gem caches,
71
+ # or packaged installation bin directories.
72
+ # @return [Array[String]]
73
+ # @api private
74
+ def alternate_bin_paths
75
+ [
76
+ PDK::Util::RubyVersion.bin_path,
77
+ File.join(PDK::Util::RubyVersion.gem_home, 'bin'),
78
+ PDK::Util::RubyVersion.gem_paths_raw.map { |gem_path_raw| File.join(gem_path_raw, 'bin') },
79
+ PDK::Util.package_install? ? File.join(PDK::Util.pdk_package_basedir, 'bin') : nil,
80
+ ].flatten.compact
81
+ end
82
+
83
+ # The full path to the command (cmd)
84
+ # Can be overridden in child classes to a non-default path
85
+ # @return [String]
86
+ # @api private
87
+ def cmd_path
88
+ return @cmd_path unless @cmd_path.nil?
89
+ @cmd_path = File.join(context.root_path, 'bin', cmd)
90
+ # Return the path to the command if it exists on disk, or we have a gemfile (i.e. Bundled install)
91
+ # The Bundle may be created after the prepare_invoke so if the file doesn't exist, it may not be an error
92
+ return @cmd_path if PDK::Util::Filesystem.exist?(@cmd_path) || !PDK::Util::Bundler::BundleHelper.new.gemfile.nil?
93
+ # But if there is no Gemfile AND cmd doesn't exist in the default path, we need to go searching...
94
+ @cmd_path = alternate_bin_paths.map { |alternate_path| File.join(alternate_path, cmd) }
95
+ .find { |path| PDK::Util::Filesystem.exist?(path) }
96
+ return @cmd_path unless @cmd_path.nil?
97
+ # If we can't find it anywhere, just let the OS find it
98
+ @cmd_path = cmd
99
+ end
100
+
101
+ # An array of command line arguments to pass to the command for validation
102
+ # @return Array[String]
103
+ # @abstract
104
+ def parse_options(_targets)
105
+ []
106
+ end
107
+
108
+ # Parses the output from the command and appends formatted events to the report.
109
+ # This is called for each command, which is a group of targets
110
+ #
111
+ # @param report [PDK::Report] The report to add events to
112
+ # @param result [Hash[Symbol => Object]] The result of validation command process
113
+ # @param targets [Array[String]] The targets for this command result
114
+ # @api private
115
+ # @see PDK::CLI::Exec::Command.execute!
116
+ # @abstract
117
+ def parse_output(_report, _result, _targets); end
118
+
119
+ # Prepares for invokation by parsing targets and creating the needed commands.
120
+ # @api private
121
+ # @see PDK::Validate::Validator.prepare_invoke!
122
+ def prepare_invoke!
123
+ return if @prepared
124
+ super
125
+
126
+ @targets, @skipped, @invalid = parse_targets
127
+ @targets = [] if @targets.nil?
128
+
129
+ target_groups = if @targets.empty? && allow_empty_targets?
130
+ # If we have no targets and we allow empty targets, create an empty target group list
131
+ [[]]
132
+ elsif invoke_style == :per_target
133
+ # If invoking :per_target, split the targets array into an array of
134
+ # single element arrays (one per target).
135
+ @targets.combination(1).to_a.compact
136
+ else
137
+ # Else we're invoking :once, wrap the targets array in another array. This is so we
138
+ # can loop through the invokes with the same logic, regardless of which invoke style
139
+ # is needed.
140
+ @targets.each_slice(1000).to_a.compact
141
+ end
142
+
143
+ # Register all of the commands for all of the targets
144
+ @commands = []
145
+ target_groups.each do |invokation_targets|
146
+ next if invokation_targets.empty? && !allow_empty_targets?
147
+ cmd_argv = parse_options(invokation_targets).unshift(cmd_path).compact
148
+ cmd_argv.unshift(File.join(PDK::Util::RubyVersion.bin_path, 'ruby.exe'), '-W0') if Gem.win_platform?
149
+
150
+ command = PDK::CLI::Exec::Command.new(*cmd_argv).tap do |c|
151
+ c.context = :module
152
+ c.environment = { 'PUPPET_GEM_VERSION' => options[:puppet] } if options[:puppet]
153
+
154
+ if spinners_enabled?
155
+ parent_validator = options[:parent_validator]
156
+ if parent_validator.nil? || parent_validator.spinner.nil? || !parent_validator.spinner.is_a?(TTY::Spinner::Multi)
157
+ c.add_spinner(spinner_text_for_targets(invokation_targets))
158
+ else
159
+ spinner = TTY::Spinner.new("[:spinner] #{spinner_text_for_targets(invokation_targets)}", PDK::CLI::Util.spinner_opts_for_platform)
160
+ parent_validator.spinner.register(spinner)
161
+ c.register_spinner(spinner, PDK::CLI::Util.spinner_opts_for_platform)
162
+ end
163
+ end
164
+ end
165
+
166
+ @commands << { command: command, invokation_targets: invokation_targets }
167
+ end
168
+ nil
169
+ end
170
+
171
+ # Invokes the prepared commands as an ExecGroup
172
+ # @see PDK::Validate::Validator.invoke
173
+ def invoke(report)
174
+ prepare_invoke!
175
+
176
+ process_skipped(report, @skipped)
177
+ process_invalid(report, @invalid)
178
+
179
+ # Nothing to execute so return success
180
+ return 0 if @commands.empty?
181
+
182
+ # If there's no Gemfile, then we can't ensure the binstubs are correct
183
+ PDK::Util::Bundler.ensure_binstubs!(cmd) unless PDK::Util::Bundler::BundleHelper.new.gemfile.nil?
184
+
185
+ exec_group = PDK::CLI::ExecGroup.create(name, { parallel: false }, options)
186
+
187
+ # Register all of the commands for all of the targets
188
+ @commands.each do |item|
189
+ command = item[:command]
190
+ invokation_targets = item[:invokation_targets]
191
+
192
+ exec_group.register do
193
+ result = command.execute!
194
+ begin
195
+ parse_output(report, result, invokation_targets.compact)
196
+ rescue PDK::Validate::ParseOutputError => e
197
+ $stderr.puts e.message
198
+ end
199
+ result[:exit_code]
200
+ end
201
+ end
202
+
203
+ # Now execute and get the return code
204
+ exec_group.exit_code
205
+ end
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,100 @@
1
+ require 'pdk'
2
+
3
+ module PDK
4
+ module Validate
5
+ # An abstract validator that runs ruby code internal to the PDK e.g. JSON and YAML validation, on a single file.
6
+ # The validator code must run within the PDK Ruby environment as opposed to the bundled Ruby environment for a module.
7
+ #
8
+ # At a a minimum child classes should implment the `name`, `pattern` and `validate_target` methods
9
+ #
10
+ # An example concrete implementation could look like:
11
+ #
12
+ # module PDK
13
+ # module Validate
14
+ # module Tasks
15
+ # class TasksNameValidator < InternalRubyValidator
16
+ # def name
17
+ # 'task-name'
18
+ # end
19
+ #
20
+ # def pattern
21
+ # 'tasks/**/*'
22
+ # end
23
+ #
24
+ # def validate_target(report, target)
25
+ # task_name = File.basename(target, File.extname(target))
26
+ # ... ruby code ...
27
+ # success ? 0 : 1
28
+ # end
29
+ # end
30
+ # end
31
+ # end
32
+ # end
33
+ #
34
+ #
35
+ # @abstract
36
+ # @see PDK::Validate::InvokableValidator
37
+ class InternalRubyValidator < InvokableValidator
38
+ # @see PDK::Validate::Validator.prepare_invoke!
39
+ def prepare_invoke!
40
+ return if @prepared
41
+ super
42
+
43
+ # Parse the targets
44
+ @targets, @skipped, @invalid = parse_targets
45
+
46
+ nil
47
+ end
48
+
49
+ # Invokes the validator to call `validate_target` on each target
50
+ # @see PDK::Validate::Validator.invoke
51
+ def invoke(report)
52
+ prepare_invoke!
53
+
54
+ process_skipped(report, @skipped)
55
+ process_invalid(report, @invalid)
56
+
57
+ return 0 if @targets.empty?
58
+
59
+ return_val = 0
60
+
61
+ before_validation
62
+
63
+ start_spinner
64
+ @targets.each do |target|
65
+ validation_result = validate_target(report, target)
66
+ if validation_result.nil?
67
+ report.add_event(
68
+ file: target,
69
+ source: name,
70
+ state: :failure,
71
+ severity: 'error',
72
+ message: "Validation did not return an exit code for #{target}",
73
+ )
74
+ validation_result = 1
75
+ end
76
+ return_val = validation_result if validation_result > return_val
77
+ end
78
+
79
+ stop_spinner(return_val.zero?)
80
+ return_val
81
+ end
82
+
83
+ # Validates a single target
84
+ # It is the responsibility of this method to populate the report with validation messages
85
+ #
86
+ # @param report [PDK::Report] The report to add the events to
87
+ # @param target [String] The target to validate
88
+ #
89
+ # @return [Integer] The exitcode of the validation. Zero indicates success. A non-zero code indicates failure
90
+ # @api private
91
+ # @abstract
92
+ def validate_target(report, target); end
93
+
94
+ # Tasks to run before validation occurs. This is run once every time `.invoke` is called
95
+ # @api private
96
+ # @abstract
97
+ def before_validation; end
98
+ end
99
+ end
100
+ end