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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/lib/pdk.rb +25 -18
- data/lib/pdk/answer_file.rb +2 -93
- data/lib/pdk/cli.rb +1 -5
- data/lib/pdk/cli/config.rb +3 -1
- data/lib/pdk/cli/config/get.rb +3 -1
- data/lib/pdk/cli/convert.rb +1 -1
- data/lib/pdk/cli/exec/command.rb +13 -0
- data/lib/pdk/cli/exec_group.rb +78 -43
- data/lib/pdk/cli/get.rb +20 -0
- data/lib/pdk/cli/get/config.rb +24 -0
- data/lib/pdk/cli/util.rb +6 -3
- data/lib/pdk/cli/validate.rb +26 -44
- data/lib/pdk/config.rb +178 -4
- data/lib/pdk/config/ini_file.rb +183 -0
- data/lib/pdk/config/ini_file_setting.rb +39 -0
- data/lib/pdk/config/namespace.rb +25 -5
- data/lib/pdk/config/setting.rb +3 -2
- data/lib/pdk/context.rb +96 -0
- data/lib/pdk/context/control_repo.rb +60 -0
- data/lib/pdk/context/module.rb +28 -0
- data/lib/pdk/context/none.rb +22 -0
- data/lib/pdk/control_repo.rb +40 -0
- data/lib/pdk/generate/module.rb +8 -12
- data/lib/pdk/module/release.rb +2 -8
- data/lib/pdk/util.rb +35 -5
- data/lib/pdk/util/bundler.rb +1 -0
- data/lib/pdk/util/changelog_generator.rb +6 -1
- data/lib/pdk/util/template_uri.rb +4 -3
- data/lib/pdk/validate.rb +72 -25
- data/lib/pdk/validate/external_command_validator.rb +208 -0
- data/lib/pdk/validate/internal_ruby_validator.rb +100 -0
- data/lib/pdk/validate/invokable_validator.rb +216 -0
- data/lib/pdk/validate/metadata/metadata_json_lint_validator.rb +86 -0
- data/lib/pdk/validate/metadata/metadata_syntax_validator.rb +78 -0
- data/lib/pdk/validate/metadata/metadata_validator_group.rb +20 -0
- data/lib/pdk/validate/puppet/puppet_epp_validator.rb +133 -0
- data/lib/pdk/validate/puppet/puppet_lint_validator.rb +66 -0
- data/lib/pdk/validate/puppet/puppet_syntax_validator.rb +137 -0
- data/lib/pdk/validate/puppet/puppet_validator_group.rb +21 -0
- data/lib/pdk/validate/ruby/ruby_rubocop_validator.rb +80 -0
- data/lib/pdk/validate/ruby/ruby_validator_group.rb +19 -0
- data/lib/pdk/validate/tasks/tasks_metadata_lint_validator.rb +88 -0
- data/lib/pdk/validate/tasks/tasks_name_validator.rb +50 -0
- data/lib/pdk/validate/tasks/tasks_validator_group.rb +20 -0
- data/lib/pdk/validate/validator.rb +111 -0
- data/lib/pdk/validate/validator_group.rb +103 -0
- data/lib/pdk/validate/yaml/yaml_syntax_validator.rb +95 -0
- data/lib/pdk/validate/yaml/yaml_validator_group.rb +19 -0
- data/lib/pdk/version.rb +1 -1
- data/locales/pdk.pot +161 -125
- metadata +29 -17
- data/lib/pdk/validate/base_validator.rb +0 -215
- data/lib/pdk/validate/metadata/metadata_json_lint.rb +0 -82
- data/lib/pdk/validate/metadata/metadata_syntax.rb +0 -111
- data/lib/pdk/validate/metadata_validator.rb +0 -26
- data/lib/pdk/validate/puppet/puppet_epp.rb +0 -135
- data/lib/pdk/validate/puppet/puppet_lint.rb +0 -64
- data/lib/pdk/validate/puppet/puppet_syntax.rb +0 -135
- data/lib/pdk/validate/puppet_validator.rb +0 -26
- data/lib/pdk/validate/ruby/rubocop.rb +0 -72
- data/lib/pdk/validate/ruby_validator.rb +0 -26
- data/lib/pdk/validate/tasks/metadata_lint.rb +0 -130
- data/lib/pdk/validate/tasks/name.rb +0 -90
- data/lib/pdk/validate/tasks_validator.rb +0 -29
- data/lib/pdk/validate/yaml/syntax.rb +0 -125
- data/lib/pdk/validate/yaml_validator.rb +0 -28
data/lib/pdk/util.rb
CHANGED
@@ -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
|
-
|
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(
|
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
|
-
|
260
|
-
|
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
|
data/lib/pdk/util/bundler.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
224
|
-
new(uri_safe(
|
224
|
+
elsif default_template_url
|
225
|
+
new(uri_safe(default_template_url)).uri
|
225
226
|
else
|
226
227
|
nil
|
227
228
|
end
|
data/lib/pdk/validate.rb
CHANGED
@@ -2,37 +2,84 @@ require 'pdk'
|
|
2
2
|
|
3
3
|
module PDK
|
4
4
|
module Validate
|
5
|
-
|
6
|
-
autoload :
|
7
|
-
autoload :
|
8
|
-
autoload :
|
9
|
-
autoload :
|
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
|
-
|
20
|
-
autoload :
|
21
|
-
autoload :
|
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
|
-
|
25
|
-
autoload :
|
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
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|