puppet-check 2.2.2 → 2.3.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a8202ec2f014dfda495943251a944a05a2f02dd411d4432d4ae2fa670090147f
4
- data.tar.gz: 79926aa5d6f7a5b4abdf5141a110d08f2dd2d678439b89a3a4193ba957b3eb36
3
+ metadata.gz: d04c10fa6bc7d10b70113b7d93ab7be0d0f5cc1e65e0976e2e40e3edcc561ff8
4
+ data.tar.gz: 5e0fc0e541f9aa21bc65015cc0bc5958a8d44b3aaf36b8d1ce5e69f3942b9221
5
5
  SHA512:
6
- metadata.gz: 5881b391a02f1f7afd9d902e16c578fa02128511275e9c670767ec2c1ebcce263a1137f36244c1e8bb118da057719f955727df577a6df421d66966cb39d3d054
7
- data.tar.gz: d74c947acf7b79cbc0f82ba7280617495eb2bfd7574e6e22791b59bffa8a9fa4228aec7194fd3c8c9b77e99993a10dc9886074e43c3166da69b2d0ccccd1a052
6
+ metadata.gz: d762b4386dc42703ffea264872629684f35a98ddbf69b2eb3fb82f9039a614e146a9a6d6961c51086c33dffd80e8d192a973f4025adc355d355d1d20e442d039
7
+ data.tar.gz: 90cea3c4ebc6a20d48793276f3563f7d82e8067b94ab3f3ff0c6e51bbbe8de00333c34b157baec92ed919d110eb9eb29065d90e04c01c1e7a287ae2ce3ed78fc
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ ### 2.3.1
2
+ - No input target paths now defaults to current working directory instead of error.
3
+ - Additionally check `Vagrantfile` and `gemspec` files.
4
+ - Fix and improve behavior for when optional dependency `octocatalog-diff` is absent.
5
+
6
+ ### 2.3.0
7
+ - Minimum Ruby version increased to 2.7.
8
+ - Support Puppet 8.
9
+ - Upgrade EYAML validation functionality from experimental to beta.
10
+ - Code execution optimization.
11
+
1
12
  ### 2.2.2
2
13
  - Workaround Ruby passbyref issue mutating an immutable.
3
14
 
data/README.md CHANGED
@@ -1,7 +1,4 @@
1
1
  # Puppet Check
