foodcritic 13.0.1 → 13.1.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
  SHA256:
3
- metadata.gz: 4043ba45f55c8b88b96eeb28ecb5111dd92e98ba45d1c74dc3ca86bc92c57cdc
4
- data.tar.gz: 2f9bd70e42c3cbdec213e727c33b568d21ed72578dca8a173110f2944375d1e6
3
+ metadata.gz: 3903e57cd4ed6cf6c556f4fa0081e5eace7eb2935faa088c407a5ac3df595a63
4
+ data.tar.gz: 4bce109b2c6ee021e420c373034bd48294f4a94cc05eef8e08ca918e000ebff6
5
5
  SHA512:
6
- metadata.gz: d7d07e5748a0a19265b0d26d7347d07e90d79bd1aff1565c1c210501f1f29205e7d433cdeeea5646bdb2793e1517f78b76134639e2bab5add1433e161a65f2de
7
- data.tar.gz: c17b5b064688c41d3a397202314df1938f549071dc07d1f368e730e5f795f73626d8e958524931bdf45b8d0523ce94f236c77814cd1196d5651f3d8edd3c5f85
6
+ metadata.gz: 48d6d18c3629a920e36f03536733078ccc1edc069ee151972cd9ba424e69f5c2470869296324ad0b10cc7155d533950e071db8b9daae86ed161535279b0267da
7
+ data.tar.gz: 9e8f389db7509486afd00772e675d1f1af6603fa689df3b4c59022362003437a99c4d57a73aec08715acd00eec112f23ee5d580baea9f4d4c237a2fdd2038311
@@ -1,5 +1,25 @@
1
1
  # Foodcritic Changelog:
2
2
 
3
+ ## [13.1.0](https://github.com/Foodcritic/foodcritic/tree/v13.1.0) (2018-04-12)
4
+
5
+ ### Speed improvements
6
+
7
+ Foodcritic now caches some of the information on cookbooks it previously calculated repeatedly. This results in a 10X reduction in some disk reads and a 7% improvement in runtime overall.
8
+
9
+ ### Rule file improvements
10
+
11
+ The fetching and parsing of Foodcritic rule files (.foodcritic files) has been improved. If a non-existent file is specified on the CLI we will now fail instead of silently continuing. Additionally, if the .foodcritic file exists, but cannot be read/parsed we will also fail instead of silently continuing.
12
+
13
+ ### Improved file detection
14
+
15
+ Several deficiencies in how Foodcritic detected files within a cookbook have been resolved. If you use the Chef 13+ root alias files such as attributes.rb or recipe.rb these will now be detected. Additionally we will detect template files not in the default directory, or deeply nested in directories within the templates directory.
16
+
17
+ ### New Rules
18
+
19
+ - `FC116` - Cookbook depends on the deprecated compat_resource cookbook
20
+ - `FC120` - Do not set the name property directly on a resource
21
+ - `FC122` - Use the build_essential resource instead of the recipe
22
+
3
23
  ## [13.0.1](https://github.com/Foodcritic/foodcritic/tree/v13.0.1) (2018-04-11)
4
24
 
5
25
  - Properly discover templates not in templates/default/. Templates in the root of the templates directory would be skipped previously
@@ -84,7 +84,7 @@ module FoodCritic
84
84
  relevant_tags = if options[:tags].any?
85
85
  options[:tags]
86
86
  else
87
- cookbook_tags(p[:filename])
87
+ rule_file_tags(p[:filename])
88
88
  end
89
89
 
90
90
  progress = "."
@@ -199,15 +199,44 @@ module FoodCritic
199
199
  rule.applies_to.yield(Gem::Version.create(version))
200
200
  end
201
201
 
202
- def cookbook_tags(file)
202
+ # given a file in the cookbook lookup all the applicable tag rules defined in rule
203
+ # files. The rule file is either that specified via CLI or the .foodcritic file
204
+ # in the cookbook. We cache this information at the cookbook level to prevent looking
205
+ # up the same thing dozens of times
206
+ #
207
+ # @param [String] file in the cookbook
208
+ # @return [Array] array of tag rules
209
+ def rule_file_tags(file)
210
+ cookbook = cookbook_dir(file)
211
+ @tag_cache ||= {}
212
+
213
+ # lookup the tags in the cache has and return that if we find something
214
+ cb_tags = @tag_cache[cookbook]
215
+ return cb_tags unless cb_tags.nil?
216
+
217
+ # if a rule file has been specified use that. Otherwise use the .foodcritic file in the CB
218
+ tags = if @options[:rule_file]
219
+ raise "ERROR: Could not find the specified rule file at #{@options[:rule_file]}" unless File.exist?(@options[:rule_file])
220
+ parse_rule_file(@options[:rule_file])
221
+ else
222
+ File.exist?("#{cookbook}/.foodcritic") ? parse_rule_file("#{cookbook}/.foodcritic") : []
223
+ end
224
+
225
+ @tag_cache[cookbook] = tags
226
+ tags
227
+ end
228
+
229
+ # given a filename parse any tag rules in that file
230
+ #
231
+ # @param [String] rule file path
232
+ # @return [Array] array of tag rules from the file
233
+ def parse_rule_file(file)
203
234
  tags = []
