pdk 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f22acd513e00856fbadcd4c5090b2787df655426
4
- data.tar.gz: 6636287e1acef4c9ba87f52b4b853c922e4ce92b
3
+ metadata.gz: 5501e7effa501cd2ba488735cc9abb8257ffef6a
4
+ data.tar.gz: e4f7a88496280db89b0ee46a42a7b8feacc24594
5
5
  SHA512:
6
- metadata.gz: 2ce7e0faffaac9a2484c23dc1e88f9b240e0d768d63c8c793439f9a560a95cfa31a8745b510d4c84b83e410639bae7eb004f9d91732fd7740b4650581f71969a
7
- data.tar.gz: d7a9e5bae06899f4972add88c8bc49053b257ce7aa10fb38537ea5101ea0e9ceae56e62e212bff6e07e372c558b6f38e9a9dc8ae290a6048d8fb7f72a64ddd0d
6
+ metadata.gz: 736c543069aa1b1d3eb79c8de901e91cf2491328fc3104f7bd660c37cafd88712583d471cbd2f4afd37b9c49890bfcb60c5b2857121f3cabb81841662fa53557
7
+ data.tar.gz: 5b5b03c6ac83fca4d730cba0db0277441d9bb062ed5f13ebecf24836d237db11856e6811f276ec2dcfafe28fd5c86a009958ef9e894021d14ba8a1e4d0a15af8
data/CHANGELOG.md CHANGED
@@ -3,6 +3,25 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
5
 
