pdk 1.9.0 → 3.2.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 +5 -5
- data/CHANGELOG.md +744 -711
- data/README.md +23 -21
- data/lib/pdk/answer_file.rb +3 -112
- data/lib/pdk/bolt.rb +20 -0
- data/lib/pdk/cli/build.rb +51 -54
- data/lib/pdk/cli/bundle.rb +33 -29
- data/lib/pdk/cli/console.rb +148 -0
- data/lib/pdk/cli/convert.rb +46 -37
- data/lib/pdk/cli/env.rb +51 -0
- data/lib/pdk/cli/errors.rb +4 -3
- data/lib/pdk/cli/exec/command.rb +285 -0
- data/lib/pdk/cli/exec/interactive_command.rb +109 -0
- data/lib/pdk/cli/exec.rb +32 -201
- data/lib/pdk/cli/exec_group.rb +79 -43
- data/lib/pdk/cli/get/config.rb +26 -0
- data/lib/pdk/cli/get.rb +22 -0
- data/lib/pdk/cli/new/class.rb +20 -22
- data/lib/pdk/cli/new/defined_type.rb +21 -21
- data/lib/pdk/cli/new/fact.rb +27 -0
- data/lib/pdk/cli/new/function.rb +27 -0
- data/lib/pdk/cli/new/module.rb +40 -29
- data/lib/pdk/cli/new/provider.rb +18 -18
- data/lib/pdk/cli/new/task.rb +23 -22
- data/lib/pdk/cli/new/test.rb +52 -0
- data/lib/pdk/cli/new/transport.rb +27 -0
- data/lib/pdk/cli/new.rb +15 -9
- data/lib/pdk/cli/release/prep.rb +39 -0
- data/lib/pdk/cli/release/publish.rb +46 -0
- data/lib/pdk/cli/release.rb +185 -0
- data/lib/pdk/cli/remove/config.rb +83 -0
- data/lib/pdk/cli/remove.rb +22 -0
- data/lib/pdk/cli/set/config.rb +121 -0
- data/lib/pdk/cli/set.rb +22 -0
- data/lib/pdk/cli/test/unit.rb +71 -69
- data/lib/pdk/cli/test.rb +9 -8
- data/lib/pdk/cli/update.rb +38 -21
- data/lib/pdk/cli/util/command_redirector.rb +13 -3
- data/lib/pdk/cli/util/interview.rb +25 -9
- data/lib/pdk/cli/util/option_normalizer.rb +6 -6
- data/lib/pdk/cli/util/option_validator.rb +19 -9
- data/lib/pdk/cli/util/spinner.rb +13 -0
- data/lib/pdk/cli/util/update_manager_printer.rb +82 -0
- data/lib/pdk/cli/util.rb +105 -48
- data/lib/pdk/cli/validate.rb +96 -111
- data/lib/pdk/cli.rb +134 -87
- data/lib/pdk/config/errors.rb +5 -0
- data/lib/pdk/config/ini_file.rb +184 -0
- data/lib/pdk/config/ini_file_setting.rb +35 -0
- data/lib/pdk/config/json.rb +35 -0
- data/lib/pdk/config/json_schema_namespace.rb +137 -0
- data/lib/pdk/config/json_schema_setting.rb +51 -0
- data/lib/pdk/config/json_with_schema.rb +47 -0
- data/lib/pdk/config/namespace.rb +362 -0
- data/lib/pdk/config/setting.rb +134 -0
- data/lib/pdk/config/task_schema.json +116 -0
- data/lib/pdk/config/validator.rb +31 -0
- data/lib/pdk/config/yaml.rb +41 -0
- data/lib/pdk/config/yaml_with_schema.rb +51 -0
- data/lib/pdk/config.rb +304 -0
- data/lib/pdk/context/control_repo.rb +61 -0
- data/lib/pdk/context/module.rb +28 -0
- data/lib/pdk/context/none.rb +22 -0
- data/lib/pdk/context.rb +98 -0
- data/lib/pdk/control_repo.rb +89 -0
- data/lib/pdk/generate/defined_type.rb +27 -33
- data/lib/pdk/generate/fact.rb +26 -0
- data/lib/pdk/generate/function.rb +49 -0
- data/lib/pdk/generate/module.rb +160 -153
- data/lib/pdk/generate/provider.rb +16 -69
- data/lib/pdk/generate/puppet_class.rb +27 -32
- data/lib/pdk/generate/puppet_object.rb +100 -159
- data/lib/pdk/generate/task.rb +34 -51
- data/lib/pdk/generate/transport.rb +34 -0
- data/lib/pdk/generate.rb +21 -8
- data/lib/pdk/logger.rb +24 -6
- data/lib/pdk/module/build.rb +125 -37
- data/lib/pdk/module/convert.rb +146 -65
- data/lib/pdk/module/metadata.rb +72 -71
- data/lib/pdk/module/release.rb +255 -0
- data/lib/pdk/module/update.rb +48 -37
- data/lib/pdk/module/update_manager.rb +75 -39
- data/lib/pdk/module.rb +10 -2
- data/lib/pdk/monkey_patches.rb +268 -0
- data/lib/pdk/report/event.rb +36 -48
- data/lib/pdk/report.rb +35 -22
- data/lib/pdk/template/fetcher/git.rb +84 -0
- data/lib/pdk/template/fetcher/local.rb +29 -0
- data/lib/pdk/template/fetcher.rb +100 -0
- data/lib/pdk/template/renderer/v1/legacy_template_dir.rb +108 -0
- data/lib/pdk/template/renderer/v1/renderer.rb +131 -0
- data/lib/pdk/template/renderer/v1/template_file.rb +100 -0
- data/lib/pdk/template/renderer/v1.rb +25 -0
- data/lib/pdk/template/renderer.rb +97 -0
- data/lib/pdk/template/template_dir.rb +67 -0
- data/lib/pdk/template.rb +52 -0
- data/lib/pdk/tests/unit.rb +101 -51
- data/lib/pdk/util/bundler.rb +44 -42
- data/lib/pdk/util/changelog_generator.rb +138 -0
- data/lib/pdk/util/env.rb +48 -0
- data/lib/pdk/util/filesystem.rb +139 -2
- data/lib/pdk/util/git.rb +108 -8
- data/lib/pdk/util/json_finder.rb +86 -0
- data/lib/pdk/util/puppet_strings.rb +125 -0
- data/lib/pdk/util/puppet_version.rb +71 -87
- data/lib/pdk/util/ruby_version.rb +49 -25
- data/lib/pdk/util/template_uri.rb +283 -0
- data/lib/pdk/util/vendored_file.rb +34 -42
- data/lib/pdk/util/version.rb +11 -10
- data/lib/pdk/util/windows/api_types.rb +74 -44
- data/lib/pdk/util/windows/file.rb +31 -27
- data/lib/pdk/util/windows/process.rb +74 -0
- data/lib/pdk/util/windows/string.rb +19 -12
- data/lib/pdk/util/windows.rb +2 -0
- data/lib/pdk/util.rb +111 -124
- data/lib/pdk/validate/control_repo/control_repo_validator_group.rb +23 -0
- data/lib/pdk/validate/control_repo/environment_conf_validator.rb +98 -0
- data/lib/pdk/validate/external_command_validator.rb +213 -0
- data/lib/pdk/validate/internal_ruby_validator.rb +101 -0
- data/lib/pdk/validate/invokable_validator.rb +238 -0
- data/lib/pdk/validate/metadata/metadata_json_lint_validator.rb +84 -0
- data/lib/pdk/validate/metadata/metadata_syntax_validator.rb +76 -0
- data/lib/pdk/validate/metadata/metadata_validator_group.rb +20 -0
- data/lib/pdk/validate/puppet/puppet_epp_validator.rb +131 -0
- data/lib/pdk/validate/puppet/puppet_lint_validator.rb +66 -0
- data/lib/pdk/validate/puppet/puppet_plan_syntax_validator.rb +38 -0
- data/lib/pdk/validate/puppet/puppet_syntax_validator.rb +135 -0
- data/lib/pdk/validate/puppet/puppet_validator_group.rb +22 -0
- data/lib/pdk/validate/ruby/ruby_rubocop_validator.rb +79 -0
- data/lib/pdk/validate/ruby/ruby_validator_group.rb +19 -0
- data/lib/pdk/validate/tasks/tasks_metadata_lint_validator.rb +83 -0
- data/lib/pdk/validate/tasks/tasks_name_validator.rb +45 -0
- data/lib/pdk/validate/tasks/tasks_validator_group.rb +20 -0
- data/lib/pdk/validate/validator.rb +120 -0
- data/lib/pdk/validate/validator_group.rb +107 -0
- data/lib/pdk/validate/yaml/yaml_syntax_validator.rb +86 -0
- data/lib/pdk/validate/yaml/yaml_validator_group.rb +19 -0
- data/lib/pdk/validate.rb +86 -12
- data/lib/pdk/version.rb +2 -2
- data/lib/pdk.rb +60 -10
- metadata +138 -100
- data/lib/pdk/cli/module/build.rb +0 -14
- data/lib/pdk/cli/module/generate.rb +0 -45
- data/lib/pdk/cli/module.rb +0 -14
- data/lib/pdk/i18n.rb +0 -4
- data/lib/pdk/module/templatedir.rb +0 -321
- data/lib/pdk/template_file.rb +0 -95
- data/lib/pdk/validate/base_validator.rb +0 -215
- data/lib/pdk/validate/metadata/metadata_json_lint.rb +0 -86
- data/lib/pdk/validate/metadata/metadata_syntax.rb +0 -109
- data/lib/pdk/validate/metadata_validator.rb +0 -30
- data/lib/pdk/validate/puppet/puppet_lint.rb +0 -67
- data/lib/pdk/validate/puppet/puppet_syntax.rb +0 -112
- data/lib/pdk/validate/puppet_validator.rb +0 -30
- data/lib/pdk/validate/ruby/rubocop.rb +0 -77
- data/lib/pdk/validate/ruby_validator.rb +0 -29
- data/lib/pdk/validate/tasks/metadata_lint.rb +0 -126
- data/lib/pdk/validate/tasks/name.rb +0 -88
- data/lib/pdk/validate/tasks_validator.rb +0 -33
- data/lib/pdk/validate/yaml/syntax.rb +0 -109
- data/lib/pdk/validate/yaml_validator.rb +0 -31
- data/locales/config.yaml +0 -21
- data/locales/pdk.pot +0 -1291
data/lib/pdk/tests/unit.rb
CHANGED
|
@@ -1,28 +1,45 @@
|
|
|
1
1
|
require 'pdk'
|
|
2
|
-
require 'pdk/cli/exec'
|
|
3
|
-
require 'pdk/util/bundler'
|
|
4
|
-
require 'json'
|
|
5
2
|
|
|
6
3
|
module PDK
|
|
7
4
|
module Test
|
|
8
5
|
class Unit
|
|
9
6
|
def self.cmd(tests, opts = {})
|
|
10
|
-
rake_args = opts
|
|
11
|
-
rake_args += "[#{tests}]" unless tests.nil?
|
|
7
|
+
rake_args = opts[:parallel] ? 'parallel_spec_standalone' : 'spec_standalone'
|
|
8
|
+
rake_args += "[#{tests}]" unless tests.nil? || tests.empty?
|
|
12
9
|
rake_args
|
|
13
10
|
end
|
|
14
11
|
|
|
15
12
|
def self.rake_bin
|
|
13
|
+
require 'pdk/util'
|
|
14
|
+
|
|
16
15
|
@rake ||= File.join(PDK::Util.module_root, 'bin', 'rake')
|
|
17
16
|
end
|
|
18
17
|
|
|
19
|
-
def self.
|
|
18
|
+
def self.cmd_with_args(task)
|
|
19
|
+
require 'pdk/util/ruby_version'
|
|
20
|
+
|
|
20
21
|
argv = [rake_bin, task]
|
|
21
22
|
argv.unshift(File.join(PDK::Util::RubyVersion.bin_path, 'ruby.exe')) if Gem.win_platform?
|
|
23
|
+
argv
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.rake(task, spinner_text, environment = {})
|
|
27
|
+
require 'pdk/cli/exec/command'
|
|
28
|
+
|
|
29
|
+
command = PDK::CLI::Exec::Command.new(*cmd_with_args(task)).tap do |c|
|
|
30
|
+
c.context = :module
|
|
31
|
+
c.add_spinner(spinner_text) if spinner_text
|
|
32
|
+
c.environment = environment
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
command.execute!
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.interactive_rake(task, environment)
|
|
39
|
+
require 'pdk/cli/exec/interactive_command'
|
|
22
40
|
|
|
23
|
-
command = PDK::CLI::Exec::
|
|
41
|
+
command = PDK::CLI::Exec::InteractiveCommand.new(*cmd_with_args(task)).tap do |c|
|
|
24
42
|
c.context = :module
|
|
25
|
-
c.add_spinner(spinner_text)
|
|
26
43
|
c.environment = environment
|
|
27
44
|
end
|
|
28
45
|
|
|
@@ -31,64 +48,94 @@ module PDK
|
|
|
31
48
|
|
|
32
49
|
def self.parallel_with_no_tests?(ran_in_parallel, json_result, result)
|
|
33
50
|
ran_in_parallel && json_result.empty? &&
|
|
34
|
-
((!result[:exit_code].zero? && result[:stderr].strip =~
|
|
35
|
-
result[:stderr].strip =~
|
|
51
|
+
((!result[:exit_code].zero? && result[:stderr].strip =~ /Pass files or folders to run$/) ||
|
|
52
|
+
result[:stderr].strip =~ /No files for parallel_spec to run against$/)
|
|
36
53
|
end
|
|
37
54
|
|
|
38
55
|
def self.print_failure(result, exception)
|
|
39
56
|
$stderr.puts ''
|
|
40
|
-
result[:stdout]
|
|
41
|
-
result[:stderr]
|
|
57
|
+
result[:stdout]&.each_line { |line| $stderr.puts line.rstrip }
|
|
58
|
+
result[:stderr]&.each_line { |line| $stderr.puts line.rstrip }
|
|
42
59
|
$stderr.puts ''
|
|
43
60
|
raise PDK::CLI::FatalError, exception
|
|
44
61
|
end
|
|
45
62
|
|
|
46
63
|
def self.tear_down
|
|
47
|
-
result = rake('spec_clean',
|
|
64
|
+
result = rake('spec_clean', 'Cleaning up after running unit tests.')
|
|
48
65
|
|
|
49
66
|
return if result[:exit_code].zero?
|
|
50
67
|
|
|
51
|
-
PDK.logger.error(
|
|
52
|
-
print_failure(result,
|
|
68
|
+
PDK.logger.error('The spec_clean rake task failed with the following error(s):')
|
|
69
|
+
print_failure(result, 'Failed to clean up after running unit tests')
|
|
53
70
|
end
|
|
54
71
|
|
|
55
72
|
def self.setup
|
|
56
|
-
result = rake('spec_prep',
|
|
73
|
+
result = rake('spec_prep', 'Preparing to run the unit tests.')
|
|
57
74
|
|
|
58
75
|
return if result[:exit_code].zero?
|
|
59
76
|
|
|
60
77
|
tear_down
|
|
61
78
|
|
|
62
|
-
PDK.logger.error(
|
|
63
|
-
print_failure(result,
|
|
79
|
+
PDK.logger.error('The spec_prep rake task failed with the following error(s):')
|
|
80
|
+
print_failure(result, 'Failed to prepare to run the unit tests.')
|
|
64
81
|
end
|
|
65
82
|
|
|
66
83
|
def self.invoke(report, options = {})
|
|
84
|
+
require 'pdk/util'
|
|
85
|
+
require 'pdk/util/bundler'
|
|
86
|
+
|
|
67
87
|
PDK::Util::Bundler.ensure_binstubs!('rake', 'rspec-core')
|
|
68
88
|
|
|
69
89
|
setup
|
|
70
90
|
|
|
71
|
-
tests = options
|
|
91
|
+
tests = options[:tests]
|
|
92
|
+
# Due to how rake handles paths in the command line options, any backslashed path (Windows platforms) needs to be converted
|
|
93
|
+
# to forward slash. We can't use File.expand_path as the files aren't guaranteed to be on-disk
|
|
94
|
+
#
|
|
95
|
+
# Ref - https://github.com/puppetlabs/pdk/issues/828
|
|
96
|
+
tests = tests.tr('\\', '/') unless tests.nil?
|
|
72
97
|
|
|
73
|
-
environment = {
|
|
98
|
+
environment = {}
|
|
74
99
|
environment['PUPPET_GEM_VERSION'] = options[:puppet] if options[:puppet]
|
|
75
|
-
spinner_msg = options
|
|
100
|
+
spinner_msg = options[:parallel] ? 'Running unit tests in parallel.' : 'Running unit tests.'
|
|
101
|
+
|
|
102
|
+
if options[:interactive]
|
|
103
|
+
environment['CI_SPEC_OPTIONS'] = if options[:verbose]
|
|
104
|
+
'--format documentation'
|
|
105
|
+
else
|
|
106
|
+
'--format progress'
|
|
107
|
+
end
|
|
108
|
+
result = interactive_rake(cmd(tests, options), environment)
|
|
109
|
+
return result[:exit_code]
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Run interactive_rake for documentation output when utilising verbose option.
|
|
113
|
+
if (options[:verbose]) && (options[:format])
|
|
114
|
+
environment['CI_SPEC_OPTIONS'] = '--format documentation'
|
|
115
|
+
result = interactive_rake(cmd(tests, options), environment)
|
|
116
|
+
# Caveat: Report will not be written to format option(s) file(s) when there are event failures.
|
|
117
|
+
return result[:exit_code] unless (result[:exit_code]).zero?
|
|
118
|
+
|
|
119
|
+
spinner_msg = "Exporting unit tests -> #{options[:format]}"
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
environment['CI_SPEC_OPTIONS'] = '--format j'
|
|
76
123
|
result = rake(cmd(tests, options), spinner_msg, environment)
|
|
77
124
|
|
|
78
|
-
json_result = if options
|
|
125
|
+
json_result = if options[:parallel]
|
|
79
126
|
PDK::Util.find_all_json_in(result[:stdout])
|
|
80
127
|
else
|
|
81
128
|
PDK::Util.find_first_json_in(result[:stdout])
|
|
82
129
|
end
|
|
83
130
|
|
|
84
|
-
if parallel_with_no_tests?(options
|
|
131
|
+
if parallel_with_no_tests?(options[:parallel], json_result, result)
|
|
85
132
|
json_result = [{ 'messages' => ['No examples found.'] }]
|
|
86
133
|
result[:exit_code] = 0
|
|
87
134
|
end
|
|
88
135
|
|
|
89
|
-
raise PDK::CLI::FatalError,
|
|
136
|
+
raise PDK::CLI::FatalError, format('Unit test output did not contain a valid JSON result: %{output}', output: result[:stdout]) if json_result.nil? || json_result.empty?
|
|
90
137
|
|
|
91
|
-
json_result = merge_json_results(json_result) if options
|
|
138
|
+
json_result = merge_json_results(json_result) if options[:parallel]
|
|
92
139
|
|
|
93
140
|
parse_output(report, json_result, result[:duration])
|
|
94
141
|
|
|
@@ -99,38 +146,38 @@ module PDK
|
|
|
99
146
|
|
|
100
147
|
def self.parse_output(report, json_data, duration)
|
|
101
148
|
# Output messages to stderr.
|
|
102
|
-
json_data['messages']
|
|
149
|
+
json_data['messages']&.each { |msg| $stderr.puts msg }
|
|
103
150
|
|
|
104
151
|
example_results = {
|
|
105
152
|
# Only possibilities are passed, failed, pending:
|
|
106
|
-
# https://github.com/rspec/rspec-core/blob/
|
|
153
|
+
# https://github.com/rspec/rspec-core/blob/main/lib/rspec/core/example.rb#L548
|
|
107
154
|
'passed' => [],
|
|
108
155
|
'failed' => [],
|
|
109
|
-
'pending' => []
|
|
156
|
+
'pending' => []
|
|
110
157
|
}
|
|
111
158
|
|
|
112
|
-
json_data['examples']
|
|
159
|
+
json_data['examples']&.each do |ex|
|
|
113
160
|
example_results[ex['status']] << ex if example_results.key?(ex['status'])
|
|
114
161
|
end
|
|
115
162
|
|
|
116
163
|
example_results.each do |result, examples|
|
|
117
164
|
# Translate rspec example results to JUnit XML testcase results
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
165
|
+
state_map = {
|
|
166
|
+
'passed' => :passed,
|
|
167
|
+
'failed' => :failure,
|
|
168
|
+
'pending' => :skipped
|
|
169
|
+
}
|
|
123
170
|
|
|
124
171
|
examples.each do |ex|
|
|
125
172
|
report.add_event(
|
|
126
173
|
source: 'rspec',
|
|
127
|
-
state:
|
|
174
|
+
state: state_map[result],
|
|
128
175
|
file: ex['file_path'],
|
|
129
176
|
line: ex['line_number'],
|
|
130
177
|
test: ex['full_description'],
|
|
131
178
|
severity: ex['status'],
|
|
132
179
|
message: ex['pending_message'] || (ex['exception'] && ex['exception']['message']) || nil,
|
|
133
|
-
trace: (ex['exception'] && ex['exception']['backtrace']) || nil
|
|
180
|
+
trace: (ex['exception'] && ex['exception']['backtrace']) || nil
|
|
134
181
|
)
|
|
135
182
|
end
|
|
136
183
|
end
|
|
@@ -138,21 +185,20 @@ module PDK
|
|
|
138
185
|
return unless json_data['summary']
|
|
139
186
|
|
|
140
187
|
# TODO: standardize summary output
|
|
141
|
-
$stderr.puts ' ' <<
|
|
142
|
-
|
|
143
|
-
duration: duration,
|
|
144
|
-
failures: json_data['summary']['failure_count'],
|
|
145
|
-
pending: json_data['summary']['pending_count'],
|
|
146
|
-
}
|
|
188
|
+
$stderr.puts ' ' << (format('Evaluated %{total} tests in %{duration} seconds: %{failures} failures, %{pending} pending.', total: json_data['summary']['example_count'], duration: duration,
|
|
189
|
+
failures: json_data['summary']['failure_count'], pending: json_data['summary']['pending_count'])) # rubocop:disable Layout/LineLength
|
|
147
190
|
end
|
|
148
191
|
|
|
149
192
|
def self.merge_json_results(json_data)
|
|
193
|
+
require 'set'
|
|
194
|
+
|
|
150
195
|
merged_json_result = {}
|
|
151
196
|
|
|
152
197
|
# Merge messages
|
|
153
198
|
message_set = Set.new
|
|
154
199
|
json_data.each do |json|
|
|
155
200
|
next unless json['messages']
|
|
201
|
+
|
|
156
202
|
message_set |= json['messages']
|
|
157
203
|
end
|
|
158
204
|
merged_json_result['messages'] = message_set.to_a
|
|
@@ -161,6 +207,7 @@ module PDK
|
|
|
161
207
|
all_examples = []
|
|
162
208
|
json_data.each do |json|
|
|
163
209
|
next unless json['examples']
|
|
210
|
+
|
|
164
211
|
all_examples.concat json['examples']
|
|
165
212
|
end
|
|
166
213
|
merged_json_result['examples'] = all_examples
|
|
@@ -169,10 +216,11 @@ module PDK
|
|
|
169
216
|
summary_hash = {
|
|
170
217
|
'example_count' => 0,
|
|
171
218
|
'failure_count' => 0,
|
|
172
|
-
'pending_count' => 0
|
|
219
|
+
'pending_count' => 0
|
|
173
220
|
}
|
|
174
221
|
json_data.each do |json|
|
|
175
222
|
next unless json['summary']
|
|
223
|
+
|
|
176
224
|
summary_hash['example_count'] += json['summary']['example_count']
|
|
177
225
|
summary_hash['failure_count'] += json['summary']['failure_count']
|
|
178
226
|
summary_hash['pending_count'] += json['summary']['pending_count']
|
|
@@ -183,23 +231,25 @@ module PDK
|
|
|
183
231
|
end
|
|
184
232
|
|
|
185
233
|
# @return array of { :id, :full_description }
|
|
186
|
-
def self.list
|
|
234
|
+
def self.list(options = {})
|
|
235
|
+
require 'pdk/util'
|
|
236
|
+
require 'pdk/util/bundler'
|
|
237
|
+
|
|
187
238
|
PDK::Util::Bundler.ensure_binstubs!('rake')
|
|
188
239
|
|
|
189
|
-
|
|
190
|
-
|
|
240
|
+
environment = {}
|
|
241
|
+
environment['PUPPET_GEM_VERSION'] = options[:puppet] if options[:puppet]
|
|
191
242
|
|
|
192
|
-
|
|
193
|
-
list_command.context = :module
|
|
194
|
-
output = list_command.execute!
|
|
243
|
+
output = rake('spec_list_json', 'Finding unit tests.', environment)
|
|
195
244
|
|
|
196
245
|
rspec_json = PDK::Util.find_first_json_in(output[:stdout])
|
|
197
|
-
raise PDK::CLI::FatalError,
|
|
246
|
+
raise PDK::CLI::FatalError, format('Failed to find valid JSON in output from rspec: %{output}', output: output[:stdout]) unless rspec_json
|
|
247
|
+
|
|
198
248
|
if rspec_json['examples'].empty?
|
|
199
249
|
rspec_message = rspec_json['messages'][0]
|
|
200
250
|
return [] if rspec_message == 'No examples found.'
|
|
201
251
|
|
|
202
|
-
raise PDK::CLI::FatalError,
|
|
252
|
+
raise PDK::CLI::FatalError, format('Unable to enumerate examples. rspec reported: %{message}', message: rspec_message)
|
|
203
253
|
else
|
|
204
254
|
examples = []
|
|
205
255
|
rspec_json['examples'].each do |example|
|
data/lib/pdk/util/bundler.rb
CHANGED
|
@@ -1,27 +1,23 @@
|
|
|
1
|
-
require '
|
|
2
|
-
require 'digest'
|
|
3
|
-
require 'fileutils'
|
|
4
|
-
require 'pdk/util'
|
|
5
|
-
require 'pdk/cli/exec'
|
|
1
|
+
require 'pdk'
|
|
6
2
|
|
|
7
3
|
module PDK
|
|
8
4
|
module Util
|
|
9
5
|
module Bundler
|
|
10
|
-
class BundleHelper; end
|
|
6
|
+
# class BundleHelper; end
|
|
11
7
|
|
|
12
|
-
def self.ensure_bundle!(gem_overrides =
|
|
8
|
+
def self.ensure_bundle!(gem_overrides = {})
|
|
13
9
|
bundle = BundleHelper.new
|
|
14
10
|
|
|
15
11
|
# This will default ensure_bundle! to re-resolving everything to latest
|
|
16
12
|
gem_overrides ||= { puppet: nil, hiera: nil, facter: nil }
|
|
17
13
|
|
|
18
14
|
if already_bundled?(bundle.gemfile, gem_overrides)
|
|
19
|
-
PDK.logger.debug(
|
|
15
|
+
PDK.logger.debug('Bundler managed gems already up to date.')
|
|
20
16
|
return
|
|
21
17
|
end
|
|
22
18
|
|
|
23
19
|
unless bundle.gemfile?
|
|
24
|
-
PDK.logger.debug(
|
|
20
|
+
PDK.logger.debug(format("No Gemfile found in '%{cwd}'. Skipping bundler management.", cwd: Dir.pwd))
|
|
25
21
|
return
|
|
26
22
|
end
|
|
27
23
|
|
|
@@ -36,11 +32,11 @@ module PDK
|
|
|
36
32
|
original_lockfile = bundle.gemfile_lock
|
|
37
33
|
temp_lockfile = "#{original_lockfile}.tmp"
|
|
38
34
|
|
|
39
|
-
|
|
35
|
+
PDK::Util::Filesystem.mv(original_lockfile, temp_lockfile)
|
|
40
36
|
|
|
41
37
|
all_deps_available = bundle.installed?(gem_overrides)
|
|
42
38
|
ensure
|
|
43
|
-
|
|
39
|
+
PDK::Util::Filesystem.mv(temp_lockfile, original_lockfile, force: true)
|
|
44
40
|
end
|
|
45
41
|
|
|
46
42
|
bundle.update_lock!(with: gem_overrides, local: all_deps_available)
|
|
@@ -48,9 +44,7 @@ module PDK
|
|
|
48
44
|
# If there are missing dependencies after updating the lockfile, let `bundle install`
|
|
49
45
|
# go out and get them. If the specified puppet gem version points to a remote location
|
|
50
46
|
# or local filepath, then run bundle install as well.
|
|
51
|
-
if !bundle.installed?
|
|
52
|
-
bundle.install!(gem_overrides)
|
|
53
|
-
end
|
|
47
|
+
bundle.install!(gem_overrides) if !bundle.installed?(gem_overrides) || gem_overrides[:puppet]&.start_with?('file://', 'git://', 'https://')
|
|
54
48
|
|
|
55
49
|
mark_as_bundled!(bundle.gemfile, gem_overrides)
|
|
56
50
|
end
|
|
@@ -70,6 +64,8 @@ module PDK
|
|
|
70
64
|
end
|
|
71
65
|
|
|
72
66
|
def self.bundle_cache_key(gemfile, gem_overrides)
|
|
67
|
+
require 'digest'
|
|
68
|
+
|
|
73
69
|
override_sig = (gem_overrides || {}).sort_by { |gem, _| gem.to_s }.to_s
|
|
74
70
|
Digest::MD5.hexdigest(gemfile.to_s + override_sig)
|
|
75
71
|
end
|
|
@@ -77,11 +73,13 @@ module PDK
|
|
|
77
73
|
|
|
78
74
|
class BundleHelper
|
|
79
75
|
def gemfile
|
|
76
|
+
require 'pdk/util'
|
|
80
77
|
@gemfile ||= PDK::Util.find_upwards('Gemfile')
|
|
81
78
|
end
|
|
82
79
|
|
|
83
80
|
def gemfile_lock
|
|
84
|
-
return
|
|
81
|
+
return if gemfile.nil?
|
|
82
|
+
|
|
85
83
|
@gemfile_lock ||= File.join(File.dirname(gemfile), 'Gemfile.lock')
|
|
86
84
|
end
|
|
87
85
|
|
|
@@ -90,11 +88,11 @@ module PDK
|
|
|
90
88
|
end
|
|
91
89
|
|
|
92
90
|
def locked?
|
|
93
|
-
!gemfile_lock.nil? &&
|
|
91
|
+
!gemfile_lock.nil? && PDK::Util::Filesystem.file?(gemfile_lock)
|
|
94
92
|
end
|
|
95
93
|
|
|
96
94
|
def installed?(gem_overrides = {})
|
|
97
|
-
PDK.logger.debug(
|
|
95
|
+
PDK.logger.debug('Checking for missing Gemfile dependencies.')
|
|
98
96
|
|
|
99
97
|
argv = ['check', "--gemfile=#{gemfile}", '--dry-run']
|
|
100
98
|
|
|
@@ -104,44 +102,41 @@ module PDK
|
|
|
104
102
|
|
|
105
103
|
result = cmd.execute!
|
|
106
104
|
|
|
107
|
-
unless result[:exit_code].zero?
|
|
108
|
-
PDK.logger.debug(result.values_at(:stdout, :stderr).join("\n"))
|
|
109
|
-
end
|
|
110
|
-
|
|
111
105
|
result[:exit_code].zero?
|
|
112
106
|
end
|
|
113
107
|
|
|
114
108
|
def lock!
|
|
109
|
+
require 'pdk/util'
|
|
110
|
+
require 'pdk/util/ruby_version'
|
|
111
|
+
|
|
115
112
|
if PDK::Util.package_install?
|
|
116
113
|
# In packaged installs, use vendored Gemfile.lock as a starting point.
|
|
117
114
|
# Subsequent 'bundle install' will still pick up any new dependencies.
|
|
118
115
|
vendored_lockfiles = [
|
|
119
116
|
File.join(PDK::Util.package_cachedir, "Gemfile-#{PDK::Util::RubyVersion.active_ruby_version}.lock"),
|
|
120
|
-
File.join(PDK::Util.package_cachedir, 'Gemfile.lock')
|
|
117
|
+
File.join(PDK::Util.package_cachedir, 'Gemfile.lock')
|
|
121
118
|
]
|
|
122
119
|
|
|
123
|
-
vendored_gemfile_lock = vendored_lockfiles.find
|
|
124
|
-
|
|
125
|
-
unless vendored_gemfile_lock
|
|
126
|
-
raise PDK::CLI::FatalError, _('Vendored Gemfile.lock (%{source}) not found.') % {
|
|
127
|
-
source: vendored_gemfile_lock,
|
|
128
|
-
}
|
|
120
|
+
vendored_gemfile_lock = vendored_lockfiles.find do |lockfile|
|
|
121
|
+
PDK::Util::Filesystem.exist?(lockfile)
|
|
129
122
|
end
|
|
130
123
|
|
|
131
|
-
PDK
|
|
132
|
-
|
|
124
|
+
raise PDK::CLI::FatalError, format('Vendored Gemfile.lock (%{source}) not found.', source: vendored_gemfile_lock) unless vendored_gemfile_lock
|
|
125
|
+
|
|
126
|
+
PDK.logger.debug(format('Using vendored Gemfile.lock from %{source}.', source: vendored_gemfile_lock))
|
|
127
|
+
PDK::Util::Filesystem.cp(vendored_gemfile_lock, File.join(PDK::Util.module_root, 'Gemfile.lock'))
|
|
133
128
|
else
|
|
134
129
|
argv = ['lock']
|
|
135
130
|
|
|
136
131
|
cmd = bundle_command(*argv).tap do |c|
|
|
137
|
-
c.add_spinner(
|
|
132
|
+
c.add_spinner('Resolving default Gemfile dependencies.')
|
|
138
133
|
end
|
|
139
134
|
|
|
140
135
|
result = cmd.execute!
|
|
141
136
|
|
|
142
137
|
unless result[:exit_code].zero?
|
|
143
|
-
PDK.logger.fatal(result.values_at(:stdout, :stderr).join("\n"))
|
|
144
|
-
raise PDK::CLI::FatalError,
|
|
138
|
+
PDK.logger.fatal(result.values_at(:stdout, :stderr).join("\n")) unless PDK.logger.debug?
|
|
139
|
+
raise PDK::CLI::FatalError, 'Unable to resolve default Gemfile dependencies.'
|
|
145
140
|
end
|
|
146
141
|
|
|
147
142
|
# After initial lockfile generation, re-resolve json gem to built-in
|
|
@@ -154,7 +149,7 @@ module PDK
|
|
|
154
149
|
end
|
|
155
150
|
|
|
156
151
|
def update_lock!(options = {})
|
|
157
|
-
PDK.logger.debug(
|
|
152
|
+
PDK.logger.debug('Updating Gemfile dependencies.')
|
|
158
153
|
|
|
159
154
|
argv = ['lock', "--lockfile=#{gemfile_lock}", '--update']
|
|
160
155
|
|
|
@@ -181,42 +176,46 @@ module PDK
|
|
|
181
176
|
result = cmd.execute!
|
|
182
177
|
|
|
183
178
|
unless result[:exit_code].zero?
|
|
184
|
-
PDK.logger.fatal(result.values_at(:stdout, :stderr).join("\n"))
|
|
185
|
-
raise PDK::CLI::FatalError,
|
|
179
|
+
PDK.logger.fatal(result.values_at(:stdout, :stderr).join("\n")) unless PDK.logger.debug?
|
|
180
|
+
raise PDK::CLI::FatalError, 'Unable to resolve Gemfile dependencies.'
|
|
186
181
|
end
|
|
187
182
|
|
|
188
183
|
true
|
|
189
184
|
end
|
|
190
185
|
|
|
191
186
|
def install!(gem_overrides = {})
|
|
187
|
+
require 'pdk/util/ruby_version'
|
|
188
|
+
|
|
192
189
|
argv = ['install', "--gemfile=#{gemfile}"]
|
|
193
190
|
argv << '-j4' unless Gem.win_platform? && Gem::Version.new(PDK::Util::RubyVersion.active_ruby_version) < Gem::Version.new('2.3.5')
|
|
194
191
|
|
|
195
192
|
cmd = bundle_command(*argv).tap do |c|
|
|
196
|
-
c.add_spinner(
|
|
193
|
+
c.add_spinner('Installing missing Gemfile dependencies.')
|
|
197
194
|
c.update_environment(gemfile_env(gem_overrides)) unless gem_overrides.empty?
|
|
198
195
|
end
|
|
199
196
|
|
|
200
197
|
result = cmd.execute!
|
|
201
198
|
|
|
202
199
|
unless result[:exit_code].zero?
|
|
203
|
-
PDK.logger.fatal(result.values_at(:stdout, :stderr).join("\n"))
|
|
204
|
-
raise PDK::CLI::FatalError,
|
|
200
|
+
PDK.logger.fatal(result.values_at(:stdout, :stderr).join("\n")) unless PDK.logger.debug?
|
|
201
|
+
raise PDK::CLI::FatalError, 'Unable to install missing Gemfile dependencies.'
|
|
205
202
|
end
|
|
206
203
|
|
|
207
204
|
true
|
|
208
205
|
end
|
|
209
206
|
|
|
210
207
|
def binstubs!(gems)
|
|
208
|
+
raise PDK::CLI::FatalError, 'Unable to install requested binstubs as the Gemfile is missing' if gemfile.nil?
|
|
209
|
+
|
|
211
210
|
binstub_dir = File.join(File.dirname(gemfile), 'bin')
|
|
212
|
-
return true if gems.all? { |gem|
|
|
211
|
+
return true if gems.all? { |gem| PDK::Util::Filesystem.file?(File.join(binstub_dir, gem)) }
|
|
213
212
|
|
|
214
213
|
cmd = bundle_command('binstubs', *gems, '--force')
|
|
215
214
|
result = cmd.execute!
|
|
216
215
|
|
|
217
216
|
unless result[:exit_code].zero?
|
|
218
|
-
PDK.logger.fatal(
|
|
219
|
-
raise PDK::CLI::FatalError,
|
|
217
|
+
PDK.logger.fatal(format("Failed to generate binstubs for '%{gems}':\n%{output}", gems: gems.join(' '), output: result.values_at(:stdout, :stderr).join("\n"))) unless PDK.logger.debug?
|
|
218
|
+
raise PDK::CLI::FatalError, 'Unable to install requested binstubs.'
|
|
220
219
|
end
|
|
221
220
|
|
|
222
221
|
true
|
|
@@ -243,6 +242,9 @@ module PDK
|
|
|
243
242
|
end
|
|
244
243
|
|
|
245
244
|
def bundle_command(*args)
|
|
245
|
+
require 'pdk/cli/exec'
|
|
246
|
+
require 'pdk/cli/exec/command'
|
|
247
|
+
|
|
246
248
|
PDK::CLI::Exec::Command.new(PDK::CLI::Exec.bundle_bin, *args).tap do |c|
|
|
247
249
|
c.context = :module
|
|
248
250
|
end
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
require 'pdk'
|
|
2
|
+
|
|
3
|
+
module PDK
|
|
4
|
+
module Util
|
|
5
|
+
module ChangelogGenerator
|
|
6
|
+
# Taken from the version regex in https://forgeapi.puppet.com/schemas/module.json
|
|
7
|
+
VERSION_REGEX = /^(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-]+)*)?$/.freeze
|
|
8
|
+
GEM = 'github_changelog_generator'.freeze
|
|
9
|
+
|
|
10
|
+
# Raises if the github_changelog_generator is not available
|
|
11
|
+
def self.github_changelog_generator_available!
|
|
12
|
+
check_command = PDK::CLI::Exec::InteractiveCommand.new(PDK::CLI::Exec.bundle_bin, 'info', 'github_changelog_generator')
|
|
13
|
+
check_command.context = :module
|
|
14
|
+
|
|
15
|
+
result = check_command.execute!
|
|
16
|
+
|
|
17
|
+
return if result[:exit_code].zero?
|
|
18
|
+
|
|
19
|
+
raise PDK::CLI::ExitWithError, format('Unable to generate the changelog as the %{gem} gem is not included in this module\'s Gemfile', gem: GEM)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Runs the Changelog Generator gem (in the module's context) to automatically create a CHANGLELOG.MD file
|
|
23
|
+
#
|
|
24
|
+
# @returns [String] The content of the new Changelog
|
|
25
|
+
def self.generate_changelog
|
|
26
|
+
github_changelog_generator_available!
|
|
27
|
+
|
|
28
|
+
changelog_command = PDK::CLI::Exec::InteractiveCommand.new(PDK::CLI::Exec.bundle_bin, 'exec', 'rake', 'changelog')
|
|
29
|
+
changelog_command.context = :module
|
|
30
|
+
|
|
31
|
+
result = changelog_command.execute!
|
|
32
|
+
raise PDK::CLI::ExitWithError, format('Error generating changelog: %{stdout}', stdout: result[:stdout]) unless result[:exit_code].zero?
|
|
33
|
+
|
|
34
|
+
output = changelog_content
|
|
35
|
+
|
|
36
|
+
raise PDK::CLI::ExitWithError, format('The generated changelog contains uncategorized Pull Requests. Please label them and try again. See %{changelog_file} for more details', changelog_file: changelog_file) if output.include?('UNCATEGORIZED PRS; GO LABEL THEM') # rubocop:disable Layout/LineLength
|
|
37
|
+
|
|
38
|
+
output
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Computes the next version, based on the content of a changelog
|
|
42
|
+
#
|
|
43
|
+
# @param current_version [String, Gem::Version] The current version of the module
|
|
44
|
+
# @return [String] The new version. May be the same as the current version if there are no notable changes
|
|
45
|
+
def self.compute_next_version(current_version)
|
|
46
|
+
raise PDK::CLI::ExitWithError, format('Invalid version string %{version}', version: current_version) unless VERSION_REGEX.match?(current_version)
|
|
47
|
+
|
|
48
|
+
version = Gem::Version.create(current_version).segments
|
|
49
|
+
PDK.logger.info format('Determing the target version from \'%{file}\'', file: changelog_file)
|
|
50
|
+
|
|
51
|
+
# Grab all lines that start with ## between from the latest changes
|
|
52
|
+
# For example given the changelog below
|
|
53
|
+
|
|
54
|
+
# ```
|
|
55
|
+
# # Change log
|
|
56
|
+
#
|
|
57
|
+
# All notable changes to this project will be documented in this file.
|
|
58
|
+
#
|
|
59
|
+
# ## [v4.0.0](https://github.com/puppetlabs/puppetlabs-inifile/tree/v4.
|
|
60
|
+
#
|
|
61
|
+
# [Full Changelog](https://github.com/puppetlabs/puppetlabs-inifile/com --+
|
|
62
|
+
# |
|
|
63
|
+
# ### Changed |
|
|
64
|
+
# |
|
|
65
|
+
# - pdksync - FM-8499 - remove ubuntu14 support [\#363](https://github. | It's this piece of text we are interested in
|
|
66
|
+
# |
|
|
67
|
+
# ### Added |
|
|
68
|
+
# |
|
|
69
|
+
# - FM-8402 add debian 10 support [\#352](https://github.com/puppetlabs |
|
|
70
|
+
# |
|
|
71
|
+
# ## [v3.1.0](https://github.com/puppetlabs/puppetlabs-inifile/tree/v3. |
|
|
72
|
+
# --+
|
|
73
|
+
# [Full Changelog](https://github.com/puppetlabs/puppetlabs-inifile/com
|
|
74
|
+
#
|
|
75
|
+
# ### Added
|
|
76
|
+
#
|
|
77
|
+
# - FM-8222 - Port Module inifile to Litmus [\#344](https://github.com/
|
|
78
|
+
# - \(FM-8154\) Add Windows Server 2019 support [\#340](https://github.
|
|
79
|
+
# - \(FM-8041\) Add RedHat 8 support [\#339](https://github.com/puppetl
|
|
80
|
+
# ````
|
|
81
|
+
data = ''
|
|
82
|
+
in_changelog_entry = false
|
|
83
|
+
changelog_content.each_line do |line|
|
|
84
|
+
line.strip!
|
|
85
|
+
if line.start_with?('[')
|
|
86
|
+
# We're leaving the latest changes so we can break
|
|
87
|
+
break if in_changelog_entry
|
|
88
|
+
|
|
89
|
+
in_changelog_entry = true
|
|
90
|
+
end
|
|
91
|
+
data += line if in_changelog_entry && line.start_with?('##')
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Check for meta headers in first two header line matches
|
|
95
|
+
case data
|
|
96
|
+
when /^### Changed/
|
|
97
|
+
# Major Version bump
|
|
98
|
+
version[0] += 1
|
|
99
|
+
version[1] = 0
|
|
100
|
+
version[2] = 0
|
|
101
|
+
when /^### Added/
|
|
102
|
+
# Minor Version bump
|
|
103
|
+
version[1] += 1
|
|
104
|
+
version[2] = 0
|
|
105
|
+
when /^### Fixed/
|
|
106
|
+
# Patch Version bump
|
|
107
|
+
version[2] += 1
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
version.join('.')
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Returns the top most version from the CHANGELOG file
|
|
114
|
+
def self.latest_version
|
|
115
|
+
latest = nil
|
|
116
|
+
changelog_content.each_line do |line|
|
|
117
|
+
line.strip!
|
|
118
|
+
if line.start_with?('## [')
|
|
119
|
+
latest = line[line.index('[') + 1..line.index(']') - 1].delete('v')
|
|
120
|
+
break # stops after the top version is extracted
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
latest
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def self.changelog_file
|
|
127
|
+
# Default Changelog file is CHANGELOG.md, but also search for the .MD prefix as well.
|
|
128
|
+
@changelog_file ||= ['CHANGELOG.md', 'CHANGELOG.MD'].map { |file| PDK::Util::Filesystem.expand_path(file) }.find { |path| PDK::Util::Filesystem.file?(path) }
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def self.changelog_content
|
|
132
|
+
return '' if changelog_file.nil?
|
|
133
|
+
|
|
134
|
+
PDK::Util::Filesystem.read_file(changelog_file, open_args: 'rb:utf-8')
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|