foodcritic 7.0.1 → 7.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
- require 'set'
1
+ require "set"
2
2
 
3
3
  module FoodCritic
4
4
  # Default output showing a summary view.
@@ -62,10 +62,10 @@ module FoodCritic
62
62
 
63
63
  # Display any relevant lines
64
64
  if warn_lines.include? file.lineno
65
- print '%4i|' % file.lineno
65
+ print "%4i|" % file.lineno
66
66
  print_line.call line.chomp
67
67
  elsif not context_warns.empty?
68
- print '%4i|' % file.lineno
68
+ print "%4i|" % file.lineno
69
69
  puts line.chomp
70
70
  end
71
71
  end
@@ -106,8 +106,8 @@ module FoodCritic
106
106
  return
107
107
  end
108
108
 
109
- colors = %w(black red green yellow blue magenta cyan white)
110
- attrs = %w(reset bold dim underscore blink reverse hidden)
109
+ colors = %w{black red green yellow blue magenta cyan white}
110
+ attrs = %w{reset bold dim underscore blink reverse hidden}
111
111
  escape = "\033[%sm"
112
112
  fmt = []
113
113
  fmt << 30 + colors.index(fg.to_s) if fg
@@ -1,5 +1,5 @@
1
- require 'rake'
2
- require 'rake/tasklib'
1
+ require "rake"
2
+ require "rake/tasklib"
3
3
 
4
4
  module FoodCritic
5
5
  module Rake
@@ -14,9 +14,8 @@ module FoodCritic
14
14
  define
15
15
  end
16
16
 
17
-
18
17
  def define
19
- desc 'Lint Chef cookbooks' unless ::Rake.application.last_description
18
+ desc "Lint Chef cookbooks" unless ::Rake.application.last_description
20
19
  task(name) do
21
20
  puts "Starting Foodcritic linting..."
22
21
  result = FoodCritic::Linter.new.check(default_options.merge(options))
@@ -28,13 +27,14 @@ module FoodCritic
28
27
  end
29
28
 
30
29
  private
30
+
31
31
  def default_options
32
32
  {
33
- fail_tags: ['correctness'], # differs to default cmd-line behaviour
33
+ fail_tags: ["correctness"], # differs to default cmd-line behaviour
34
34
  cookbook_paths: files,
35
- exclude_paths: ['test/**/*', 'spec/**/*', 'features/**/*'],
35
+ exclude_paths: ["test/**/*", "spec/**/*", "features/**/*"],
36
36
  context: false,
37
- chef_version: FoodCritic::Linter::DEFAULT_CHEF_VERSION
37
+ chef_version: FoodCritic::Linter::DEFAULT_CHEF_VERSION,
38
38
  }
39
39
  end
40
40
  end
@@ -9,16 +9,16 @@
9
9
  # query only, as any nodes returned from a `recipe` block will be converted
10
10
  # into warnings.
11
11
 
12
- rule 'FC001',
13
- 'Use strings in preference to symbols to access node attributes' do
14
- tags %w(style attributes)
12
+ rule "FC001",
13
+ "Use strings in preference to symbols to access node attributes" do
14
+ tags %w{style attributes}
15
15
  recipe do |ast|
16
16
  attribute_access(ast, type: :symbol)
17
17
  end
18
18
  end
19
19
 
20
- rule 'FC002', 'Avoid string interpolation where not required' do
21
- tags %w(style strings)
20
+ rule "FC002", "Avoid string interpolation where not required" do
21
+ tags %w{style strings}
22
22
  recipe do |ast|
23
23
  ast.xpath(%q{//*[self::string_literal | self::assoc_new]/string_add[
24
24
  count(descendant::string_embexpr) = 1 and
@@ -26,10 +26,10 @@ rule 'FC002', 'Avoid string interpolation where not required' do
26
26
  end
27
27
  end
28
28
 
29
- rule 'FC003',
30
- 'Check whether you are running with chef server before using'\
31
- ' server-specific features' do
32
- tags %w(portability solo)
29
+ rule "FC003",
30
+ "Check whether you are running with chef server before using"\
31
+ " server-specific features" do
32
+ tags %w{portability solo}
33
33
  recipe do |ast, filename|
34
34
  unless checks_for_chef_solo?(ast) || chef_solo_search_supported?(filename)
35
35
  searches(ast)
@@ -37,32 +37,32 @@ rule 'FC003',
37
37
  end
38
38
  end
39
39
 
40
- rule 'FC004', 'Use a service resource to start and stop services' do
41
- tags %w(style services)
40
+ rule "FC004", "Use a service resource to start and stop services" do
41
+ tags %w{style services}
42
42
  recipe do |ast|
43
- find_resources(ast, type: 'execute').find_all do |cmd|
44
- cmd_str = (resource_attribute(cmd, 'command') || resource_name(cmd)).to_s
45
- (cmd_str.include?('/etc/init.d') || ['service ', '/sbin/service ',
46
- 'start ', 'stop ', 'invoke-rc.d '].any? do |service_cmd|
47
- cmd_str.start_with?(service_cmd)
48
- end) && %w(start stop restart reload).any? { |a| cmd_str.include?(a) }
43
+ find_resources(ast, type: "execute").find_all do |cmd|
44
+ cmd_str = (resource_attribute(cmd, "command") || resource_name(cmd)).to_s
45
+ (cmd_str.include?("/etc/init.d") || ["service ", "/sbin/service ",
46
+ "start ", "stop ", "invoke-rc.d "].any? do |service_cmd|
47
+ cmd_str.start_with?(service_cmd)
48
+ end) && %w{start stop restart reload}.any? { |a| cmd_str.include?(a) }
49
49
  end
50
50
  end
51
51
  end
52
52
 
53
- rule 'FC005', 'Avoid repetition of resource declarations' do
54
- tags %w(style)
53
+ rule "FC005", "Avoid repetition of resource declarations" do
54
+ tags %w{style}
55
55
  recipe do |ast|
56
56
  resources = find_resources(ast).map do |res|
57
57
  resource_attributes(res).merge({ type: resource_type(res),
58
- ast: res })
58
+ ast: res })
59
59
  end.chunk do |res|
60
60
  res[:type] +