2
- [![Build Status](https://travis-ci.com/mschuchard/puppet-check.svg?branch=master)](https://travis-ci.com/mschuchard/puppet-check)
3
- [![CircleCI](https://circleci.com/gh/mschuchard/puppet-check.svg?style=svg)](https://circleci.com/gh/mschuchard/puppet-check)
4
-
5
2
  - [Description](#description)
6
3
  - [Usage](#usage)
7
4
  - [CLI](#cli)
@@ -16,7 +13,7 @@
16
13
  ## Description
17
14
  Puppet Check is a gem that provides a comprehensive, streamlined, and efficient analysis of the syntax, style, and validity of your entire Puppet code and data.
18
15
 
19
- **IMPORTANT**: The current support for encrypted yaml validation is experimental. The code is blocked in the current release (the files will continue to be treated as unrecognized) and will be unblocked when the feature is finished in a future version.
16
+ **IMPORTANT**: The current support for encrypted yaml validation is experimental and should be considered a beta feature as of 2.3.0.
20
17
 
21
18
  ### Former Method for Code and Data Checks
22
19
  ![Old](https://raw.githubusercontent.com/mschuchard/puppet-check/master/images/puppetcheck_old.png)
@@ -6,7 +6,9 @@ class PuppetCheck::CLI
6
6
  def self.run(args)
7
7
  # gather the user arguments
8
8
  settings = parse(args)
9
- raise 'puppet-check: no file paths specified; try using --help' if args.empty?
9
+
10
+ # target cwd if no paths input as variadic
11
+ args = [Dir.pwd] if args.empty?
10
12
 
11
13
  # run PuppetCheck with specified paths
12
14
  PuppetCheck.new.run(settings, args)
@@ -29,7 +31,9 @@ class PuppetCheck::CLI
29
31
 
30
32
  # base options
31
33
  opts.on('--version', 'Display the current version.') do
32
- puts 'puppet-check 2.2.2'
34
+ require 'rubygems'
35
+
36
+ puts Gem::Specification.load("#{File.dirname(__FILE__)}/../../puppet-check.gemspec").version
33
37
  exit 0
34
38
  end
35
39
 
@@ -43,27 +43,30 @@ class DataParser
43
43
  x509 = OpenSSL::X509::Certificate.new(File.read(public))
44
44
 
45
45
  files.each do |file|
46
- # grab all encoded portions of the eyaml
46
+ # check encoded yaml syntax
47
+ parsed = YAML.load_file(file)
47
48
 
48
- # decrypt the encoded portions
49
- decrypted = OpenSSL::PKCS7.new(File.read(file)).decrypt(rsa, x509)
49
+ # extract encoded values
50
+ # ENC[PKCS7]
50
51
 
51
- # insert decrypted portions back into eyaml (pass into loader below)
52
+ # decrypt the encoded yaml
53
+ # decrypted = OpenSSL::PKCS7.new(File.read(file)).decrypt(rsa, x509)
52
54
 
53
- # check yaml syntax
54
- begin
55
- parsed = YAML.load_file(decrypted)
56
- rescue StandardError => err
57
- PuppetCheck.files[:errors][file] = err.to_s.gsub("(#{file}): ", '').split("\n")
58
- else
59
- warnings = []
60
-
61
- # perform some rudimentary hiera checks if data exists and is hieradata
62
- warnings = hiera(parsed, file) if parsed
63
-
64
- next PuppetCheck.files[:warnings][file] = warnings unless warnings.empty?
65
- PuppetCheck.files[:clean].push(file.to_s)
66
- end
55
+ # check decoded eyaml syntax
56
+ # decoded = YAML.safe_load(decrypted)
57
+
58
+ # merge data hashes
59
+ # parsed = merge(parsed, decoded)
60
+ rescue StandardError => err
61
+ PuppetCheck.files[:errors][file] = err.to_s.gsub("(#{file}): ", '').split("\n")
62
+ else
63
+ warnings = []
64
+
65
+ # perform some rudimentary hiera checks if data exists and is hieradata
66
+ warnings = hiera(parsed, file) if parsed
67
+
68
+ next PuppetCheck.files[:warnings][file] = warnings unless warnings.empty?
69
+ PuppetCheck.files[:clean].push(file.to_s)
67
70
  end
68
71
  end
69
72
 
@@ -79,127 +82,125 @@ class DataParser
79
82
 
80
83
  files.each do |file|
81
84
  # check json syntax
82
- begin
83
- parsed = JSON.parse(File.read(file))
84
- rescue JSON::ParserError => err
85
- PuppetCheck.files[:errors][file] = err.to_s.lines.first.strip.split("\n")
86
- else
87
- warnings = []
88
-
89
- # check metadata.json
90
- if File.basename(file) == 'metadata.json'
91
- # metadata-json-lint has issues and is essentially no longer maintained, so here is an improved and leaner version of it
92
- require 'rubygems/util/licenses'
93
-
94
- # check for errors
95
- errors = []
96
-
97
- # check for required keys
98
- REQUIRED_KEYS.each do |key|
99
- errors.push("Required field '#{key}' not found.") unless parsed.key?(key)
100
- end
85
+ parsed = JSON.parse(File.read(file))
86
+ rescue JSON::ParserError => err
87
+ PuppetCheck.files[:errors][file] = err.to_s.lines.first.strip.split("\n")
88
+ else
89
+ warnings = []
101
90
 
102
- # check requirements and dependencies keys
103
- REQ_DEP_KEYS.each do |key|
104
- # skip if key is missing or value is an empty string, array, or hash
105
- next if !parsed.key?(key) || parsed[key].empty?
91
+ # check metadata.json
92
+ if File.basename(file) == 'metadata.json'
93
+ # metadata-json-lint has issues and is essentially no longer maintained, so here is an improved and leaner version of it
94
+ require 'rubygems/util/licenses'
106
95
 
107
- # check that dependencies and requirements are an array of hashes
108
- next errors.push("Field '#{key}' is not an array of hashes.") unless (parsed[key].is_a? Array) && (parsed[key][0].is_a? Hash)
96
+ # check for errors
97
+ errors = []
109
98
 
110
- # check dependencies and requirements values
111
- names = []
112
- parsed[key].each do |req_dep|
113
- # check for duplicate dependencies and requirements
114
- name = req_dep['name']
115
- next errors.push("Duplicate #{key} on #{name}.") if names.include?(name)
116
- names << name
99
+ # check for required keys
100
+ REQUIRED_KEYS.each do |key|
101
+ errors.push("Required field '#{key}' not found.") unless parsed.key?(key)
102
+ end
103
+
104
+ # check requirements and dependencies keys
105
+ REQ_DEP_KEYS.each do |key|
106
+ # skip if key is missing or value is an empty string, array, or hash
107
+ next if !parsed.key?(key) || parsed[key].empty?
108
+
109
+ # check that dependencies and requirements are an array of hashes
110
+ next errors.push("Field '#{key}' is not an array of hashes.") unless (parsed[key].is_a? Array) && (parsed[key][0].is_a? Hash)
117
111
 
118
- # warn and skip if key is missing
119
- next warnings.push("'#{req_dep['name']}' is missing a 'version_requirement' key.") if req_dep['version_requirement'].nil?
112
+ # check dependencies and requirements values
113
+ names = []
114
+ parsed[key].each do |req_dep|
115
+ # check for duplicate dependencies and requirements
116
+ name = req_dep['name']
117
+ next errors.push("Duplicate #{key} on #{name}.") if names.include?(name)
118
+ names << name
120
119
 
121
- # warn and skip if no upper bound
122
- next warnings.push("'#{req_dep['name']}' is missing an upper bound.") unless req_dep['version_requirement'].include?('<')
120
+ # warn and skip if key is missing
121
+ next warnings.push("'#{req_dep['name']}' is missing a 'version_requirement' key.") if req_dep['version_requirement'].nil?
123
122
 
124
- # check for semantic versioning
125
- if key == 'dependencies' && req_dep['version_requirement'] !~ /\d+\.\d+\.\d+.*\d+\.\d+\.\d+/
126
- warnings.push("'#{req_dep['name']}' has non-semantic versioning in its 'version_requirement' key.")
127
- end
123
+ # warn and skip if no upper bound
124
+ next warnings.push("'#{req_dep['name']}' is missing an upper bound.") unless req_dep['version_requirement'].include?('<')
125
+
126
+ # check for semantic versioning
127
+ if key == 'dependencies' && req_dep['version_requirement'] !~ /\d+\.\d+\.\d+.*\d+\.\d+\.\d+/
128
+ warnings.push("'#{req_dep['name']}' has non-semantic versioning in its 'version_requirement' key.")
128
129
  end
129
130
  end
131
+ end
130
132
 
131
- # check for deprecated fields
132
- DEPRECATED_KEYS.each do |key|
133
- errors.push("Deprecated field '#{key}' found.") if parsed.key?(key)
134
- end
133
+ # check for deprecated fields
134
+ DEPRECATED_KEYS.each do |key|
135
+ errors.push("Deprecated field '#{key}' found.") if parsed.key?(key)
136
+ end
135
137
 
136
- # check for summary under 144 character
137
- errors.push('Summary exceeds 144 characters.') if parsed.key?('summary') && parsed['summary'].size > 144
138
+ # check for summary under 144 character
139
+ errors.push('Summary exceeds 144 characters.') if parsed.key?('summary') && parsed['summary'].size > 144
138
140
 
139
- next PuppetCheck.files[:errors][file] = errors unless errors.empty?
141
+ next PuppetCheck.files[:errors][file] = errors unless errors.empty?
140
142
 
141
- # check for warnings
142
- # check for operatingsystem_support hash array
143
- if parsed.key?('operatingsystem_support')
144
- # check if operatingsystem_support array is actually empty
145
- if !(parsed['operatingsystem_support'].is_a? Array) || parsed['operatingsystem_support'].empty? || (!parsed['operatingsystem_support'].empty? && !(parsed['operatingsystem_support'][0].is_a? Hash))
146
- warnings.push('Recommended field \'operatingsystem\' not found.')
147
- warnings.push('Recommended field \'operatingsystemrelease\' not found.')
143
+ # check for warnings
144
+ # check for operatingsystem_support hash array
145
+ if parsed.key?('operatingsystem_support')
146
+ # check if operatingsystem_support array is actually empty
147
+ if !(parsed['operatingsystem_support'].is_a? Array) || parsed['operatingsystem_support'].empty? || (!parsed['operatingsystem_support'].empty? && !(parsed['operatingsystem_support'][0].is_a? Hash))
148
+ warnings.push('Recommended field \'operatingsystem\' not found.')
149
+ warnings.push('Recommended field \'operatingsystemrelease\' not found.')
150
+ else
151
+ # check for operatingsystem string
152
+ if parsed['operatingsystem_support'][0].key?('operatingsystem')
153
+ warnings.push('Field \'operatingsystem\' is not a string.') unless parsed['operatingsystem_support'][0]['operatingsystem'].is_a? String
148
154
  else
149
- # check for operatingsystem string
150
- if parsed['operatingsystem_support'][0].key?('operatingsystem')
151
- warnings.push('Field \'operatingsystem\' is not a string.') unless parsed['operatingsystem_support'][0]['operatingsystem'].is_a? String
152
- else
153
- warnings.push('Recommended field \'operatingsystem\' not found.')
154
- end
155
-
156
- # check for operatingsystemrelease string array
157
- if parsed['operatingsystem_support'][0].key?('operatingsystemrelease')
158
- warnings.push('Field \'operatingsystemrelease\' is not a string array.') unless parsed['operatingsystem_support'][0]['operatingsystemrelease'][0].is_a? String
159
- else
160
- warnings.push('Recommended field \'operatingsystemrelease\' not found.')
161
- end
155
+ warnings.push('Recommended field \'operatingsystem\' not found.')
162
156
  end
163
- else
164
- warnings.push('Recommended field \'operatingsystem_support\' not found.')
165
- end
166
157
 
167
- # check for spdx license
168
- if parsed.key?('license') && !Gem::Licenses.match?(parsed['license']) && parsed['license'] !~ /[pP]roprietary/
169
- warnings.push("License identifier '#{parsed['license']}' is not in the SPDX list: http://spdx.org/licenses/")
170
- end
171
- # assume this is task metadata if it has this key
172
- elsif parsed.key?('description')
173
- # check that description is a string
174
- warnings.push('description value is not a String') unless parsed['description'].is_a?(String)
175
- # check that input_method is one of three possible values
176
- if parsed.key?('input_method')
177
- if parsed['input_method'].is_a?(String)
178
- warnings.push('input_method value is not one of environment, stdin, or powershell') unless TASK_INPUTS.include?(parsed['input_method'])
158
+ # check for operatingsystemrelease string array
159
+ if parsed['operatingsystem_support'][0].key?('operatingsystemrelease')
160
+ warnings.push('Field \'operatingsystemrelease\' is not a string array.') unless parsed['operatingsystem_support'][0]['operatingsystemrelease'][0].is_a? String
179
161
  else
180
- warnings.push('input_method value is not a String')
162
+ warnings.push('Recommended field \'operatingsystemrelease\' not found.')
181
163
  end
182
164
  end
183
- # check that parameters is a hash
184
- if parsed.key?('parameters') && !parsed['parameters'].is_a?(Hash)
185
- warnings.push('parameters value is not a Hash')
186
- end
187
- # check that puppet_task_version is an integer
188
- if parsed.key?('puppet_task_version') && !parsed['puppet_task_version'].is_a?(Integer)
189
- warnings.push('puppet_task_version value is not an Integer')
190
- end
191
- # check that supports_noop is a boolean
192
- if parsed.key?('supports_noop') && !(parsed['supports_noop'].is_a?(TrueClass) || parsed['supports_noop'].is_a?(FalseClass))
193
- warnings.push('supports_noop value is not a Boolean')
165
+ else
166
+ warnings.push('Recommended field \'operatingsystem_support\' not found.')
167
+ end
168
+
169
+ # check for spdx license
170
+ if parsed.key?('license') && !Gem::Licenses.match?(parsed['license']) && parsed['license'] !~ /[pP]roprietary/
171
+ warnings.push("License identifier '#{parsed['license']}' is not in the SPDX list: http://spdx.org/licenses/")
172
+ end
173
+ # assume this is task metadata if it has this key
174
+ elsif parsed.key?('description')
175
+ # check that description is a string
176
+ warnings.push('description value is not a String') unless parsed['description'].is_a?(String)
177
+ # check that input_method is one of three possible values
178
+ if parsed.key?('input_method')
179
+ if parsed['input_method'].is_a?(String)
180
+ warnings.push('input_method value is not one of environment, stdin, or powershell') unless TASK_INPUTS.include?(parsed['input_method'])
181
+ else
182
+ warnings.push('input_method value is not a String')
194
183
  end
195
- # assume this is hieradata and ensure it is non-empty
196
- elsif parsed
197
- # perform some rudimentary hiera checks if data exists
198
- warnings = hiera(parsed, file)
199
184
  end
200
- next PuppetCheck.files[:warnings][file] = warnings unless warnings.empty?
201
- PuppetCheck.files[:clean].push(file.to_s)
185
+ # check that parameters is a hash
186
+ if parsed.key?('parameters') && !parsed['parameters'].is_a?(Hash)
187
+ warnings.push('parameters value is not a Hash')
188
+ end
189
+ # check that puppet_task_version is an integer
190
+ if parsed.key?('puppet_task_version') && !parsed['puppet_task_version'].is_a?(Integer)
191
+ warnings.push('puppet_task_version value is not an Integer')
192
+ end
193
+ # check that supports_noop is a boolean
194
+ if parsed.key?('supports_noop') && !(parsed['supports_noop'].is_a?(TrueClass) || parsed['supports_noop'].is_a?(FalseClass))
195
+ warnings.push('supports_noop value is not a Boolean')
196
+ end
197
+ # assume this is hieradata and ensure it is non-empty
198
+ elsif parsed
199
+ # perform some rudimentary hiera checks if data exists
200
+ warnings = hiera(parsed, file)
202
201
  end
202
+ next PuppetCheck.files[:warnings][file] = warnings unless warnings.empty?
203
+ PuppetCheck.files[:clean].push(file.to_s)
203
204
  end
204
205
  end
205
206
 
@@ -219,7 +220,7 @@ class DataParser
219
220
  end
220
221
 
221
222
  # check that '---' does not show up more than once in the hieradata
222
- warnings.push('The string --- appears more than once in this data and Hiera may fail to parse it correctly.') if File.read(file).scan(/---/).count >= 2
223
+ warnings.push('The string --- appears more than once in this data and Hiera may fail to parse it correctly.') if File.read(file).scan('---').count >= 2
223
224
 
224
225
  warnings
225
226
  end
@@ -2,6 +2,13 @@ require_relative '../puppet_check'
2
2
 
3
3
  # class to handle outputting diagnostic results in desired format
4
4
  class OutputResults
5
+ HEADER = {
6
+ errors: "\033[31mThe following files have errors:\033[0m\n",
7
+ warnings: "\033[33mThe following files have warnings:\033[0m\n",
8
+ clean: "\033[32mThe following files have no errors or warnings:\033[0m\n-- ",
9
+ ignored: "\033[36mThe following files have unrecognized formats and therefore were not processed:\033[0m\n-- "
10
+ }.freeze
11
+
5
12
  # output the results in various formats
6
13
  def self.run(files, format)
7
14
  # remove empty entries
@@ -28,24 +35,26 @@ class OutputResults
28
35
  def self.text(files)
29
36
  private_class_method :method
30
37
 
31
- # errors
32
- if files.key?(:errors)
33
- puts "\033[31mThe following files have errors:\033[0m"
34
- files[:errors].each { |file, errors| puts "-- #{file}:\n#{errors.join("\n")}" }
35
- end
36
- # warnings
37
- if files.key?(:warnings)
38
- puts "\n\033[33mThe following files have warnings:\033[0m"
39
- files[:warnings].each { |file, warnings| puts "-- #{file}:\n#{warnings.join("\n")}" }
40
- end
41
- # cleans
42
- if files.key?(:clean)
43
- print "\n\033[32mThe following files have no errors or warnings:\033[0m\n-- "
44
- puts files[:clean].join("\n-- ")
38
+ # output text for each of four file categories
39
+ %i[errors warnings clean ignored].each do |category|
40
+ # immediately return if category is empty
41
+ next unless files.key?(category)
42
+
43
+ # display heading, files, and file messages per category for text formatting
44
+ category_files = files[category]
45
+
46
+ # display category heading
47
+ print HEADER[category]
48
+
49
+ # display files and optionally messages
50
+ case category_files
51
+ when Hash then category_files.each { |file, messages| puts "-- #{file}:\n#{messages.join("\n")}" }
52
+ when Array then puts category_files.join("\n-- ")
53
+ else raise "puppet-check: The files category was of unexpected type #{category_files.class}. Please file an issue with this log message, category heading, and information about the parsed files."
54
+ end
55
+
56
+ # newline between categories for easier visual parsing
57
+ puts ''
45
58
  end
46
- # ignores
47
- return unless files.key?(:ignored)
48
- print "\n\033[36mThe following files have unrecognized formats and therefore were not processed:\033[0m\n-- "
49
- puts files[:ignored].join("\n-- ")
50
59
  end
51
60
  end
@@ -10,6 +10,13 @@ class PuppetParser
10
10
  # prepare the Puppet settings for the error checking
11
11
  Puppet.initialize_settings unless Puppet.settings.app_defaults_initialized?
12
12
 
13
+ # prepare the PuppetLint object for style checks
14
+ if style
15
+ require 'puppet-lint'
16
+ require 'puppet-lint/optparser'
17
+ puppet_lint = PuppetLint.new
18
+ end
19
+
13
20
  files.each do |file|
14
21
  # setup error logging and collection; warnings logged for all versions, but errors for only puppet < 6.5
15
22
  errors = []
@@ -48,9 +55,6 @@ class PuppetParser
48
55
 
49
56
  # check puppet style
50
57
  if style
51
- require 'puppet-lint'
52
- require 'puppet-lint/optparser'
53
-
54
58
  # check for invalid arguments to PuppetLint
55
59
  begin
56
60
  PuppetLint::OptParser.build.parse!(pl_args.clone)
@@ -58,8 +62,7 @@ class PuppetParser
58
62
  raise "puppet-lint: invalid option supplied among #{pl_args.join(' ')}"
59
63
  end
60
64
 
61
- # prepare the PuppetLint object for style checks
62
- puppet_lint = PuppetLint.new
65
+ # execute puppet-lint style checks
63
66
  puppet_lint.file = file
64
67
  puppet_lint.run
65
68
 
@@ -1,29 +1,34 @@
1
- # temporarily supress warning messages for octocatalog-diff redefining puppet constants and then reactivate
2
- $VERBOSE = nil
3
- require 'octocatalog-diff'
4
- $VERBOSE = false
1
+ begin
2
+ # temporarily supress warning messages for octocatalog-diff redefining puppet constants and then reactivate
3
+ $VERBOSE = nil
4
+ require 'octocatalog-diff'
5
+ $VERBOSE = false
5
6
 
6
- # executes smoke and regression tests on catalogs
7
- class RegressionCheck
8
- # smoke testing
9
- def self.smoke(interface_nodes, octoconfig)
10
- options = config(octoconfig)
11
- nodes = options.key?(:node) ? [options[:node]] : interface_nodes
12
- nodes.each do |node|
13
- options[:node] = node
14
- OctocatalogDiff::API::V1.catalog(options)
7
+ # executes smoke and regression tests on catalogs
8
+ class RegressionCheck
9
+ # smoke testing
10
+ def self.smoke(interface_nodes, octoconfig)
11
+ options = config(octoconfig)
12
+ nodes = options.key?(:node) ? [options[:node]] : interface_nodes
13
+ nodes.each do |node|
14
+ options[:node] = node
15
+ OctocatalogDiff::API::V1.catalog(options)
16
+ end
15
17
  end
16
- end
17
18
 
18
- # regression testing
19
- # def self.regression(nodes, octoconfig)
20
- # options = RegressionCheck.config(octoconfig)
21
- # nodes.each { |node| stuff }
22
- # end
19
+ # regression testing
20
+ # def self.regression(nodes, octoconfig)
21
+ # options = RegressionCheck.config(octoconfig)
22
+ # nodes.each { |node| stuff }
23
+ # end
23
24
 
24
- # config file loading
25
- def self.config(octoconfig)
26
- private_class_method :method
27
- OctocatalogDiff::API::V1.config(filename: octoconfig)
25
+ # config file loading
26
+ def self.config(octoconfig)
27
+ private_class_method :method
28
+ OctocatalogDiff::API::V1.config(filename: octoconfig)
29
+ end
28
30
  end
31
+ rescue LoadError
32
+ warn 'puppet-check: octocatalog-diff is not installed, and therefore the regression checks will be skipped'
33
+ $VERBOSE = false
29
34
  end
@@ -5,26 +5,30 @@ require_relative 'utils'
5
5
  class RubyParser
6
6
  # checks ruby (.rb)
7
7
  def self.ruby(files, style, rc_args)
8
+ # prepare rubocop object for style checks
9
+ if style
10
+ require 'json'
11
+ require 'rubocop'
12
+ require 'reek'
13
+ require 'reek/cli/application'
14
+
15
+ rubocop_cli = RuboCop::CLI.new
16
+ end
17
+
8
18
  files.each do |file|
9
19
  # check ruby syntax
10
- # prevents ruby code from actually executing
11
- catch(:good) { instance_eval("BEGIN {throw :good}; #{File.read(file)}", file) }
20
+ # prevents ruby code from actually executing the input ruby file
21
+ catch(:good) { instance_eval("BEGIN {throw :good}; #{File.read(file)} # BEGIN {throw :good}; ruby_file_content", file) }
12
22
  rescue ScriptError, StandardError => err
13
23
  PuppetCheck.files[:errors][file] = err.to_s.gsub("#{file}:", '').split("\n")
14
24
  else
15
25
  # check ruby style
16
26
  if style
17
27
  # check RuboCop and parse warnings' JSON output
18
- require 'json'
19
- require 'rubocop'
20
-
21
- rubocop_warnings = Utils.capture_stdout { RuboCop::CLI.new.run(rc_args + ['--enable-pending-cops', '--require', 'rubocop-performance', '--format', 'json', file]) }
28
+ rubocop_warnings = Utils.capture_stdout { rubocop_cli.run(rc_args + ['--enable-pending-cops', '--require', 'rubocop-performance', '--format', 'json', file]) }
22
29
  rubocop_offenses = JSON.parse(rubocop_warnings)['files'][0]['offenses'].map { |warning| "#{warning['location']['line']}:#{warning['location']['column']} #{warning['message']}" }
23
30
 
24
31
  # check Reek and parse warnings' JSON output
25
- require 'reek'
26
- require 'reek/cli/application'
27
-
28
32
  reek_warnings = Utils.capture_stdout { Reek::CLI::Application.new(['-f', 'json', file]).execute }
29
33
  reek_offenses = JSON.parse(reek_warnings).map { |warning| "#{warning['lines'].join(',')}: #{warning['context']} #{warning['message']}" }
30
34
 
@@ -65,24 +69,25 @@ class RubyParser
65
69
  def self.librarian(files, style, rc_args)
66
70
  # efficient var assignment prior to iterator
67
71
  if style
72
+ require 'json'
73
+ require 'rubocop'
74
+
75
+ rubocop_cli = RuboCop::CLI.new
76
+
68
77
  # RuboCop is grumpy about non-snake_case filenames so disable the FileName check
69
78
  rc_args.include?('--except') ? rc_args[rc_args.index('--except') + 1] = "#{rc_args[rc_args.index('--except') + 1]},Naming/FileName" : rc_args.push('--except', 'Naming/FileName')
70
79
  end
71
80
 
72
81
  files.each do |file|
73
82
  # check librarian puppet syntax
74
- # prevents ruby code from actually executing
75
- catch(:good) { instance_eval("BEGIN {throw :good}; #{File.read(file)}", file) }
83
+ # prevents ruby code from actually executing the input ruby file
84
+ catch(:good) { instance_eval("BEGIN {throw :good}; #{File.read(file)} # BEGIN {throw :good}; ruby_file_content", file) }
76
85
  rescue SyntaxError, LoadError, ArgumentError => err
77
86
  PuppetCheck.files[:errors][file] = err.to_s.gsub("#{file}:", '').split("\n")
78
87
  # check librarian puppet style
79
88
  else
80
89
  if style
81
- # check Rubocop
82
- require 'json'
83
- require 'rubocop'
84
-
85
- warnings = Utils.capture_stdout { RuboCop::CLI.new.run(rc_args + ['--enable-pending-cops', '--require', 'rubocop-performance', '--format', 'json', file]) }
90
+ warnings = Utils.capture_stdout { rubocop_cli.run(rc_args + ['--enable-pending-cops', '--require', 'rubocop-performance', '--format', 'json', file]) }
86
91
  offenses = JSON.parse(warnings)['files'][0]['offenses'].map { |warning| "#{warning['location']['line']}:#{warning['location']['column']} #{warning['message']}" }
87
92
 
88
93
  # collect style warnings