204
- fc_file = @options[:rule_file] || "#{cookbook_dir(file)}/.foodcritic"
205
- if File.exist? fc_file
206
- begin
207
- tag_text = File.read fc_file
208
- tags = tag_text.split(/\s/)
209
- rescue Errno::EACCES
210
- end
235
+ begin
236
+ tag_text = File.read file
237
+ tags = tag_text.split(/\s/)
238
+ rescue
239
+ raise "ERROR: Could not read or parse the specified rule file at #{file}"
211
240
  end
212
241
  tags
213
242
  end
@@ -218,13 +247,46 @@ module FoodCritic
218
247
  end
219
248
  end
220
249
 
250
+ # provides the path to the cookbook from a file within the cookbook
251
+ # we cache this data in a hash because this method gets called often
252
+ # for the same files.
253
+ #
254
+ # @param [String] file - a file path in the cookbook
255
+ # @return [String] the path to the cookbook
221
256
  def cookbook_dir(file)
222
- Pathname.new(File.join(File.dirname(file),
223
- case File.basename(file)
224
- when "metadata.rb" then ""
225
- when /\.erb$/ then "../.."
226
- else ".."
227
- end)).cleanpath
257
+ @dir_cache ||= {}
258
+ abs_file = File.absolute_path(file)
259
+
260
+ # lookup the file in the cache has and return that if we find something
261
+ cook_val = @dir_cache[abs_file]
262
+ return cook_val unless cook_val.nil?
263
+
264
+ if file =~ /\.erb$/
265
+ # split each directory into an item in the array
266
+ dir_array = File.dirname(file).split(File::SEPARATOR)
267
+
268
+ # walk through the array of directories backwards until we hit the templates directory
269
+ position = -1
270
+ position -= 1 until dir_array[position] == "templates"
271
+
272
+ # go back 1 more position to get to the cookbook dir
273
+ position -= 1
274
+
275
+ # slice from the start to the cookbook dir and then join it all back to a string
276
+ cook_val = dir_array.slice(0..position).join(File::SEPARATOR)
277
+ else
278
+ # determine the difference to the root of the CB from our file's directory
279
+ relative_difference = case File.basename(file)
280
+ when "recipe.rb", "attribute.rb", "metadata.rb" then ""
281
+ else # everything else is 1 directory up ie. cookbook/recipes/default.rb
282
+ ".."
283
+ end
284
+
285
+ cook_val = Pathname.new(File.join(File.dirname(file), relative_difference)).cleanpath
286
+ end
287
+
288
+ @dir_cache[abs_file] = cook_val
289
+ cook_val
228
290
  end
229
291
 
230
292
  def dsl_method_for_file(file)
@@ -0,0 +1,6 @@
1
+ rule "FC116", "Cookbook depends on the deprecated compat_resource cookbook" do
2
+ tags %w{deprecated}
3
+ metadata do |ast, filename|
4
+ [file_match(filename)] if declared_dependencies(ast).include?("compat_resource")
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ rule "FC120", "Do not set the name property directly on a resource" do
2
+ tags %w{correctness}
3
+ recipe do |ast|
4
+ find_resources(ast).xpath('(.//command|.//fcall)[ident/@value="name"]')
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ rule "FC122", "Use the build_essential resource instead of the recipe" do
2
+ tags %w{correctness}
3
+ recipe do |ast|
4
+ ast.xpath("//command[ident/@value = 'include_recipe']/descendant::tstring_content[@value='build-essential' or @value='build-essential::default']")
5
+ end
6
+ end
@@ -1,4 +1,4 @@
1
1
  module FoodCritic
2
2
  # The current version of foodcritic