61
- res[:ast].xpath("ancestor::*[self::if | self::unless | self::elsif |
62
- self::else | self::when | self::method_add_block/call][position() = 1]/
63
- descendant::pos[position() = 1]").to_s +
64
- res[:ast].xpath("ancestor::method_add_block/command[
65
- ident/@value='action']/args_add_block/descendant::ident/@value").to_s
61
+ res[:ast].xpath("ancestor::*[self::if | self::unless | self::elsif |
62
+ self::else | self::when | self::method_add_block/call][position() = 1]/
63
+ descendant::pos[position() = 1]").to_s +
64
+ res[:ast].xpath("ancestor::method_add_block/command[
65
+ ident/@value='action']/args_add_block/descendant::ident/@value").to_s
66
66
  end.reject { |res| res[1].size < 3 }
67
67
  resources.map do |cont_res|
68
68
  first_resource = cont_res[1][0][:ast]
@@ -80,10 +80,10 @@ rule 'FC005', 'Avoid repetition of resource declarations' do
80
80
  end
81
81
  end
82
82
 
83
- rule 'FC006',
84
- 'Mode should be quoted or fully specified when '\
85
- 'setting file permissions' do
86
- tags %w(correctness files)
83
+ rule "FC006",
84
+ "Mode should be quoted or fully specified when "\
85
+ "setting file permissions" do
86
+ tags %w{correctness files}
87
87
  recipe do |ast|
