pdk 1.16.0 → 1.17.0

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