{"id":436,"date":"2015-10-03T12:24:06","date_gmt":"2015-10-03T12:24:06","guid":{"rendered":"http:\/\/www.scmgalaxy.com\/tutorials\/2015\/10\/03\/chef-code-analysis-using-foodcritic\/"},"modified":"2021-11-19T06:49:33","modified_gmt":"2021-11-19T06:49:33","slug":"chef-code-analysis-using-foodcritic","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/chef-code-analysis-using-foodcritic\/","title":{"rendered":"Chef Code Analysis using Foodcritic | Foodcritic Tutorial"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-3338 aligncenter\" src=\"http:\/\/www.scmgalaxy.com\/tutorials\/wp-content\/uploads\/2015\/10\/chef-code-analysis-using-fo-1.png\" alt=\"chef-code-analysis-using-foodcritic\" width=\"600\" height=\"400\" srcset=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2015\/10\/chef-code-analysis-using-fo-1.png 600w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2015\/10\/chef-code-analysis-using-fo-1-300x200.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p><strong>What is Foodcritic?<\/strong> Foodcritic is a static linting tool that analyzes all of the Ruby code that is authored in a cookbook against a number of rules, and then returns a list of violations. In another word, Foodcritic is a helpful lint tool you can use to check your Chef cookbooks for common problems.<\/p>\n<p><strong>We use Foodcritic to check cookbooks for common problems:<\/strong><br>\nStyle<br>\nCorrectness<br>\nSyntax<br>\nBest practices<br>\nCommon mistakes<br>\nDeprecations<\/p>\n<p><strong>Foodcritic does not <\/strong><br>\nFoodcritic does not validate the intention of a recipe, rather it evaluates the structure of the code, and helps enforce specific behavior, detect portability of recipes, identify potential run-time failures, and spot common anti-patterns.<\/p>\n<p>When Foodcritic returns a violation, this does not automatically mean the code needs to be changed. It is important to first understand the intention of the rule before making the changes it suggests.<\/p>\n<p><strong>Foodcritic has two goals:<\/strong><\/p>\n<p>To make it easier to flag problems in your Chef cookbooks that will cause Chef to blow up when you attempt to converge. This is about faster feedback. If you automate checks for common problems you can save a lot of time.<\/p>\n<p>To encourage discussion within the Chef community on the more subjective stuff &#8211; what does a good cookbook look like? Opscode have avoided being overly prescriptive which by and large I think is a good thing. Having a set of rules to base discussion on helps drive out what we as a community think is good style.<\/p>\n<p><strong>Foodcritic built-in Rules<\/strong><br>\nIt comes with 47 built-in rules that identify problems ranging from simple style inconsistencies to difficult to diagnose issues that will hurt in production. If you want to see the list of rules, please navigate the url as below;<br>\n<a href=\"http:\/\/www.foodcritic.io\/\" target=\"_blank\" rel=\"noopener\">http:\/\/www.foodcritic.io\/<\/a><\/p>\n<p><strong>Prerequisites<\/strong><br>\nFoodcritic runs on Ruby (MRI) 1.9.2+ which depending on your workstation setup may be a more recent version of Ruby than you have installed. The Ruby Version Manager (RVM) is a popular choice for running multiple versions of ruby on the same workstation, so you can try foodcritic out without running the risk of damaging your main install<\/p>\n<p><strong>Foodcritic installation<\/strong><\/p>\n<p><strong>Method 1<\/strong><br>\nInstall RVM as non-root user<\/p>\n<pre><code>$&nbsp;sudo \/etc\/init.d\/iptables stop OR sudo start ufw<\/code><\/pre>\n<p>$&nbsp;curl -s raw.github.com\/wayneeseguin\/rvm\/master\/binscripts\/rvm-installer | bash -s stable<br>\nOR<br>\n$&nbsp;sudo bash -s stable &lt; &lt;(curl -s https:\/\/raw.github.com\/wayneeseguin\/rvm\/master\/binscripts\/rvm-installer )<br>\nOR<br>\n$&nbsp;curl -s raw.github.com\/wayneeseguin\/rvm\/master\/binscripts\/rvm-installer | sudo bash -s stable<br>\nOR<br>\n$&nbsp;gpg &#8211;keyserver hkp:\/\/keys.gnupg.net &#8211;recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3<br>\nOR<br>\n$&nbsp;command curl -sSL https:\/\/rvm.io\/mpapis.asc | gpg &#8211;import &#8211;<\/p>\n<pre><code><\/code><\/pre>\n<p>$&nbsp;rvm get stable<br>\n$&nbsp;rvm install ruby-2.2.3<br>\n$&nbsp;gem install foodcritic<\/p>\n<p><strong>Method 2<\/strong><br>\nInstall ruby<\/p>\n<p>$&nbsp;sudo apt-get install ruby-2.2.3 (Ubantu)<br>\n$&nbsp;sudo yum install ruby-2.2.3 (rhel)<\/p>\n<p>Install foodcritic<br>\n&gt; gem install foodcritic<\/p>\n<p><strong>Method 3<\/strong><br>\nAlternatively install ChefDK which already includes foodcritic:<a href=\"https:\/\/downloads.getchef.com\/chef-dk\/\" target=\"_blank\" rel=\"noopener\"> https:\/\/downloads.getchef.com\/chef-dk\/<\/a><\/p>\n<p><strong>How to run Foodcritic?<\/strong><br>\nYou should now find you have a foodcritic command on your PATH. Run foodcritic to see what arguments it supports:<\/p>\n<p>foodcritic [cookbook_path]<br>\n-r, &#8211;[no-]repl Drop into a REPL for interactive rule editing.<br>\n-t, &#8211;tags TAGS Only check against rules with the specified tags.<br>\n-f, &#8211;epic-fail TAGS Fail the build if any of the specified tags are matched.<br>\n-C, &#8211;[no-]context Show lines matched against rather than the default summary.<br>\n-I, &#8211;include PATH Additional rule file path(s) to load.<br>\n-S, &#8211;search-grammar PATH Specify grammar to use when validating search syntax.<br>\n-V, &#8211;version Display version.<\/p>\n<p><strong>How to setup Foodcritic with Jenkins<\/strong><\/p>\n<p><strong>Configuring Jenkins to run foodcritic<\/strong><br>\nTo manually add a new job to Jenkins to check your cookbooks with foodcritic do the following:<\/p>\n<ol>\n<li>Ensure you have Ruby 1.9.2+ and the foodcritic gem installed on the box running Jenkins.<\/li>\n<li>You\u2019ll probably need to install the Git plugin. In Jenkins select \u201cManage Jenkins\u201d -&gt; \u201cManage Plugins\u201d. Select the \u201cAvailable\u201d tab. Check the checkbox next to the Git Plugin and click the \u201cInstall without restart\u201d button.<\/li>\n<li>In Jenkins select \u201cNew Job\u201d. Enter a name for the job \u201cmy-cookbook\u201d, select \u201cBuild a free-style software project\u201d and click \u201cOK\u201d.<\/li>\n<li>On the resulting page select \u201cGit\u201d under \u201cSource Code Management\u201d and enter the URL for your repo.<\/li>\n<li>Check the checkbox \u201cPoll SCM\u201d under \u201cBuild Triggers\u201d.<\/li>\n<li>Click \u201cAdd Build Step\u201d -&gt; \u201cExecute shell\u201d under \u201cBuild\u201d. This is where we will call foodcritic.<\/li>\n<li>Assuming you are using rvm enter the following as the command:<\/li>\n<li>#!\/usr\/bin\/env rvm-shell 1.9.3<br>\nfoodcritic .<\/li>\n<li>Click \u201cSave\u201d.<\/li>\n<li>Cool, we\u2019ve created your new job. Now lets see if it works. Click \u201cBuild Now\u201d on the left-hand side.<\/li>\n<li>You can click the build progress bar to be taken directly to the console output.<\/li>\n<li>After a moment you should see that the build has been successful and foodcritic warnings (if any) are shown in your console output.<\/li>\n<li>Yes, for maximum goodness you should be automating all this with Chef. \ud83d\ude42<\/li>\n<li>For more information refer to the instructions for building a \u201cfree-style software project\u201d here:<br>\nhttps:\/\/wiki.jenkins-ci.org\/display\/JENKINS\/Building+a+software+project<\/li>\n<li>See also this blog post about rvm-shell which ensures you have the right version of Ruby loaded when trying to build with foodcritic:<br>\nhttp:\/\/blog.ninjahideout.com\/posts\/rvm-improved-support-for-hudson<\/li>\n<\/ol>\n<p><strong>Failing the build<\/strong><br>\nThe above is a start, but we\u2019d also like to fail the build if there are any warnings that might stop the cookbook from working.<\/p>\n<p>CI is only useful if people will act on it. Lets start by only failing the build when there is a correctness problem that would likely break our Chef run. We\u2019ll continue to have the other warnings available for reference in the console log but only correctness issues will fail the build.<\/p>\n<p>Select the \u201cmy-cookbook\u201d job in Jenkins and click \u201cConfigure\u201d.<\/p>\n<p>Scroll down to our \u201cExecute shell\u201d command and change it to look like the following:<\/p>\n<p>#!\/usr\/bin\/env rvm-shell 1.9.3<br>\nfoodcritic -f correctness .<br>\nClick \u201cSave\u201d and then \u201cBuild Now\u201d.<\/p>\n<p><strong>More complex expressions<\/strong><br>\nFoodcritic supports more complex expressions with the standard Cucumber tag syntax. For example:<\/p>\n<p>#!\/usr\/bin\/env rvm-shell 1.9.3<br>\nfoodcritic -f any -f ~FC014 .<br>\nHere we use any to fail the build on any warning, but then use the tilde ~ to exclude FC014. The build will fail on any warning raised, except FC014.<\/p>\n<p>You can find more detail on Cucumber tag expressions at the Cucumber wiki:<\/p>\n<p><a href=\"https:\/\/github.com\/cucumber\/cucumber\/wiki\/Tags\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/cucumber\/cucumber\/wiki\/Tags<\/a><\/p>\n<p><strong>Tracking warnings over time<\/strong><br>\nThe Jenkins Warnings plugin can be configured to understand foodcritic output and track your cookbook warnings over time.<\/p>\n<p>You\u2019ll need to install the Warnings plugin. In Jenkins select \u201cManage Jenkins\u201d -&gt; \u201cManage Plugins\u201d. Select the \u201cAvailable\u201d tab. Check the checkbox next to the Warnings Plugin and click the \u201cInstall without restart\u201d button.<\/p>\n<p>From \u201cManage Jenkins\u201d select \u201cConfigure System\u201d. Scroll down to the \u201cCompiler Warnings\u201d section and click the \u201cAdd\u201d button next to \u201cParsers\u201d.<\/p>\n<p>Enter \u201cFoodcritic\u201d in the Name field.<\/p>\n<p>Enter the following regex in the \u201cRegular Expression\u201d field:<\/p>\n<p>^(FC[0-9]+): (.*): ([^:]+):([0-9]+)$<\/p>\n<p><strong>Enter the following Groovy script into the \u201cMapping Script\u201d field:<\/strong><\/p>\n<p>import hudson.plugins.warnings.parser.Warning<\/p>\n<p>String fileName = matcher.group(3)<br>\nString lineNumber = matcher.group(4)<br>\nString category = matcher.group(1)<br>\nString message = matcher.group(2)<\/p>\n<p>return new Warning(fileName, Integer.parseInt(lineNumber), &#8220;Chef Lint Warning&#8221;, category, message);<\/p>\n<p><strong>To test the match, enter the following example message in the \u201cExample Log Message\u201d field:<\/strong><\/p>\n<p>FC001: Use strings in preference to symbols to access node attributes: .\/recipes\/innostore.rb:30<br>\nClick in the \u201cMapping Script\u201d field and you should see the following appear below the Example Log Message:<\/p>\n<p>One warning found<br>\nfile name: .\/recipes\/innostore.rb<br>\nline number: 30<br>\npriority: Normal Priority<br>\ncategory: FC001<br>\ntype: Chef Lint Warning<br>\nmessage: Use strings in prefe[&#8230;]ols to access node attributes<br>\nCool, it\u2019s parsed our example message successfully. Click \u201cSave\u201d to save the parser.<\/p>\n<p>Select the \u201cmy-cookbook\u201d job in Jenkins and click \u201cConfigure\u201d.<\/p>\n<p>Check the checkbox next to \u201cScan for compiler warnings\u201d underneath \u201cPost-build Actions\u201d.<\/p>\n<p>Click the \u201cAdd\u201d button next to \u201cScan console log\u201d and select our \u201cFoodcritic\u201d parser from the drop-down list.<\/p>\n<p>Click the \u201cAdvanced\u2026\u201d button and check the \u201cRun always\u201d checkbox.<\/p>\n<p>Click \u201cSave\u201d and then \u201cBuild Now\u201d.<\/p>\n<p>Add the bottom of the console log you should see something similar to this:<\/p>\n<p>[WARNINGS] Parsing warnings in console log with parsers [Foodcritic]<br>\n[WARNINGS] Foodcritic : Found 48 warnings.<br>\nClick \u201cBack to Project\u201d. Once you have built the project a couple of times the warnings trend will appear here.<\/p>\n<p><strong>Reference:<\/strong><br>\n<a href=\"http:\/\/acrmp.github.io\/foodcritic\/\" target=\"_blank\" rel=\"noopener\">http:\/\/acrmp.github.io\/foodcritic\/<\/a><br>\n<a href=\"https:\/\/docs.chef.io\/foodcritic.html\" target=\"_blank\" rel=\"noopener\">https:\/\/docs.chef.io\/foodcritic.html<\/a><br>\n<a href=\"http:\/\/www.foodcritic.io\/\" target=\"_blank\" rel=\"noopener\">http:\/\/www.foodcritic.io\/<\/a><br>\n<a href=\"https:\/\/atom.io\/packages\/linter-foodcritic\" target=\"_blank\" rel=\"noopener\">https:\/\/atom.io\/packages\/linter-foodcritic<\/a><br>\n<a href=\"http:\/\/www.slideshare.net\/harthoover\/rapid-chef-development-with-berkshelf-testkitchen-and-foodcritic\" target=\"_blank\" rel=\"noopener\">http:\/\/www.slideshare.net\/harthoover\/rapid-chef-development-with-berkshelf-testkitchen-and-foodcritic<\/a><\/p>\n\n<div class=\"epyt-gallery\" data-currpage=\"1\" id=\"epyt_gallery_28965\"><figure class=\"wp-block-embed wp-block-embed-youtube is-type-video is-provider-youtube epyt-figure\"><div class=\"wp-block-embed__wrapper\"><iframe loading=\"lazy\"  id=\"_ytid_37131\"  width=\"760\" height=\"427\"  data-origwidth=\"760\" data-origheight=\"427\" src=\"https:\/\/www.youtube.com\/embed\/?enablejsapi=1&#038;autoplay=0&#038;cc_load_policy=0&#038;cc_lang_pref=&#038;iv_load_policy=1&#038;loop=0&#038;rel=1&#038;fs=1&#038;playsinline=0&#038;autohide=2&#038;theme=dark&#038;color=red&#038;controls=1&#038;disablekb=0&#038;\" class=\"__youtube_prefs__  no-lazyload\" title=\"YouTube player\"  data-epytgalleryid=\"epyt_gallery_28965\"  allow=\"fullscreen; accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen data-no-lazy=\"1\" data-skipgform_ajax_framebjll=\"\"><\/iframe><\/div><\/figure><div class=\"epyt-gallery-list\"><div>Sorry, there was a YouTube error.<\/div><\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>What is Foodcritic? Foodcritic is a static linting tool that analyzes all of the Ruby code that is authored in a cookbook against a number of rules, and then returns a list of violations. In another word, Foodcritic is a helpful lint tool you can use to check your Chef cookbooks for common problems. We&#8230;<\/p>\n","protected":false},"author":1,"featured_media":3337,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","_joinchat":[],"footnotes":""},"categories":[88],"tags":[517,407,1457,1461,1003,784,1458,1456,1459,1460,545,593],"class_list":["post-436","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-chef","tag-analysis","tag-chef","tag-chef-code-analysis","tag-chef-code-analysis-using-foodcritic","tag-code","tag-code-analysis","tag-code-analysis-using-foodcritic","tag-foodcritic","tag-foodcritic-guide","tag-foodcritic-tutorials","tag-how","tag-process"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/436","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=436"}],"version-history":[{"count":3,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/436\/revisions"}],"predecessor-version":[{"id":25803,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/436\/revisions\/25803"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media\/3337"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=436"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=436"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=436"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}