88
88
  ast.xpath(%q{//ident[@value='mode']/parent::command/
89
89
  descendant::int[string-length(@value) < 5
@@ -93,42 +93,42 @@ rule 'FC006',
93
93
  end
94
94
  end
95
95
 
96
- rule 'FC007', 'Ensure recipe dependencies are reflected '\
97
- 'in cookbook metadata' do
98
- tags %w(correctness metadata)
96
+ rule "FC007", "Ensure recipe dependencies are reflected "\
97
+ "in cookbook metadata" do
98
+ tags %w{correctness metadata}
99
99
  recipe do |ast, filename|
100
100
  metadata_path = Pathname.new(
101
- File.join(File.dirname(filename), '..', 'metadata.rb')).cleanpath
101
+ File.join(File.dirname(filename), "..", "metadata.rb")).cleanpath
102
102
  next unless File.exist? metadata_path
103
103
  actual_included = included_recipes(ast, with_partial_names: false)
104
104
  undeclared = actual_included.keys.map do |recipe|
105
- recipe.split('::').first
105
+ recipe.split("::").first
106
106
  end - [cookbook_name(filename)] -
107
- declared_dependencies(read_ast(metadata_path))
107
+ declared_dependencies(read_ast(metadata_path))
108
108
  actual_included.map do |recipe, include_stmts|
109
109
  if undeclared.include?(recipe) ||
110
- undeclared.any? { |u| recipe.start_with?("#{u}::") }
110
+ undeclared.any? { |u| recipe.start_with?("#{u}::") }
111
111
  include_stmts
112
112
  end
113
113
  end.flatten.compact
114
114
  end
115
115
  end
116
116
 
117
- rule 'FC008', 'Generated cookbook metadata needs updating' do
118
- tags %w(style metadata)
117
+ rule "FC008", "Generated cookbook metadata needs updating" do
118
+ tags %w{style metadata}
119
119
  metadata do |ast, filename|
120
120
  {
121
- 'maintainer' => 'YOUR_COMPANY_NAME',
122
- 'maintainer_email' => 'YOUR_EMAIL'
121
+ "maintainer" => "YOUR_COMPANY_NAME",
122
+ "maintainer_email" => "YOUR_EMAIL",
123
123
  }.map do |field, value|
124
- ast.xpath(%Q(//command[ident/@value='#{field}']/
125
- descendant::tstring_content[@value='#{value}']))
124
+ ast.xpath(%Q{//command[ident/@value='#{field}']/
125
+ descendant::tstring_content[@value='#{value}']})
126
126
  end
127
127
  end
128
128
  end
129
129
 
130
- rule 'FC009', 'Resource attribute not recognised' do
131
- tags %w(correctness)
130
+ rule "FC009", "Resource attribute not recognised" do
131
+ tags %w{correctness}
132
132
  recipe do |ast|
133
133
  matches = []
134
134
  resource_attributes_by_type(ast).each do |type, resources|
@@ -146,47 +146,47 @@ rule 'FC009', 'Resource attribute not recognised' do
146
146
  end
147
147
  end
148
148
 
149
- rule 'FC010', 'Invalid search syntax' do
150
- tags %w(correctness search)
149
+ rule "FC010", "Invalid search syntax" do
150
+ tags %w{correctness search}
151
151
  recipe do |ast|
152
152
  # This only works for literal search strings
153
- literal_searches(ast).reject { |search| valid_query?(search['value']) }
153
+ literal_searches(ast).reject { |search| valid_query?(search["value"]) }
154
154
  end
155
155
  end
156
156
 
157
- rule 'FC011', 'Missing README in markdown format' do
158
- tags %w(style readme)
157
+ rule "FC011", "Missing README in markdown format" do
158
+ tags %w{style readme}
159
159
  cookbook do |filename|
160
- unless File.exist?(File.join(filename, 'README.md'))
161
- [file_match(File.join(filename, 'README.md'))]
160
+ unless File.exist?(File.join(filename, "README.md"))
161
+ [file_match(File.join(filename, "README.md"))]
162
162
  end
163
163
  end
164
164
  end
165
165
 
166
- rule 'FC012', 'Use Markdown for README rather than RDoc' do
167
- tags %w(style readme)
166
+ rule "FC012", "Use Markdown for README rather than RDoc" do
167
+ tags %w{style readme}
168
168
  cookbook do |filename|
169
- if File.exist?(File.join(filename, 'README.rdoc'))
170
- [file_match(File.join(filename, 'README.rdoc'))]
169
+ if File.exist?(File.join(filename, "README.rdoc"))
170
+ [file_match(File.join(filename, "README.rdoc"))]
171
171
  end
172
172
  end
173
173
  end
174
174
 
175
- rule 'FC013', 'Use file_cache_path rather than hard-coding tmp paths' do
176
- tags %w(style files)
175
+ rule "FC013", "Use file_cache_path rather than hard-coding tmp paths" do
176
+ tags %w{style files}
177
177
  recipe do |ast|
178
- find_resources(ast, type: 'remote_file').find_all do |download|
179
- path = (resource_attribute(download, 'path') ||
178
+ find_resources(ast, type: "remote_file").find_all do |download|
179
+ path = (resource_attribute(download, "path") ||
180
180
  resource_name(download)).to_s
181
- path.start_with?('/tmp/')
181
+ path.start_with?("/tmp/")
182
182
  end
183
183
  end
184
184
  end
185
185
 
186
- rule 'FC014', 'Consider extracting long ruby_block to library' do
187
- tags %w(style libraries)
186
+ rule "FC014", "Consider extracting long ruby_block to library" do
187
+ tags %w{style libraries}
188
188
  recipe do |ast|
189
- find_resources(ast, type: 'ruby_block').find_all do |rb|
189
+ find_resources(ast, type: "ruby_block").find_all do |rb|
190
190
  lines = rb.xpath("descendant::fcall[ident/@value='block']/../../
191
191
  descendant::*[@line]/@line").map { |n| n.value.to_i }.sort
192
192
  (!lines.empty?) && (lines.last - lines.first) > 15
@@ -194,17 +194,17 @@ rule 'FC014', 'Consider extracting long ruby_block to library' do
194
194
  end
195
195
  end
196
196
 
197
- rule 'FC015', 'Consider converting definition to a Custom Resource' do
198
- tags %w(style definitions lwrp)
197
+ rule "FC015", "Consider converting definition to a Custom Resource" do
198
+ tags %w{style definitions lwrp}
199
199
  cookbook do |dir|
200
- Dir[File.join(dir, 'definitions', '*.rb')].reject do |entry|
201
- ['.', '..'].include? entry
200
+ Dir[File.join(dir, "definitions", "*.rb")].reject do |entry|
201
+ [".", ".."].include? entry
202
202
  end.map { |entry| file_match(entry) }
203
203
  end
204
204
  end
205
205
 
206
- rule 'FC016', 'LWRP does not declare a default action' do
207
- tags %w(correctness lwrp)
206
+ rule "FC016", "LWRP does not declare a default action" do
207
+ tags %w{correctness lwrp}
208
208
  resource do |ast, filename|
209
209
  unless ["//ident/@value='default_action'",
210
210
  "//def/bodystmt/descendant::assign/
@@ -214,8 +214,8 @@ rule 'FC016', 'LWRP does not declare a default action' do
214
214
  end
215
215
  end
216
216
 
217
- rule 'FC017', 'LWRP does not notify when updated' do
218
- tags %w(correctness lwrp)
217
+ rule "FC017", "LWRP does not notify when updated" do
218
+ tags %w{correctness lwrp}
219
219
  provider do |ast, filename|
220
220
 
221
221
  use_inline_resources = !ast.xpath('//*[self::vcall or self::var_ref]/ident
@@ -228,7 +228,7 @@ rule 'FC017', 'LWRP does not notify when updated' do
228
228
  actions.reject do |action|
229
229
  blk = action.xpath('ancestor::command[1]/
230
230
  following-sibling::*[self::do_block or self::brace_block]')
231
- empty = !blk.xpath('stmts_add/void_stmt').empty?
231
+ empty = !blk.xpath("stmts_add/void_stmt").empty?
232
232
  converge_by = !blk.xpath('descendant::*[self::command or self::fcall]
233
233
  /ident[@value="converge_by"]').empty?
234
234
 
@@ -244,8 +244,8 @@ rule 'FC017', 'LWRP does not notify when updated' do
244
244
  end
245
245
  end
246
246
 
247
- rule 'FC018', 'LWRP uses deprecated notification syntax' do
248
- tags %w(style lwrp deprecated)
247
+ rule "FC018", "LWRP uses deprecated notification syntax" do
248
+ tags %w{style lwrp deprecated}
249
249
  provider do |ast|
250
250
  ast.xpath("//assign/var_field/ivar[@value='@updated']").map do |class_var|
251
251
  match(class_var)
@@ -254,13 +254,13 @@ rule 'FC018', 'LWRP uses deprecated notification syntax' do
254
254
  end
255
255
  end
256
256
 
257
- rule 'FC019', 'Access node attributes in a consistent manner' do
258
- tags %w(style attributes)
257
+ rule "FC019", "Access node attributes in a consistent manner" do
258
+ tags %w{style attributes}
259
259
  cookbook do |cookbook_dir|
260
260
  asts = {}; files = Dir["#{cookbook_dir}/*/*.rb"].reject do |file|
261
261
  relative_path = Pathname.new(file).relative_path_from(
262
262
  Pathname.new(cookbook_dir))
263
- relative_path.to_s.split(File::SEPARATOR).include?('spec')
263
+ relative_path.to_s.split(File::SEPARATOR).include?("spec")
264
264
  end.map do |file|
265
265
  { path: file, ast: read_ast(file) }
266
266
  end
@@ -268,7 +268,7 @@ rule 'FC019', 'Access node attributes in a consistent manner' do
268
268
  {
269
269
  access_type: type, count: files.map do |file|
270
270
  attribute_access(file[:ast], type: type, ignore_calls: true,
271
- cookbook_dir: cookbook_dir, ignore: 'run_state').tap do |ast|
271
+ cookbook_dir: cookbook_dir, ignore: "run_state").tap do |ast|
272
272
  unless ast.empty?
273
273
  (asts[type] ||= []) << { ast: ast, path: file[:path] }
274
274
  end
@@ -289,8 +289,8 @@ rule 'FC019', 'Access node attributes in a consistent manner' do
289
289
  end
290
290
  end
291
291
 
292
- rule 'FC021', 'Resource condition in provider may not behave as expected' do
293
- tags %w(correctness lwrp)
292
+ rule "FC021", "Resource condition in provider may not behave as expected" do
293
+ tags %w{correctness lwrp}
294
294
  provider do |ast|
295
295
  find_resources(ast).map do |resource|
296
296
  condition = resource.xpath(%q{//method_add_block/
@@ -303,16 +303,16 @@ rule 'FC021', 'Resource condition in provider may not behave as expected' do
303
303
  end
304
304
  end
305
305
 
306
- rule 'FC022', 'Resource condition within loop may not behave as expected' do
307
- tags %w(correctness)
306
+ rule "FC022", "Resource condition within loop may not behave as expected" do
307
+ tags %w{correctness}
308
308
  recipe do |ast|
309
309
  ast.xpath("//call[ident/@value='each']/../do_block[count(ancestor::
310
310
  method_add_block/method_add_arg/fcall/ident[@value='only_if' or
311
311
  @value = 'not_if']) = 0]").map do |lp|
312
- block_vars = lp.xpath('block_var/params/child::*').map do |n|
313
- n.name.sub(/^ident/, '')
314
- end + lp.xpath('block_var/params/child::*/descendant::ident').map do |v|
315
- v['value']
312
+ block_vars = lp.xpath("block_var/params/child::*").map do |n|
313
+ n.name.sub(/^ident/, "")
314
+ end + lp.xpath("block_var/params/child::*/descendant::ident").map do |v|
315
+ v["value"]
316
316
  end
317
317
  find_resources(lp).map do |resource|
318
318
  # if any of the parameters to the block are used in a condition then we
@@ -323,13 +323,13 @@ rule 'FC022', 'Resource condition within loop may not behave as expected' do
323
323
  self::command][1]/descendant::ident/@value}).map do |a|
324
324
  a.value
325
325
  end)).empty?
326
- c = resource.xpath('command[count(descendant::string_embexpr) = 0]')
327
- if resource.xpath('command/ident/@value').first.value == 'define'
326
+ c = resource.xpath("command[count(descendant::string_embexpr) = 0]")
327
+ if resource.xpath("command/ident/@value").first.value == "define"
328
328
  next
329
329
  end
330
330
  resource unless c.empty? || block_vars.any? do |var|
331
- !resource.xpath(%Q(command/args_add_block/args_add/
332
- var_ref/ident[@value='#{var}'])).empty?
331
+ !resource.xpath(%Q{command/args_add_block/args_add/
332
+ var_ref/ident[@value='#{var}']}).empty?
333
333
  end
334
334
  end
335
335
  end
@@ -337,8 +337,8 @@ rule 'FC022', 'Resource condition within loop may not behave as expected' do
337
337
  end
338
338
  end
339
339
 
340
- rule 'FC023', 'Prefer conditional attributes' do
341
- tags %w(style)
340
+ rule "FC023", "Prefer conditional attributes" do
341
+ tags %w{style}
342
342
  recipe do |ast|
343
343
  ast.xpath(%q{//method_add_block[command/ident][count(descendant::ident
344
344
  [@value='only_if' or @value='not_if']) = 0]/ancestor::*[self::if or
@@ -349,13 +349,13 @@ rule 'FC023', 'Prefer conditional attributes' do
349
349
  end
350
350
  end
351
351
 
352
- rule 'FC024', 'Consider adding platform equivalents' do
353
- tags %w(portability)
354
- RHEL = %w(amazon centos redhat scientific oracle)
352
+ rule "FC024", "Consider adding platform equivalents" do
353
+ tags %w{portability}
354
+ RHEL = %w{amazon centos redhat scientific oracle}
355
355
  recipe do |ast, filename|
356
- next if Pathname.new(filename).basename.to_s == 'metadata.rb'
356
+ next if Pathname.new(filename).basename.to_s == "metadata.rb"
357
357
  metadata_path = Pathname.new(
358
- File.join(File.dirname(filename), '..', 'metadata.rb')).cleanpath
358
+ File.join(File.dirname(filename), "..", "metadata.rb")).cleanpath
359
359
  md_platforms = if File.exist?(metadata_path)
360
360
  supported_platforms(read_ast(
361
361
  metadata_path)).map { |p| p[:platform] }
@@ -366,29 +366,29 @@ rule 'FC024', 'Consider adding platform equivalents' do
366
366
 
367
367
  ['//method_add_arg[fcall/ident/@value="platform?"]/
368
368
  arg_paren/args_add_block',
369
- '//when'].map do |expr|
369
+ "//when"].map do |expr|
370
370
  ast.xpath(expr).map do |whn|
371
371
  platforms = whn.xpath('args_add/
372
372
  descendant::tstring_content').map do |p|
373
- p['value']
373
+ p["value"]
374
374
  end.sort
375
375
  unless platforms.size == 1 || (md_platforms & platforms).empty?
376
376
  whn unless (platforms & RHEL).empty? ||
377
- ((md_platforms & RHEL) - (platforms & RHEL)).empty?
377
+ ((md_platforms & RHEL) - (platforms & RHEL)).empty?
378
378
  end
379
379
  end.compact
380
380
  end.flatten
381
381
  end
382
382
  end
383
383
 
384
- rule 'FC025', 'Prefer chef_gem to compile-time gem install' do
385
- tags %w(style deprecated)
384
+ rule "FC025", "Prefer chef_gem to compile-time gem install" do
385
+ tags %w{style deprecated}
386
386
  recipe do |ast|
387
387
  gem_install = ast.xpath("//stmts_add/assign[method_add_block[command/ident/
388
388
  @value='gem_package'][do_block/stmts_add/command[ident/@value='action']
389
389
  [descendant::ident/@value='nothing']]]")
390
390
  gem_install.map do |install|
391
- gem_var = install.xpath('var_field/ident/@value')
391
+ gem_var = install.xpath("var_field/ident/@value")
392
392
  unless ast.xpath("//method_add_arg[call/
393
393
  var_ref/ident/@value='#{gem_var}']
394
394
  [arg_paren/descendant::ident/@value='install' or
@@ -399,33 +399,33 @@ rule 'FC025', 'Prefer chef_gem to compile-time gem install' do
399
399
  end
400
400
  end
401
401
 
402
- rule 'FC026', 'Conditional execution block attribute contains only string' do
403
- tags %w(correctness)
402
+ rule "FC026", "Conditional execution block attribute contains only string" do
403
+ tags %w{correctness}
404
404
  recipe do |ast|
405
405
  find_resources(ast).map { |r| resource_attributes(r) }.map do |resource|
406
- [resource['not_if'], resource['only_if']]
406
+ [resource["not_if"], resource["only_if"]]
407
407
  end.flatten.compact.select do |condition|
408
408
  condition.respond_to?(:xpath) &&
409
- !condition.xpath('descendant::string_literal').empty? &&
410
- !condition.xpath('stmts_add/string_literal').empty? &&
409
+ !condition.xpath("descendant::string_literal").empty? &&
410
+ !condition.xpath("stmts_add/string_literal").empty? &&
411
411
  condition.xpath('descendant::stmts_add[count(ancestor::
412
412
  string_literal) = 0]').size == 1
413
413
  end
414
414
  end
415
415
  end
416
416
 
417
- rule 'FC027', 'Resource sets internal attribute' do
418
- tags %w(correctness)
417
+ rule "FC027", "Resource sets internal attribute" do
418
+ tags %w{correctness}
419
419
  recipe do |ast|
420
420
  find_resources(ast, type: :service).map do |service|
421
421
  service unless (resource_attributes(service).keys &
422
- ['enabled', 'running']).empty?
422
+ %w{enabled running}).empty?
423
423
  end.compact
424
424
  end
425
425
  end
426
426
 
427
- rule 'FC028', 'Incorrect #platform? usage' do
428
- tags %w(correctness)
427
+ rule "FC028", 'Incorrect #platform? usage' do
428
+ tags %w{correctness}
429
429
  recipe do |ast|
430
430
  ast.xpath(%q{//*[self::call | self::command_call]
431
431
  [(var_ref|vcall)/ident/@value='node']
@@ -433,23 +433,23 @@ rule 'FC028', 'Incorrect #platform? usage' do
433
433
  end
434
434
  end
435
435
 
436
- rule 'FC029', 'No leading cookbook name in recipe metadata' do
437
- tags %w(correctness metadata)
436
+ rule "FC029", "No leading cookbook name in recipe metadata" do
437
+ tags %w{correctness metadata}
438
438
  metadata do |ast, filename|
439
439
  ast.xpath('//command[ident/@value="recipe"]').map do |declared_recipe|
440
- next unless declared_recipe.xpath('count(//vcall|//var_ref)').to_i == 0
440
+ next unless declared_recipe.xpath("count(//vcall|//var_ref)").to_i == 0
441
441
  recipe_name = declared_recipe.xpath('args_add_block/
442
442
  descendant::tstring_content[1]/@value').to_s
443
443
  unless recipe_name.empty? ||
444
- recipe_name.split('::').first == cookbook_name(filename.to_s)
444
+ recipe_name.split("::").first == cookbook_name(filename.to_s)
445
445
  declared_recipe
446
446
  end
447
447
  end.compact
448
448
  end
449
449
  end
450
450
 
451
- rule 'FC030', 'Cookbook contains debugger breakpoints' do
452
- tags %w(annoyances)
451
+ rule "FC030", "Cookbook contains debugger breakpoints" do
452
+ tags %w{annoyances}
453
453
  def pry_bindings(ast)
454
454
  ast.xpath('//call[(vcall|var_ref)/ident/@value="binding"]
455
455
  [ident/@value="pry"]')
@@ -460,22 +460,22 @@ rule 'FC030', 'Cookbook contains debugger breakpoints' do
460
460
  template { |ast| pry_bindings(ast) }
461
461
  end
462
462
 
463
- rule 'FC031', 'Cookbook without metadata file' do
464
- tags %w(correctness metadata)
463
+ rule "FC031", "Cookbook without metadata file" do
464
+ tags %w{correctness metadata}
465
465
  cookbook do |filename|
466
- if !File.exist?(File.join(filename, 'metadata.rb'))
467
- [file_match(File.join(filename, 'metadata.rb'))]
466
+ if !File.exist?(File.join(filename, "metadata.rb"))
467
+ [file_match(File.join(filename, "metadata.rb"))]
468
468
  end
469
469
  end
470
470
  end
471
471
 
472
- rule 'FC032', 'Invalid notification timing' do
473
- tags %w(correctness notifications)
472
+ rule "FC032", "Invalid notification timing" do
473
+ tags %w{correctness notifications}
474
474
  recipe do |ast|
475
- valid_timings = if resource_attribute?('file', 'notifies_before') then
476
- [:delayed, :immediate, :before]
477
- else
478
- [:delayed, :immediate]
475
+ valid_timings = if resource_attribute?("file", "notifies_before") then
476
+ [:delayed, :immediate, :before]
477
+ else
478
+ [:delayed, :immediate]
479
479
  end
480
480
  find_resources(ast).select do |resource|
481
481
  notifications(resource).any? do |notification|
@@ -485,12 +485,12 @@ rule 'FC032', 'Invalid notification timing' do
485
485
  end
486
486
  end
487
487
 
488
- rule 'FC033', 'Missing template' do
489
- tags %w(correctness)
488
+ rule "FC033", "Missing template" do
489
+ tags %w{correctness}
490
490
  recipe do |ast, filename|
491
491
  find_resources(ast, type: :template).reject do |resource|
492
- resource_attributes(resource)['local'] ||
493
- resource_attributes(resource)['cookbook']
492
+ resource_attributes(resource)["local"] ||
493
+ resource_attributes(resource)["cookbook"]
494
494
  end.map do |resource|
495
495
  file = template_file(resource_attributes(resource,
496
496
  return_expressions: true))
@@ -502,7 +502,7 @@ rule 'FC033', 'Missing template' do
502
502
  relative_path = []
503
503
  Pathname.new(path).ascend do |template_path|
504
504
  relative_path << template_path.basename
505
- break if template_path.dirname.dirname.basename.to_s == 'templates'
505
+ break if template_path.dirname.dirname.basename.to_s == "templates"
506
506
  end
507
507
  File.join(relative_path.reverse) == resource[:file]
508
508
  end
@@ -510,26 +510,26 @@ rule 'FC033', 'Missing template' do
510
510
  end
511
511
  end
512
512
 
513
- rule 'FC034', 'Unused template variables' do
514
- tags %w(correctness)
513
+ rule "FC034", "Unused template variables" do
514
+ tags %w{correctness}
515
515
  recipe do |ast, filename|
516
- Array(resource_attributes_by_type(ast)['template']).select do |t|
517
- t['variables'] && t['variables'].respond_to?(:xpath)
516
+ Array(resource_attributes_by_type(ast)["template"]).select do |t|
517
+ t["variables"] && t["variables"].respond_to?(:xpath)
518
518
  end.map do |resource|
519
519
  all_templates = template_paths(filename)
520
520
  template_paths = all_templates.select do |path|
521
521
  File.basename(path) == template_file(resource)
522
522
  end
523
523
  next unless template_paths.any?
524
- passed_vars = resource['variables'].xpath(
525
- 'symbol/ident/@value').map { |tv| tv.to_s }
524
+ passed_vars = resource["variables"].xpath(
525
+ "symbol/ident/@value").map { |tv| tv.to_s }
526
526
 
527
527
  unused_vars_exist = template_paths.all? do |template_path|
528
528
  begin
529
529
  template_vars = templates_included(
530
530
  all_templates, template_path).map do |template|
531
- read_ast(template).xpath('//var_ref/ivar/@value').map do |v|
532
- v.to_s.sub(/^@/, '')
531
+ read_ast(template).xpath("//var_ref/ivar/@value").map do |v|
532
+ v.to_s.sub(/^@/, "")
533
533
  end
534
534
  end.flatten
535
535
  ! (passed_vars - template_vars).empty?
@@ -542,8 +542,8 @@ rule 'FC034', 'Unused template variables' do
542
542
  end
543
543
  end
544
544
 
545
- rule 'FC037', 'Invalid notification action' do
546
- tags %w(correctness)
545
+ rule "FC037", "Invalid notification action" do
546
+ tags %w{correctness}
547
547
  recipe do |ast|
548
548
  find_resources(ast).select do |resource|
549
549
  notifications(resource).any? do |n|
@@ -557,11 +557,11 @@ rule 'FC037', 'Invalid notification action' do
557
557
  end
558
558
  end
559
559
 
560
- rule 'FC038', 'Invalid resource action' do
561
- tags %w(correctness)
560
+ rule "FC038", "Invalid resource action" do
561
+ tags %w{correctness}
562
562
  recipe do |ast|
563
563
  find_resources(ast).select do |resource|
564
- actions = resource_attributes(resource)['action']
564
+ actions = resource_attributes(resource)["action"]
565
565
  if actions.respond_to?(:xpath)
566
566
  actions = actions.xpath('descendant::array/
567
567
  descendant::symbol/ident/@value')
@@ -575,11 +575,11 @@ rule 'FC038', 'Invalid resource action' do
575
575
  end
576
576
  end
577
577
 
578
- rule 'FC039', 'Node method cannot be accessed with key' do
579
- tags %w(correctness)
578
+ rule "FC039", "Node method cannot be accessed with key" do
579
+ tags %w{correctness}
580
580
  recipe do |ast|
581
- [{ type: :string, path: '@value' },
582
- { type: :symbol, path: 'ident/@value' }].map do |access_type|
581
+ [{ type: :string, path: "@value" },
582
+ { type: :symbol, path: "ident/@value" }].map do |access_type|
583
583
  attribute_access(ast, type: access_type[:type]).select do |att|
584
584
  att_name = att.xpath(access_type[:path]).to_s.to_sym
585
585
  att_name != :tags && chef_node_methods.include?(att_name)
@@ -595,12 +595,12 @@ rule 'FC039', 'Node method cannot be accessed with key' do
595
595
  end
596
596
  end
597
597
 
598
- rule 'FC040', 'Execute resource used to run git commands' do
599
- tags %w(style recipe etsy)
598
+ rule "FC040", "Execute resource used to run git commands" do
599
+ tags %w{style recipe etsy}
600
600
  recipe do |ast|
601
- possible_git_commands = %w( clone fetch pull checkout reset )
602
- find_resources(ast, type: 'execute').select do |cmd|
603
- cmd_str = (resource_attribute(cmd, 'command') || resource_name(cmd)).to_s
601
+ possible_git_commands = %w{ clone fetch pull checkout reset }
602
+ find_resources(ast, type: "execute").select do |cmd|
603
+ cmd_str = (resource_attribute(cmd, "command") || resource_name(cmd)).to_s
604
604
 
605
605
  actual_git_commands = cmd_str.scan(/git ([a-z]+)/).map { |c| c.first }
606
606
  (possible_git_commands & actual_git_commands).any?
@@ -608,25 +608,25 @@ rule 'FC040', 'Execute resource used to run git commands' do
608
608
  end
609
609
  end
610
610
 
611
- rule 'FC041', 'Execute resource used to run curl or wget commands' do
612
- tags %w(style recipe etsy)
611
+ rule "FC041", "Execute resource used to run curl or wget commands" do
612
+ tags %w{style recipe etsy}
613
613
  recipe do |ast|
614
- find_resources(ast, type: 'execute').select do |cmd|
615
- cmd_str = (resource_attribute(cmd, 'command') || resource_name(cmd)).to_s
616
- (cmd_str.match(/^curl.*(-o|>|--output).*$/) || cmd_str.include?('wget '))
614
+ find_resources(ast, type: "execute").select do |cmd|
615
+ cmd_str = (resource_attribute(cmd, "command") || resource_name(cmd)).to_s
616
+ (cmd_str.match(/^curl.*(-o|>|--output).*$/) || cmd_str.include?("wget "))
617
617
  end
618
618
  end
619
619
  end
620
620
 
621
- rule 'FC042', 'Prefer include_recipe to require_recipe' do
622
- tags %w(deprecated)
621
+ rule "FC042", "Prefer include_recipe to require_recipe" do
622
+ tags %w{deprecated}
623
623
  recipe do |ast|
624
624
  ast.xpath('//command[ident/@value="require_recipe"]')
625
625
  end
626
626
  end
627
627
 
628
- rule 'FC043', 'Prefer new notification syntax' do
629
- tags %w(style notifications deprecated)
628
+ rule "FC043", "Prefer new notification syntax" do
629
+ tags %w{style notifications deprecated}
630
630
  recipe do |ast|
631
631
  find_resources(ast).select do |resource|
632
632
  notifications(resource).any? { |notify| notify[:style] == :old }
@@ -634,10 +634,10 @@ rule 'FC043', 'Prefer new notification syntax' do
634
634
  end
635
635
  end
636
636
 
637
- rule 'FC044', 'Avoid bare attribute keys' do
638
- tags %w(style)
637
+ rule "FC044", "Avoid bare attribute keys" do
638
+ tags %w{style}
639
639
  attributes do |ast|
640
- declared = ast.xpath('//descendant::var_field/ident/@value').map do |v|
640
+ declared = ast.xpath("//descendant::var_field/ident/@value").map do |v|
641
641
  v.to_s
642
642
  end
643
643
 
@@ -646,32 +646,32 @@ rule 'FC044', 'Avoid bare attribute keys' do
646
646
 
647
647
  local_declared = v.xpath("ancestor::*[self::brace_block or self::do_block]
648
648
  /block_var/descendant::ident/@value").map do |v|
649
- v.to_s
650
- end
649
+ v.to_s
650
+ end
651
651
 
652
- (v['value'] != 'secure_password') &&
653
- !(declared + local_declared).uniq.include?(v['value']) &&
652
+ (v["value"] != "secure_password") &&
653
+ !(declared + local_declared).uniq.include?(v["value"]) &&
654
654
  !v.xpath("ancestor::*[self::brace_block or self::do_block]/block_var/
655
655
  descendant::ident/@value='#{v['value']}'")
656
656
  end
657
657
  end
658
658
  end
659
659
 
660
- rule 'FC045', 'Metadata does not contain cookbook name' do
661
- tags %w(correctness metadata chef12)
660
+ rule "FC045", "Metadata does not contain cookbook name" do
661
+ tags %w{correctness metadata chef12}
662
662
  metadata do |ast, filename|
663
663
  unless ast.xpath('descendant::stmts_add/command/ident/@value="name"')
664
664
  [file_match(filename)]
665
665
  end
666
666
  end
667
667
  cookbook do |filename|
668
- if !File.exist?(File.join(filename, 'metadata.rb'))
669
- [file_match(File.join(filename, 'metadata.rb'))]
668
+ if !File.exist?(File.join(filename, "metadata.rb"))
669
+ [file_match(File.join(filename, "metadata.rb"))]
670
670
  end
671
671
  end
672
672
  end
673
673
 
674
- rule 'FC046', 'Attribute assignment uses assign unless nil' do
674
+ rule "FC046", "Attribute assignment uses assign unless nil" do
675
675
  attributes do |ast|
676
676
  attribute_access(ast).map do |a|
677
677
  a.xpath('ancestor::opassign/op[@value="||="]')
@@ -679,15 +679,15 @@ rule 'FC046', 'Attribute assignment uses assign unless nil' do
679
679
  end
680
680
  end
681
681
 
682
- rule 'FC047', 'Attribute assignment does not specify precedence' do
683
- tags %w(attributes correctness chef11)
682
+ rule "FC047", "Attribute assignment does not specify precedence" do
683
+ tags %w{attributes correctness chef11}
684
684
  recipe do |ast|
685
685
  attribute_access(ast).map do |att|
686
686
  exclude_att_types = '[count(following-sibling::ident[
687
687
  is_att_type(@value) or @value = "run_state"]) = 0]'
688
- att.xpath(%Q(ancestor::assign[*[self::field | self::aref_field]
688
+ att.xpath(%Q{ancestor::assign[*[self::field | self::aref_field]
689
689
  [descendant::*[self::vcall | self::var_ref][ident/@value="node"]
690
- #{exclude_att_types}]]), AttFilter.new) +
690
+ #{exclude_att_types}]]}, AttFilter.new) +
691
691
  att.xpath(%Q{ancestor::binary[@value="<<"]/*[position() = 1]
692
692
  [self::aref]
693
693
  [descendant::*[self::vcall | self::var_ref]#{exclude_att_types}
@@ -696,33 +696,33 @@ rule 'FC047', 'Attribute assignment does not specify precedence' do
696
696
  end
697
697
  end
698
698
 
699
- rule 'FC048', 'Prefer Mixlib::ShellOut' do
700
- tags %w(style processes)
699
+ rule "FC048", "Prefer Mixlib::ShellOut" do
700
+ tags %w{style processes}
701
701
  recipe do |ast|
702
- xstring_literal = ast.xpath('//xstring_literal')
702
+ xstring_literal = ast.xpath("//xstring_literal")
703
703
  next xstring_literal if xstring_literal.any?
704
704
 
705
705
  ast.xpath('//*[self::command or self::fcall]/ident[@value="system"]').select do |x|
706
- resource_name = x.xpath('ancestor::do_block/preceding-sibling::command/ident/@value')
707
- next false if resource_name.any? && resource_name.all? { |r| resource_attribute?(r.to_s, 'system') }
706
+ resource_name = x.xpath("ancestor::do_block/preceding-sibling::command/ident/@value")
707
+ next false if resource_name.any? && resource_name.all? { |r| resource_attribute?(r.to_s, "system") }
708
708
  next x.xpath('count(following-sibling::args_add_block/descendant::kw[@value="true" or @value="false"]) = 0')
709
709
  end
710
710
  end
711
711
  end
712
712
 
713
- rule 'FC049', 'Role name does not match containing file name' do
714
- tags %w(style roles)
713
+ rule "FC049", "Role name does not match containing file name" do
714
+ tags %w{style roles}
715
715
  role do |ast, filename|
716
716
  role_name_specified = field_value(ast, :name)
717
- role_name_file = Pathname.new(filename).basename.sub_ext('').to_s
717
+ role_name_file = Pathname.new(filename).basename.sub_ext("").to_s
718
718
  if role_name_specified && role_name_specified != role_name_file
719
719
  field(ast, :name)
720
720
  end
721
721
  end
722
722
  end
723
723
 
724
- rule 'FC050', 'Name includes invalid characters' do
725
- tags %w(correctness environments roles)
724
+ rule "FC050", "Name includes invalid characters" do
725
+ tags %w{correctness environments roles}
726
726
  def invalid_name(ast)
727
727
  field(ast, :name) unless field_value(ast, :name) =~ /^[a-zA-Z0-9_\-]+$/
728
728
  end
@@ -730,8 +730,8 @@ rule 'FC050', 'Name includes invalid characters' do
730
730
  role { |ast| invalid_name(ast) }
731
731
  end
732
732
 
733
- rule 'FC051', 'Template partials loop indefinitely' do
734
- tags %w(correctness)
733
+ rule "FC051", "Template partials loop indefinitely" do
734
+ tags %w{correctness}
735
735
  recipe do |_, filename|
736
736
  cbk_templates = template_paths(filename)
737
737
 
@@ -746,40 +746,40 @@ rule 'FC051', 'Template partials loop indefinitely' do
746
746
  end
747
747
  end
748
748
 
749
- rule 'FC052', 'Metadata uses the unimplemented "suggests" keyword' do
750
- tags %w(style metadata)
749
+ rule "FC052", 'Metadata uses the unimplemented "suggests" keyword' do
750
+ tags %w{style metadata}
751
751
  metadata do |ast, filename|
752
- ast.xpath(%Q(//command[ident/@value='suggests']))
752
+ ast.xpath(%q{//command[ident/@value='suggests']})
753
753
  end
754
754
  end
755
755
 
756
- rule 'FC053', 'Metadata uses the unimplemented "recommends" keyword' do
757
- tags %w(style metadata)
756
+ rule "FC053", 'Metadata uses the unimplemented "recommends" keyword' do
757
+ tags %w{style metadata}
758
758
  metadata do |ast, filename|
759
- ast.xpath(%Q(//command[ident/@value='recommends']))
759
+ ast.xpath(%q{//command[ident/@value='recommends']})
760
760
  end
761
761
  end
762
762
 
763
763
  # NOTE: FC054 was yanked and should be considered reserved, do not reuse it
764
764
 
765
- rule 'FC055', 'Ensure maintainer is set in metadata' do
766
- tags %w(correctness metadata)
765
+ rule "FC055", "Ensure maintainer is set in metadata" do
766
+ tags %w{correctness metadata}
767
767
  metadata do |ast, filename|
768
- [file_match(filename)] unless field(ast, 'maintainer').any?
768
+ [file_match(filename)] unless field(ast, "maintainer").any?
769
769
  end
770
770
  end
771
771
 
772
- rule 'FC056', 'Ensure maintainer_email is set in metadata' do
773
- tags %w(correctness metadata)
772
+ rule "FC056", "Ensure maintainer_email is set in metadata" do
773
+ tags %w{correctness metadata}
774
774
  metadata do |ast, filename|
775
- [file_match(filename)] unless field(ast, 'maintainer_email').any?
775
+ [file_match(filename)] unless field(ast, "maintainer_email").any?
776
776
  end
777
777
  end
778
778
 
779
- rule 'FC057', 'Library provider does not declare use_inline_resources' do
780
- tags %w(correctness)
779
+ rule "FC057", "Library provider does not declare use_inline_resources" do
780
+ tags %w{correctness}
781
781
  applies_to do |version|
782
- version >= gem_version('11.0.0')
782
+ version >= gem_version("11.0.0")
783
783
  end
784
784
  library do |ast, filename|
785
785
  ast.xpath('//const_path_ref/const[@value="LWRPBase"]/..//const[@value="Provider"]/../../..').select do |x|
@@ -788,23 +788,23 @@ rule 'FC057', 'Library provider does not declare use_inline_resources' do
788
788
  end
789
789
  end
790
790
 
791
- rule 'FC058', 'Library provider declares use_inline_resources and declares #action_<name> methods' do
792
- tags %w(correctness)
791
+ rule "FC058", 'Library provider declares use_inline_resources and declares #action_<name> methods' do
792
+ tags %w{correctness}
793
793
  applies_to do |version|
794
- version >= gem_version('11.0.0')
794
+ version >= gem_version("11.0.0")
795
795
  end
796
796
  library do |ast, filename|
797
797
  ast.xpath('//const_path_ref/const[@value="LWRPBase"]/..//const[@value="Provider"]/../../..').select do |x|
798
798
  x.xpath('//*[self::vcall or self::var_ref]/ident[@value="use_inline_resources"]').length > 0 &&
799
- x.xpath(%Q(//def[ident[contains(@value, 'action_')]])).length > 0
799
+ x.xpath(%q{//def[ident[contains(@value, 'action_')]]}).length > 0
800
800
  end
801
801
  end
802
802
  end
803
803
 
804
- rule 'FC059', 'LWRP provider does not declare use_inline_resources' do
805
- tags %w(correctness)
804
+ rule "FC059", "LWRP provider does not declare use_inline_resources" do
805
+ tags %w{correctness}
806
806
  applies_to do |version|
807
- version >= gem_version('11.0.0')
807
+ version >= gem_version("11.0.0")
808
808
  end
809
809
  provider do |ast, filename|
810
810
  use_inline_resources = !ast.xpath('//*[self::vcall or self::var_ref]/ident
@@ -815,21 +815,21 @@ rule 'FC059', 'LWRP provider does not declare use_inline_resources' do
815
815
  end
816
816
  end
817
817
 
818
- rule 'FC060', 'LWRP provider declares use_inline_resources and declares #action_<name> methods' do
819
- tags %w(correctness)
818
+ rule "FC060", 'LWRP provider declares use_inline_resources and declares #action_<name> methods' do
819
+ tags %w{correctness}
820
820
  applies_to do |version|
821
- version >= gem_version('11.0.0')
821
+ version >= gem_version("11.0.0")
822
822
  end
823
823
  provider do |ast, filename|
824
824
  use_inline_resources = !ast.xpath('//*[self::vcall or self::var_ref]/ident
825
825
  [@value="use_inline_resources"]').empty?
826
826
  if use_inline_resources
827
- ast.xpath(%Q(//def[ident[contains(@value, 'action_')]]))
827
+ ast.xpath(%q{//def[ident[contains(@value, 'action_')]]})
828
828
  end
829
829
  end
830
830
  end
831
831
 
832
- rule 'FC061', 'Valid cookbook versions are of the form x.y or x.y.z' do
832
+ rule "FC061", "Valid cookbook versions are of the form x.y or x.y.z" do
833
833
  tags %w{metadata correctness}
834
834
  metadata do |ast, filename|
835
835
  # matches a version method with a string literal with no interpolation
@@ -840,38 +840,38 @@ rule 'FC061', 'Valid cookbook versions are of the form x.y or x.y.z' do
840
840
  end
841
841
  end
842
842
 
843
- rule 'FC062', 'Cookbook should have version metadata' do
843
+ rule "FC062", "Cookbook should have version metadata" do
844
844
  tags %w{metadata}
845
845
  metadata do |ast, filename|
846
- [file_match(filename)] unless field(ast, 'version').any?
846
+ [file_match(filename)] unless field(ast, "version").any?
847
847
  end
848
848
  end
849
849
 
850
- rule 'FC063', 'Cookbook incorrectly depends on itself' do
851
- tags %w(metadata correctness)
850
+ rule "FC063", "Cookbook incorrectly depends on itself" do
851
+ tags %w{metadata correctness}
852
852
  metadata do |ast, filename|
853
853
  name = cookbook_name(filename)
854
- ast.xpath(%Q(//command[ident/@value='depends']/
855
- descendant::tstring_content[@value='#{name}']))
854
+ ast.xpath(%Q{//command[ident/@value='depends']/
855
+ descendant::tstring_content[@value='#{name}']})
856
856
  end
857
857
  end
858
858
 
859
- rule 'FC064', 'Ensure issues_url is set in metadata' do
860
- tags %w(metadata supermarket chef12)
859
+ rule "FC064", "Ensure issues_url is set in metadata" do
860
+ tags %w{metadata supermarket chef12}
861
861
  applies_to do |version|
862
- version >= gem_version('12.0.0')
862
+ version >= gem_version("12.0.0")
863
863
  end
864
864
  metadata do |ast, filename|
865
- [file_match(filename)] unless field(ast, 'issues_url').any?
865
+ [file_match(filename)] unless field(ast, "issues_url").any?
866
866
  end
867
867
  end
868
868
 
869
- rule 'FC065', 'Ensure source_url is set in metadata' do
870
- tags %w(metadata supermarket chef12)
869
+ rule "FC065", "Ensure source_url is set in metadata" do
870
+ tags %w{metadata supermarket chef12}
871
871
  applies_to do |version|
872
- version >= gem_version('12.0.0')
872
+ version >= gem_version("12.0.0")
873
873
  end
874
874
  metadata do |ast, filename|
875
- [file_match(filename)] unless field(ast, 'source_url').any?
875
+ [file_match(filename)] unless field(ast, "source_url").any?
876
876
  end
877
877
  end