6
+ ## [v0.3.0](https://github.com/puppetlabs/pdk/tree/v0.3.0) (2017-06-29)
7
+ [Full Changelog](https://github.com/puppetlabs/pdk/compare/v0.2.0...v0.3.0)
8
+
9
+ **Implemented enhancements:**
10
+
11
+ - \(MAINT\) Add support for stacktrace to Report::Event class [\#112](https://github.com/puppetlabs/pdk/pull/112) ([scotje](https://github.com/scotje))
12
+ - \(MAINT\) Various CLI::Exec improvements and updates [\#111](https://github.com/puppetlabs/pdk/pull/111) ([scotje](https://github.com/scotje))
13
+ - \(SDK-148\) Add "test unit --list" [\#107](https://github.com/puppetlabs/pdk/pull/107) ([james-stocks](https://github.com/james-stocks))
14
+ - \(SDK-137\) Add puppet syntax validation [\#105](https://github.com/puppetlabs/pdk/pull/105) ([bmjen](https://github.com/bmjen))
15
+ - \(SDK-285\) Add --auto-correct flag to validators that support it [\#104](https://github.com/puppetlabs/pdk/pull/104) ([rodjek](https://github.com/rodjek))
16
+ - \(SDK-284\) Add guidance for users during new module interview [\#103](https://github.com/puppetlabs/pdk/pull/103) ([rodjek](https://github.com/rodjek))
17
+ - \(SDK-147\) Add 'test unit' runner and basic output formatting [\#98](https://github.com/puppetlabs/pdk/pull/98) ([scotje](https://github.com/scotje))
18
+
19
+ **Fixed bugs:**
20
+
21
+ - \(SDK-297\) Fixes writing reports to a file [\#119](https://github.com/puppetlabs/pdk/pull/119) ([bmjen](https://github.com/bmjen))
22
+ - \(SDK-290\) Make sure that all usernames are processed when creating a new module [\#108](https://github.com/puppetlabs/pdk/pull/108) ([austb](https://github.com/austb))
23
+ - \(SDK-277\) Exit cleanly if pdk commands are run outside of a module [\#100](https://github.com/puppetlabs/pdk/pull/100) ([rodjek](https://github.com/rodjek))
24
+
6
25
  ## [v0.2.0](https://github.com/puppetlabs/pdk/tree/v0.2.0) (2017-06-21)
7
26
  [Full Changelog](https://github.com/puppetlabs/pdk/compare/v0.1.0...v0.2.0)
8
27
 
data/README.md CHANGED
@@ -52,12 +52,48 @@ pdk validate
52
52
  This displays results in the console:
53
53
 
54
54
  ```
55
- Running validations on `new_module`:
56
- * ruby syntax: OK!
57
- * puppet syntax: OK!
55
+ pdk (INFO): Running all available validators...
56
+ [✔] Checking for missing Gemfile dependencies
57
+ [✔] Checking metadata.json
58
+ [✔] Checking Ruby code style
58
59
  [...]
59
60
  ```
60
61
 
62
+ Specific validators can be run by providing the validator name (or a comma
63
+ separated list of names) as an argument to `pdk validate`.
64
+
65
+ ```
66
+ $ pdk validate metadata
67
+ [✔] Checking for missing Gemfile dependencies
68
+ [✔] Checking metadata.json
69
+ ```
70
+
71
+ By default each validator will automatically determine which files in the
72
+ module that it should validate, however validations can be run on specific
73
+ files or directories by providing them as arguments to `pdk validate`
74
+
75
+ ```
76
+ $ pdk validate lib/
77
+ [✔] Checking for missing Gemfile dependencies
78
+ [✔] Checking Ruby code style
79
+ ```
80
+
81
+ Some validators support automatic correction of detected problems (for example,
82
+ both rubocop and puppet-lint can automatically correct many common code style
83
+ problems). To enable this functionality, run `pdk validate` with the
84
+ `--auto-correct` option.
85
+
86
+ ```
87
+ $ pdk validate --auto-correct
88
+ pdk (INFO): Running all available validators...
89
+ [✔] Checking for missing Gemfile dependencies
90
+ [✔] Checking metadata.json
91
+ [✔] Checking Puppet manifest style
92
+ [✔] Checking Puppet manifest syntax
93
+ [✔] Checking Ruby code style
94
+ manifests/init.pp:1:10: corrected: double quoted string containing no variables
95
+ ```
96
+
61
97
  ### Run unit tests
62
98
 
63
99
  The default template sets up [rspec](http://rspec.info/) for Ruby-level unit testing, and [rspec-puppet](https://github.com/rodjek/rspec-puppet/) for catalog-level unit testing.
@@ -262,3 +298,13 @@ bundle binstubs pdk --path ~/bin
262
298
  ```
263
299
 
264
300
  Bug reports and pull requests are welcome on GitHub at https://github.com/puppetlabs/pdk.
301
+
302
+ ### Release Process
303
+
304
+ 1. Bump the version in `lib/pdk/version.rb`.
305
+ 1. In a clean checkout of master, run `bundle exec rake changelog`.
306
+ 1. Edit PR titles and tags, until `bundle exec rake changelog` output makes sense.
307
+ 1. Commit and PR the changes.
308
+ 1. When the PR is merged, get a clean checkout of the merged commit, and run `bundle exec rake release[upstream]` (where "upstream" is your local name of the puppetlabs remote)
309
+ 1. Profit!
310
+ 1. Update `lib/pdk/version.rb` with `x.y.z-pre`, commit, and PR to prepare for next release.
data/lib/pdk/cli.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'cri'
2
2
 
3
3
  require 'pdk/cli/errors'
4
+ require 'pdk/cli/util'
4
5
  require 'pdk/cli/util/option_normalizer'
5
6
  require 'pdk/cli/util/option_validator'
6
7
  require 'pdk/generators/module'
data/lib/pdk/cli/exec.rb CHANGED
@@ -55,6 +55,7 @@ module PDK
55
55
  attr_reader :argv
56
56
  attr_reader :context
57
57
  attr_accessor :timeout
58
+ attr_accessor :environment
58
59
 
59
60
  def initialize(*argv)
60
61
  @argv = argv
@@ -70,6 +71,9 @@ module PDK
70
71
 
71
72
  # Default to running things in the system context.
72
73
  @context = :system
74
+
75
+ # Extra environment vars to add to base set.
76
+ @environment = {}
73
77
  end
74
78
 
75
79
  def context=(new_context)
@@ -84,19 +88,32 @@ module PDK
84
88
  @success_message = opts.delete(:success)
85
89
  @failure_message = opts.delete(:failure)
86
90
 
87
- @spinner = TTY::Spinner.new("[:spinner] #{message}", opts)
91
+ @spinner = Gem.win_platform? ? WindowsSpinner.new(message, opts) : TTY::Spinner.new("[:spinner] #{message}", opts)
88
92
  end
89
93
 
90
94
  def execute!
91
95
  # Start spinning if configured.
92
96
  @spinner.auto_spin if @spinner
93
97
 
98
+ # Add custom env vars.
99
+ @environment.each do |k, v|
100
+ @process.environment[k] = v
101
+ end
102
+
94
103
  if context == :module
95
104
  # TODO: we should probably more carefully manage PATH and maybe other things too
96
105
  @process.environment['GEM_HOME'] = File.join(PDK::Util.cachedir, 'bundler', 'ruby', RbConfig::CONFIG['ruby_version'])
97
106
  @process.environment['GEM_PATH'] = pdk_gem_path
98
107
 
99
- Dir.chdir(PDK::Util.module_root) do
108
+ mod_root = PDK::Util.module_root
109
+
110
+ unless mod_root
111
+ @spinner.error
112
+
113
+ raise PDK::CLI::FatalError, _('Current working directory is not part of a module. (No metadata.json was found.)')
114
+ end
115
+
116
+ Dir.chdir(mod_root) do
100
117
  ::Bundler.with_clean_env do
101
118
  run_process!
102
119
  end
@@ -132,15 +149,12 @@ module PDK
132
149
  protected
133
150
 
134
151
  def run_process!
152
+ command_string = argv.join(' ')
153
+ PDK.logger.debug(_("Executing '%{command}'") % { command: command_string })
135
154
  begin
136
155
  @process.start
137
156
  rescue ChildProcess::LaunchError => e
138
- msg = if @process.respond_to?(:argv)
139
- _("Failed to execute '%{command}': %{message}") % { command: @process.argv.join(' '), message: e.message }
140
- else
141
- _('Failed to execute process: %{message}') % { message: e.message }
142
- end
143
- raise PDK::CLI::FatalError, msg
157
+ raise PDK::CLI::FatalError, _("Failed to execute '%{command}': %{message}") % { command: command_string, message: e.message }
144
158
  end
145
159
 
146
160
  if timeout
@@ -160,7 +174,6 @@ module PDK
160
174
  end
161
175
 
162
176
  def find_pdk_gem_path
163
- # /opt/puppetlabs/sdk/private/ruby/2.1.9/lib/ruby/gems/2.1.0
164
177
  package_gem_path = File.join(PDK::CLI::Exec.pdk_basedir, 'private', 'ruby', RUBY_VERSION, 'lib', 'ruby', 'gems', RbConfig::CONFIG['ruby_version'])
165
178
 
166
179
  if File.directory?(package_gem_path)
@@ -171,6 +184,30 @@ module PDK
171
184
  end
172
185
  end
173
186
  end
187
+
188
+ # This is a placeholder until we integrate ansicon into Windows packaging
189
+ # or come up with some other progress indicator for Windows.
190
+ class WindowsSpinner
191
+ def initialize(message, _opts = {})
192
+ @message = message
193
+ end
194
+
195
+ def auto_spin
196
+ $stderr.print @message << '...'
197
+ end
198
+
199
+ def success(message = '')
200
+ message ||= 'done.'
201
+
202
+ $stderr.print message << "\n"
203
+ end
204
+
205
+ def error(message = '')
206
+ message ||= 'FAILED'
207
+
208
+ $stderr.print message << "\n"
209
+ end
210
+ end
174
211
  end
175
212
  end
176
213
  end
@@ -1,4 +1,3 @@
1
-
2
1
  module PDK::CLI
3
2
  @new_class_cmd = @new_cmd.define_command do
4
3
  name 'class'
@@ -10,6 +9,8 @@ module PDK::CLI
10
9
  run do |opts, args, _cmd|
11
10
  require 'pdk/generators/puppet_class'
12
11
 
12
+ PDK::CLI::Util.ensure_in_module!
13
+
13
14
  class_name = args[0]
14
15
  module_dir = Dir.pwd
15
16
 
@@ -1,3 +1,5 @@
1
+ require 'pdk/cli/util/option_validator'
2
+ require 'pdk/report'
1
3
 
2
4
  module PDK::CLI
3
5
  @test_unit_cmd = @test_cmd.define_command do
@@ -7,32 +9,49 @@ module PDK::CLI
7
9
 
8
10
  flag nil, :list, _('list all available unit tests and their descriptions')
9
11
 
10
- option nil, :tests, _('a comma-separated list of tests to run'), argument: :required do |values|
11
- OptionValidator.list(values)
12
+ option nil, :tests, _('a comma-separated list of tests to run'), argument: :required, default: '' do |values|
13
+ PDK::CLI::Util::OptionValidator.comma_separated_list?(values)
12
14
  end
13
15
 
14
- option nil, :runner_options, _('options to pass through to the actual test-runner'), argument: :required
16
+ # TODO
17
+ # option nil, :runner_options, _("options to pass through to the actual test-runner"), argument: :required
15
18
 
16
19
  run do |opts, _args, _cmd|
17
20
  require 'pdk/tests/unit'
18
21
 
22
+ PDK::CLI::Util.ensure_in_module!
23
+
19
24
  report = nil
20
25
 
21
26
  if opts[:list]
22
- puts _('List of all available unit tests: (TODO)')
23
- end
24
-
25
- if opts[:tests]
26
- tests = opts.fetch(:tests)
27
+ examples = PDK::Test::Unit.list
28
+ if examples.empty?
29
+ puts _('No examples found.')
30
+ else
31
+ puts _('Examples:')
32
+ examples.each do |example|
33
+ puts _("%{id}\t%{description}" % { id: example[:id], description: example[:full_description] })
34
+ end
35
+ end
36
+ else
37
+ report = PDK::Report.new
38
+ report_formats = if opts[:format]
39
+ PDK::CLI::Util::OptionNormalizer.report_formats(opts[:format])
40
+ else
41
+ [{
42
+ method: PDK::Report.default_format,
43
+ target: PDK::Report.default_target,
44
+ }]
45
+ end
46
+
47
+ exit_code = PDK::Test::Unit.invoke(report, opts)
48
+
49
+ report_formats.each do |format|
50
+ report.send(format[:method], format[:target])
51
+ end
52
+
53
+ exit exit_code
27
54
  end
28
-
29
- # Note: Reporting may be delegated to the validation tool itself.
30
- if opts[:'report-file']
31
- format = opts.fetch(:'report-format', PDK::Report.default_format)
32
- report = Report.new(opts.fetch(:'report-file'), format)
33
- end
34
-
35
- PDK::Test::Unit.invoke(tests, report)
36
55
  end
37
56
  end
38
57
  end
@@ -0,0 +1,15 @@
1
+ module PDK
2
+ module CLI
3
+ module Util
4
+ # Ensures the calling code is being run from inside a module directory.
5
+ #
6
+ # @raise [PDK::CLI::FatalError] if the current directory or parents do
7
+ # not contain a `metadata.json` file.
8
+ def ensure_in_module!
9
+ message = _('This command must be run from inside a module (no metadata.json found)')
10
+ raise PDK::CLI::FatalError, message if PDK::Util.module_root.nil?
11
+ end
12
+ module_function :ensure_in_module!
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,52 @@
1
+ require 'tty-prompt'
2
+
3
+ module PDK
4
+ module CLI
5
+ module Util
6
+ class Interview < TTY::Prompt::AnswersCollector
7
+ def pastel
8
+ @pastel ||= Pastel.new
9
+ end
10
+
11
+ def add_questions(questions)
12
+ questions.each do |question|
13
+ add_question(question)
14
+ end
15
+ end
16
+
17
+ def add_question(options = {})
18
+ (@questions ||= {})[options[:name]] = options
19
+ end
20
+
21
+ def num_questions
22
+ @questions.count
23
+ end
24
+
25
+ def run
26
+ i = 1
27
+ num_questions = @questions.count
28
+ @questions.each do |question_name, question|
29
+ @name = question_name
30
+ puts pastel.bold(_('[Q %{current_number}/%{questions_total}]') % { current_number: i, questions_total: num_questions })
31
+ puts pastel.bold(question[:question])
32
+ puts question[:help]
33
+ ask(_('-->')) do |q|
34
+ q.required(question.fetch(:required, false))
35
+
36
+ if question.key?(:validate_pattern)
37
+ q.validate(question[:validate_pattern], question[:validate_message])
38
+ end
39
+
40
+ q.default(question[:default]) if question.key?(:default)
41
+ end
42
+ i += 1
43
+ puts ''
44
+ end
45
+ @answers
46
+ rescue TTY::Prompt::Reader::InputInterrupt
47
+ nil
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -42,7 +42,7 @@ module PDK
42
42
  target = $stderr
43
43
  end
44
44
 
45
- { method: "to_#{format}".to_sym, target: target }
45
+ { method: "write_#{format}".to_sym, target: target }
46
46
  end
47
47
  end
48
48
 
@@ -3,11 +3,18 @@ require 'pdk/util/bundler'
3
3
  module PDK::CLI
4
4
  @validate_cmd = @base_cmd.define_command do
5
5
  name 'validate'
6
- usage _('validate [options]')
6
+ usage _('validate [validators] [options] [targets]')
7
7
  summary _('Run static analysis tests.')
8
- description _('Run metadata, puppet, or ruby validation.')
8
+ description _(
9
+ "Run metadata, puppet, or ruby validation.\n\n" \
10
+ '[validators] is an optional comma separated list of validators to use. ' \
11
+ "If not specified, all validators will be used.\n\n" \
12
+ '[targets] is an optional space separated list of files or directories to be validated. ' \
13
+ 'If not specified, the validators will be run against all applicable files in the module.',
14
+ )
9
15
 
10
16
  flag nil, :list, _('list all available validators')
17
+ flag :a, 'auto-correct', _('automatically correct problems (where possible)')
11
18
 
12
19
  run do |opts, args, _cmd|
13
20
  validator_names = PDK::Validate.validators.map { |v| v.name }
@@ -19,6 +26,8 @@ module PDK::CLI
19
26
  exit 0
20
27
  end
21
28
 
29
+ PDK::CLI::Util.ensure_in_module!
30
+
22
31
  if args[0]
23
32
  # This may be a single validator, a list of validators, or a target.
24
33
  if Util::OptionValidator.comma_separated_list?(args[0])
@@ -60,6 +69,7 @@ module PDK::CLI
60
69
  end
61
70
 
62
71
  options = targets.empty? ? {} : { targets: targets }
72
+ options[:auto_correct] = true if opts.key?(:'auto-correct')
63
73
 
64
74
  exit_code = 0
65
75
 
@@ -1,13 +1,14 @@
1
1
  require 'etc'
2
2
  require 'pathname'
3
3
  require 'fileutils'
4
+ require 'tty-prompt'
4
5
 
5
6
  require 'pdk'
6
7
  require 'pdk/logger'
7
8
  require 'pdk/module/metadata'
8
9
  require 'pdk/module/templatedir'
9
10
  require 'pdk/cli/exec'
10
- require 'pdk/cli/input'
11
+ require 'pdk/cli/util/interview'
11
12
  require 'pdk/util'
12
13
  require 'pdk/util/version'
13
14
 
@@ -17,26 +18,13 @@ module PDK
17
18
  DEFAULT_TEMPLATE = 'https://github.com/puppetlabs/pdk-module-template'.freeze
18
19
 
19
20
  def self.invoke(opts = {})
20
- defaults = {
21
- 'name' => "#{Etc.getlogin}-#{opts[:name]}",
22
- 'version' => '0.1.0',
23
- 'dependencies' => [
24
- { 'name' => 'puppetlabs-stdlib', 'version_requirement' => '>= 4.13.1 < 5.0.0' },
25
- ],
26
- }
27
-
28
- defaults['license'] = opts[:license] if opts.key? :license
29
21
  target_dir = File.expand_path(opts[:target_dir])
30
22
 
31
23
  if File.exist?(target_dir)
32
24
  raise PDK::CLI::FatalError, _("The destination directory '%{dir}' already exists") % { dir: target_dir }
33
25
  end
34
26
 
35
- metadata = PDK::Module::Metadata.new(defaults)
36
-
37
- module_interview(metadata, opts) unless opts[:'skip-interview'] # @todo Build way to get info by answers file
38
-
39
- metadata.update!('pdk-version' => PDK::Util::Version.version_string)
27
+ metadata = prepare_metadata(opts)
40
28
 
41
29
  temp_target_dir = PDK::Util.make_tmpdir_name('pdk-module-target')
42
30
 
@@ -63,6 +51,31 @@ module PDK
63
51
  FileUtils.mv(temp_target_dir, target_dir)
64
52
  end
65
53
 
54
+ def self.prepare_metadata(opts)
55
+ username = Etc.getlogin.gsub(%r{[^0-9a-z]}i, '')
56
+ username = 'username' if username == ''
57
+ if Etc.getlogin != username
58
+ PDK.logger.warn(_('Your username is not a valid Forge username, proceeding with the username %{username}' % { username: username }))
59
+ end
60
+
61
+ defaults = {
62
+ 'name' => "#{username}-#{opts[:name]}",
63
+ 'version' => '0.1.0',
64
+ 'dependencies' => [
65
+ { 'name' => 'puppetlabs-stdlib', 'version_requirement' => '>= 4.13.1 < 5.0.0' },
66
+ ],
67
+ }
68
+ defaults['license'] = opts[:license] if opts.key? :license
69
+
70
+ metadata = PDK::Module::Metadata.new(defaults)
71
+
72
+ module_interview(metadata, opts) unless opts[:'skip-interview'] # @todo Build way to get info by answers file
73
+
74
+ metadata.update!('pdk-version' => PDK::Util::Version.version_string)
75
+
76
+ metadata
77
+ end
78
+
66
79
  def self.prepare_module_directory(target_dir)
67
80
  [
68
81
  File.join(target_dir, 'manifests'),
@@ -77,63 +90,98 @@ module PDK
77
90
  end
78
91
 
79
92
  def self.module_interview(metadata, opts = {})
80
- puts _(
81
- 'We need to create a metadata.json file for this module. Please answer the ' \
82
- 'following questions; if the question is not applicable to this module, feel free ' \
83
- 'to leave it blank.',
84
- )
85
-
86
- begin
87
- puts ''
88
- forge_user = PDK::CLI::Input.get(_('What is your Puppet Forge username?'), metadata.data['author'])
89
- metadata.update!('name' => "#{forge_user}-#{opts[:name]}")
90
- rescue StandardError => e
91
- PDK.logger.error(_("We're sorry, we could not parse your module name: %{message}") % { message: e.message })
92
- retry
93
- end
93
+ questions = [
94
+ {
95
+ name: 'name',
96
+ question: _('What is your Puppet Forge username?'),
97
+ help: _('This will be used when uploading your module to the Forge. You can opt out of this at any time.'),
98
+ required: true,
99
+ validate_pattern: %r{\A[a-z0-9]+\Z}i,
100
+ validate_message: _('Forge usernames can only contain lowercase letters and numbers'),
101
+ default: metadata.data['author'],
102
+ },
103
+ {
104
+ name: 'version',
105
+ question: _('What version is this module?'),
106
+ help: _('Puppet uses Semantic Versioning (semver.org) to version modules.'),
107
+ required: true,
108
+ validate_pattern: %r{\A[0-9]+\.[0-9]+\.[0-9]+},
109
+ validate_message: _('Semantic Version numbers must be in the form MAJOR.MINOR.PATCH'),
110
+ default: metadata.data['version'],
111
+ },
112
+ {
113
+ name: 'author',
114
+ question: _('Who wrote this module?'),
115
+ help: _('The person who gets credit for creating the module. '),
116
+ required: true,
117
+ default: metadata.data['author'],
118
+ },
119
+ {
120
+ name: 'license',
121
+ question: _('What license does this module code fall under?'),
122
+ help: _('This should be an identifier from https://spdk.org/licenses/. Common values are "Apache-2.0", "MIT", or "proprietary".'),
123
+ required: true,
124
+ default: metadata.data['license'],
125
+ },
126
+ {
127
+ name: 'summary',
128
+ question: _('How would you describe this module in a single sentence?'),
129
+ help: _('To help other Puppet users understand what the module does.'),
130
+ required: true,
131
+ default: metadata.data['summary'],
132
+ },
133
+ {
134
+ name: 'source',
135
+ question: _("Where is this modules's source code repository?"),
136
+ help: _('Usually a GitHub URL'),
137
+ required: true,
138
+ default: metadata.data['source'],
139
+ },
140
+ {
141
+ name: 'project_page',
142
+ question: _('Where can others go to learn more about this module?'),
143
+ help: _('A web site that offers full information about your module.'),
144
+ default: metadata.data['project_page'],
145
+ },
146
+ {
147
+ name: 'issues_url',
148
+ question: _('Where can others go to file issues about this module?'),
149
+ help: _('A web site with a public bug tracker for your module.'),
150
+ default: metadata.data['issues_url'],
151
+ },
152
+ ]
153
+
154
+ prompt = TTY::Prompt.new
155
+
156
+ interview = PDK::CLI::Util::Interview.new(prompt)
157
+
158
+ questions.reject! { |q| q[:name] == 'license' } if opts.key?(:license)
159
+
160
+ interview.add_questions(questions)
94
161
 
95
- begin
96
- puts "\n" + _('Puppet uses Semantic Versioning (semver.org) to version modules.')
97
- module_version = PDK::CLI::Input.get(_('What version is this module?'), metadata.data['version'])
98
- metadata.update!('version' => module_version)
99
- rescue StandardError => e
100
- PDK.logger.error(_("We're sorry, we could not parse that as a Semantic Version: %{message}") % { message: e.message })
101
- retry
102
- end
162
+ puts _(
163
+ "\nWe need to create a metadata.json file for this module, so we're going to ask you %{count} quick questions.\n" \
164
+ "If the question is not applicable to this module, just leave the answer blank.\n\n",
165
+ ) % { count: interview.num_questions }
103
166
 
104
- puts ''
105
- module_author = PDK::CLI::Input.get(_('Who wrote this module?'), metadata.data['author'])
106
- metadata.update!('author' => module_author)
167
+ answers = interview.run
107
168
 
108
- unless opts.key?(:license)
109
- puts ''
110
- module_license = PDK::CLI::Input.get(_('What license does this module code fall under?'), metadata.data['license'])
111
- metadata.update!('license' => module_license)
169
+ if answers.nil?
170
+ puts _('Interview cancelled, aborting...')
171
+ exit 0
112
172
  end
113
173
 
114
- puts ''
115
- module_summary = PDK::CLI::Input.get(_('How would you describe this module in a single sentence?'), metadata.data['summary'])
116
- metadata.update!('summary' => module_summary)
174
+ answers['name'] = "#{answers['name']}-#{opts[:name]}"
175
+ metadata.update!(answers)
117
176
 
118
- puts ''
119
- module_source = PDK::CLI::Input.get(_("Where is this module's source code repository?"), metadata.data['source'])
120
- metadata.update!('source' => module_source)
121
-
122
- puts ''
123
- module_page = PDK::CLI::Input.get(_('Where can others go to learn more about this module?'), metadata.data['project_page'])
124
- metadata.update!('project_page' => module_page)
125
-
126
- puts ''
127
- module_issues = PDK::CLI::Input.get(_('Where can others go to file issues about this module?'), metadata.data['issues_url'])
128
- metadata.update!('issues_url' => module_issues)
129
-
130
- puts
177
+ puts '-' * 40
178
+ puts _('SUMMARY')
131
179
  puts '-' * 40
132
180
  puts metadata.to_json
133
181
  puts '-' * 40
134
182
  puts
135
183
 
136
- unless PDK::CLI::Input.get(_('About to generate this module; continue?'), 'Y') =~ %r{^y(es)?$}i # rubocop:disable Style/GuardClause
184
+ unless prompt.yes?(_('About to generate this module; continue?')) # rubocop:disable Style/GuardClause
137
185
  puts _('Aborting...')
138
186
  exit 0
139
187
  end