3
- VERSION = "13.0.1"
3
+ VERSION = "13.1.0"
4
4
  end
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+
3
+ describe "FC116" do
4
+ context "with metadata depending on compat_resource" do
5
+ metadata_file "name 'test'\ndepends 'compat_resource'"
6
+ it { is_expected.to violate_rule }
7
+ end
8
+
9
+ context "with metadata depending on foo" do
10
+ metadata_file "name 'test'\ndepends 'foo'"
11
+ it { is_expected.to_not violate_rule }
12
+ end
13
+
14
+ context "with metadata depending on nothing" do
15
+ metadata_file "name 'test'"
16
+ it { is_expected.to_not violate_rule }
17
+ end
18
+ end
@@ -0,0 +1,21 @@
1
+ require "spec_helper"
2
+
3
+ describe "FC120" do
4
+ context "with a resource that sets the name property" do
5
+ recipe_file <<-EOF
6
+ foo 'bar' do
7
+ name 'Administrator'
8
+ end
9
+ EOF
10
+ it { is_expected.to violate_rule }
11
+ end
12
+
13
+ context "with a resource that does not set the name property" do
14
+ recipe_file <<-EOF
15
+ foo 'bar' do
16
+ foo_name 'Administrator'
17
+ end
18
+ EOF
19
+ it { is_expected.not_to violate_rule }
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+
3
+ describe "FC122" do
4
+ context "with a recipe that includes build-essential" do
5
+ recipe_file "include_recipe 'build-essential'"
6
+ it { is_expected.to violate_rule }
7
+ end
8
+
9
+ context "with a recipe that includes build-essential::default" do
10
+ recipe_file "include_recipe 'build-essential::default'"
11
+ it { is_expected.to violate_rule }
12
+ end
13
+
14
+ context "with a recipe that includes build-essential-mycorp" do
15
+ recipe_file "include_recipe 'build-essential-mycorp'"
16
+ it { is_expected.to_not violate_rule }
17
+ end
18
+ end
@@ -16,6 +16,28 @@ describe FoodCritic::Linter do
16
16
  end
17
17
  end
18
18
 
19
+ describe "#cookbook_dir" do
20
+ it "given a root alias file the cookbook is correctly detected" do
21
+ expect(linter.send(:cookbook_dir, "./cookbook/recipe.rb").to_s).to eq "cookbook"
22
+ end
23
+
24
+ it "given the metadata.rb file the cookbook is correctly detected" do
25
+ expect(linter.send(:cookbook_dir, "./cookbook/metadata.rb").to_s).to eq "cookbook"
26
+ end
27
+
28
+ it "given a template nested multiple levels deep the cookbook is correctly detected" do
29
+ expect(linter.send(:cookbook_dir, "./cookbook/templates/foo/bar/file.erb").to_s).to eq "./cookbook"
30
+ end
31
+
32
+ it "given a template directly in the templates directory the cookbook is correctly detected" do
33
+ expect(linter.send(:cookbook_dir, "./cookbook/templates/file.erb").to_s).to eq "./cookbook"
34
+ end
35
+
36
+ it "given a standard recipe file the cookbook is correctly detected" do
37
+ expect(linter.send(:cookbook_dir, "./cookbook/recipes/default.rb").to_s).to eq "cookbook"
38
+ end
39
+ end
40
+
19
41
  describe "#check" do
20
42
  it "requires a cookbook_path, role_path or environment_path to be specified" do
21
43
  expect { linter.check({}) }.to raise_error ArgumentError
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foodcritic
3
3
  version: !ruby/object:Gem::Version
4
- version: 13.0.1
4
+ version: 13.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Crump
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-11 00:00:00.000000000 Z
11
+ date: 2018-04-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cucumber-core
@@ -337,9 +337,12 @@ files:
337
337
  - lib/foodcritic/rules/fc113.rb
338
338
  - lib/foodcritic/rules/fc114.rb
339
339
  - lib/foodcritic/rules/fc115.rb
340
+ - lib/foodcritic/rules/fc116.rb
340
341
  - lib/foodcritic/rules/fc117.rb
341
342
  - lib/foodcritic/rules/fc118.rb
342
343
  - lib/foodcritic/rules/fc119.rb
344
+ - lib/foodcritic/rules/fc120.rb
345
+ - lib/foodcritic/rules/fc122.rb
343
346
  - lib/foodcritic/template.rb
344
347
  - lib/foodcritic/version.rb
345
348
  - lib/foodcritic/xml.rb
@@ -429,9 +432,12 @@ files:
429
432
  - spec/functional/fc113_spec.rb
430
433
  - spec/functional/fc114_spec.rb
431
434
  - spec/functional/fc115_spec.rb
435
+ - spec/functional/fc116_spec.rb
432
436
  - spec/functional/fc117_spec.rb
433
437
  - spec/functional/fc118_spec.rb
434
438
  - spec/functional/fc119_spec.rb
439
+ - spec/functional/fc120_spec.rb
440
+ - spec/functional/fc122_spec.rb
435
441
  - spec/functional/root_aliases_spec.rb
436
442
  - spec/regression/cookbooks.txt
437
443
  - spec/regression/expected/activemq.txt
@@ -548,5 +554,5 @@ rubyforge_project:
548
554
  rubygems_version: 2.7.5
549
555
  signing_key:
550
556
  specification_version: 4
551
- summary: foodcritic-13.0.1
557
+ summary: foodcritic-13.1.0
552
558
  test_files: []