cookbook from the Fundamentals Course • We’ll show you how to run cookbooks in a sandbox environment mirroring production with Test Kitchen • We’ll show you how to detect suspicious cookbook code with Foodcritic & RuboCop • We’ll show you how to produce runnable documentation with ChefSpec 4 Wednesday, April 30, 14
tests for your infrastructure” -Ezra Zygmuntowicz, Co-Founder Engine Yard http://www.akitaonrails.com/2008/6/5/railsconf-2008-brazil-rails-podcast-special-edition#.U0HfiF7Ed-8 Wednesday, April 30, 14
you type in cookbook code: • Foodcritic analyzes your Chef style • RuboCop analyzes your Ruby coding technique • Before you deploy to a test node: • ChefSpec helps you document and organize your code • After you deploy to a test node: • Serverspec verifies a cookbook behaves as intended 21 Wednesday, April 30, 14
whoami i-am-a-workstation This is an example of a command to run on your workstation user@hostname:~$ whoami i-am-a-chef-node This is an example of a command to run on your target node via SSH. 23 Wednesday, April 30, 14
'uvo1qrwls0jdgs3blvt.vm.cld.sr (69.195.232.110)' can't be established. RSA key fingerprint is d9:95:a3:b9:02:27:e9:cd: 74:e4:a2:34:23:f5:a6:8b. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'uvo1qrwls0jdgs3blvt.vm.cld.sr, 69.195.232.110' (RSA) to the list of known hosts. [email protected]'s password: Last login: Mon Jan 6 16:26:24 2014 from host86-145-117-53.range86-145.btcentralplus.com [chef@CentOS63 ~]$ 33 Wednesday, April 30, 14
virtual machine (VM) or server that you’ll use for the lab exercises • The IP address or public hostname • An application for establishing an ssh connection • 'sudo' or 'root' permissions on the VM 34 Wednesday, April 30, 14
kernel extensions needed for Docker (64-bit only). • Ubuntu is recommended if you are using a VM. The Enterprise Linux package uses the 3.14 kernel which has issues working with the VMware and VirtualBox guest tools. 36 Wednesday, April 30, 14
base OS with Docker: • Ubuntu Server: https://github.com/misheska/basebox-packer/blob/ master/template/ubuntu/ubuntu1204-docker.json • Vagrant Cloud: vagrant init learningchef/ubuntu1204-‐docker 37 Wednesday, April 30, 14
Linux % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 14398 100 14398 0 0 56535 0 --:--:-- --:--:-- --:--:-- 78250 Downloading Chef for ubuntu... Installing Chef installing with dpkg... Selecting previously unselected package chef. (Reading database ... 78644 files and directories currently installed.) Unpacking chef (from .../chef_11.12.2-1_amd64.deb) ... Setting up chef (11.12.2-1) ... Thank you for installing Chef! 41 Wednesday, April 30, 14
installed via an operating system-specific package ("omnibus installer") • Installation includes • The Ruby language - used by Chef • knife - Command line tool for administrators • chef-client - Client application • ohai - System profiler • ...and more 42 Wednesday, April 30, 14
created in the Chef Fundamentals training, adding tests: https://github.com/learnchef/chef-fundamentals-repo/ tree/master/cookbooks/apache 61 Wednesday, April 30, 14
you Fetching gem metadata from https://rubygems.org/.......... Fetching gem metadata from https://rubygems.org/.. Installing mixlib-shellout (1.3.0) Installing net-ssh (2.8.0) Installing net-scp (1.1.2) Installing safe_yaml (1.0.2) Installing thor (0.19.1) Installing test-kitchen (1.2.1) Installing kitchen-docker (1.0.0) Using bundler (1.1.5) Your bundle is complete! It was installed into ./vendor/bundle 88 Wednesday, April 30, 14
• -‐-‐path option passed to bundle install overrides system gems by installing Gemfile gems locally • Bundler docs recommend using vendor/bundle Wednesday, April 30, 14
• They set reasonable defaults for all attributes used • Test Kitchen is designed to run a cookbook in isolation to give you feedback on attribute use 109 Wednesday, April 30, 14
this class • Test Kitchen supports injection of test attributes • We’ll supply the correct attribute in the .kitchen.yml configuration file 110 Wednesday, April 30, 14
.kitchen.yml file. • .kitchen.yml is a tab-free zone - you will get errors if you try to use tabs. Set your editor accordingly. 112 Wednesday, April 30, 14
Starting Kitchen (v1.2.1) -----> Converging <default-centos-64>... Preparing files for transfer Preparing current project directory as a cookbook Removing non-cookbook files before transfer Transfering files to <default-centos-64> [2014-04-07T02:40:01-04:00] INFO: Forking chef instance to converge... Starting Chef Client, version 11.10.4 .... 114 Wednesday, April 30, 14
Starting Kitchen (v1.2.1) -----> Converging <default-centos-64>... Preparing files for transfer Preparing current project directory as a cookbook Removing non-cookbook files before transfer Transfering files to <default-centos-64> [2014-04-07T02:40:01-04:00] INFO: Forking chef instance to converge... Starting Chef Client, version 11.10.4 .... [2014-04-07T02:40:03-04:00] INFO: Report handlers complete Chef Client finished, 5/10 resources updated in 2.52587913 seconds Finished converging <default-centos-64> (0m4.15s). -----> Kitchen is finished. (0m4.22s) 115 WIN Wednesday, April 30, 14
sent to you are part of the class registration. • Chapter 1 covers Test Kitchen and .kitchen.yml format in more detail. • Appendix provides sample .kitchen.yml configs 116 Wednesday, April 30, 14
with its versioning scheme. You can take advantage of this to choose a version constraint to lock down the gem in your application. http://guides.rubygems.org/patterns/#declaring_dependencies Wednesday, April 30, 14
1.MAJOR version when you make incompatible API changes, 2.MINOR version when you add functionality in a backwards- compatible manner, and 3.PATCH version when you make backwards-compatible bug fixes. Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format. http://guides.rubygems.org/patterns/#semantic_versioning Wednesday, April 30, 14
gem exist: ▪Version 2.1.0 — Baseline ▪Version 2.2.0 — Introduced some new (backward compatible) features. ▪Version 2.2.1 — Removed some bugs ▪Version 2.2.2 — Streamlined your code ▪Version 2.3.0 — More new features (but still backwards compatible). ▪Version 3.0.0 — Reworked the interface. Code written to version 2.x might not work. http://guides.rubygems.org/patterns/#semantic_versioning Wednesday, April 30, 14
‘responds on port 80’ do expect(port 80).to be_listening ‘tcp’ end end Expect Form One-Liner Should Form describe ‘clowns site’ do describe port(80) do it { should be_listening.with(‘tcp’) } end end Wednesday, April 30, 14
use expect vs. should is epic: http://myronmars.to/n/dev-blog/2012/06/rspecs-new- expectation-syntax ...and pointless. Use whatever makes the most sense to you. There are some technical limitations to the ‘should’ form, but if you stick to the “one-liner should” syntax, they are essentially interchangeable. Wednesday, April 30, 14
will look in the test/ integration directory for test-related files • For convenience, Test Kitchen creates this directory when you run kitchen init Wednesday, April 30, 14
directories underneath test/integration • First directory name underneath test/integration should match the suite name: └── test/ └── integration/ └── <suite_name>/ Wednesday, April 30, 14
test plugin, as Test Kitchen many different kinds of test plugins. A test plugin is called a busser. We’ll be using the busser directory called serverspec. └── test/ └── integration/ └── default/ └── serverspec/ Wednesday, April 30, 14
it requires yet another directory level to denote the hostname. We won’t be using this capability, so it should be localhost └── test/ └── integration/ └── default/ └── serverspec/ └── localhost/ Wednesday, April 30, 14
site' do it 'responds on port 80' do expect(port 80).to be_listening 'tcp' end end OPEN IN EDITOR: apache/test/integration/default/serverspec/clown_spec.rb Wednesday, April 30, 14
run kitchen setup • kitchen setup loads and configures the file necessary to run test plugins on the node • The component that manages Test Kitchen plugins is called Busser Wednesday, April 30, 14
describe 'clowns site' do it 'responds on port 85' do expect(port 85).to be_listening 'tcp' end end OPEN IN EDITOR: apache/test/integration/default/serverspec/clown_spec.rb Wednesday, April 30, 14
Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/ suites/serverspec/localhost/clown_spec.rb --color --format documentation clowns site responds on port 85 (FAILED - 1) Failures: 1) clowns site responds on port 85 Failure/Error: expect(port 85).to be_listening 'tcp' netstat -tunl | grep -- :85\ expected Port "85" to be listening "tcp" # /tmp/busser/suites/serverspec/localhost/clown_spec.rb:7:in `block (2 levels) in <top (required)>' Finished in 0.00718 seconds 1 example, 1 failure ... 191 Wednesday, April 30, 14
Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/ suites/serverspec/localhost/clown_spec.rb --color --format documentation clowns site responds on port 85 (FAILED - 1) Failures: 1) clowns site responds on port 85 Failure/Error: expect(port 85).to be_listening 'tcp' netstat -tunl | grep -- :85\ expected Port "85" to be listening "tcp" # /tmp/busser/suites/serverspec/localhost/clown_spec.rb:7:in `block (2 levels) in <top (required)>' Finished in 0.00718 seconds 1 example, 1 failure ... 192 WIN FAIL Wednesday, April 30, 14
describe 'clowns site' do it 'responds on port 80' do expect(port 80).to be_listening 'tcp' end end OPEN IN EDITOR: apache/test/integration/default/serverspec/clown_spec.rb Wednesday, April 30, 14
site' do it 'responds on port 81' do expect(port 81).to be_listening 'tcp' end end OPEN IN EDITOR: apache/test/integration/default/serverspec/bear_spec.rb Wednesday, April 30, 14
... ----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/ embedded/bin/rspec /tmp/busser/suites/serverspec/localhost/bear_spec.rb /tmp/busser/ suites/serverspec/localhost/clown_spec.rb --color --format documentation bears site responds on port 81 clowns site responds on port 80 Finished in 0.00889 seconds 2 examples, 0 failures ... 199 Wednesday, April 30, 14
a file called spec_helper.rb in test/integration/default/ serverspec • Test Kitchen automatically looks for spec_helper.rb in test/integration/default/ serverspec Wednesday, April 30, 14
it 'responds on port 80' do expect(port 80).to be_listening 'tcp' end end OPEN IN EDITOR: apache/test/integration/default/serverspec/clown_spec.rb Wednesday, April 30, 14
it 'responds on port 81' do expect(port 81).to be_listening 'tcp' end end OPEN IN EDITOR: apache/test/integration/default/serverspec/bear_spec.rb Wednesday, April 30, 14
w/spec_helper.rb ... ----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/ embedded/bin/rspec /tmp/busser/suites/serverspec/localhost/bear_spec.rb /tmp/busser/ suites/serverspec/localhost/clown_spec.rb --color --format documentation bears site response on port 81 clowns site responds on port 80 Finished in 0.00889 seconds 2 examples, 0 failures ... 205 Wednesday, April 30, 14
w/spec_helper.rb ... ----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/ embedded/bin/rspec /tmp/busser/suites/serverspec/localhost/bear_spec.rb /tmp/busser/ suites/serverspec/localhost/clown_spec.rb --color --format documentation bears site response on port 81 clowns site responds on port 80 Finished in 0.00889 seconds 2 examples, 0 failures ... 206 WIN Wednesday, April 30, 14
added checks to verify that the test node is listening on ports 80 and 81, we haven’t verified that users see the right content when they visit these sites. • Let’s use the command resource with the return_stdout matcher to do a simple check with curl to verify that port 80 is clowns and port 81 is bears. Wednesday, April 30, 14
it 'responds on port 80' do expect(port 80).to be_listening 'tcp' end it 'returns clowns in the HTML body' do expect(command 'curl localhost:80').to \ return_stdout(/clowns/) end end OPEN IN EDITOR: apache/test/integration/default/serverspec/clown_spec.rb Wednesday, April 30, 14
it 'responds on port 81' do expect(port 81).to be_listening 'tcp' end it 'returns bears in the HTML body' do expect(command 'curl localhost:81').to \ return_stdout(/bears/) end end OPEN IN EDITOR: apache/test/integration/default/serverspec/bear_spec.rb Wednesday, April 30, 14
-----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/ suites/serverspec/localhost/bear_spec.rb /tmp/busser/suites/serverspec/localhost/clown_spec.rb --color -- format documentation bears site responds on port 81 returns bears in the HTML body clowns site responds on port 80 returns clowns in the HTML body Finished in 0.0293 seconds 4 examples, 0 failures Finished verifying <default-centos-64> (0m1.73s). -----> Kitchen is finished. (0m1.79s) ... 212 WIN Wednesday, April 30, 14
require that Serverspec detect the OS so it can run the correct command for your platform expect(package 'httpd').to be_installed • You’ll need to add an extra Helper to spec_helper.rb Wednesday, April 30, 14
'has apache installed' do expect(package 'httpd').to be_installed end end OPEN IN EDITOR: apache/test/integration/default/serverspec/default_spec.rb Wednesday, April 30, 14
-----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/ suites/serverspec/localhost/bear_spec.rb /tmp/busser/suites/serverspec/localhost/clown_spec.rb --color -- format documentation bears site responds on port 81 returns bears in the HTML body clowns site responds on port 80 returns clowns in the HTML body Finished in 0.0293 seconds 4 examples, 0 failures Finished verifying <default-centos-64> (0m1.73s). -----> Kitchen is finished. (0m1.79s) ... 216 WIN Wednesday, April 30, 14
all the previous actions you’ve learned so far into one command. It runs the following commands in sequence: • kitchen destroy (if necessary) •kitchen create •kitchen converge •kitchen setup •kitchen verify •kitchen destroy Wednesday, April 30, 14
to be used as a final check on a fresh image before committing changes to source control and/or to be used in a Continuous Integration environment like Jenkins. Wednesday, April 30, 14
custom Serverspec matchers used in jenkins/test/integration: •describe jenkins_job('my-‐project') do it { should be_a_jenkins_job } end 221 Wednesday, April 30, 14
to share test data between serverspec suites • Directory specified in data/path is copied to /tmp/ kitchen/data on guest • Reason for weird require_relative directive in tests that use custom Serverspec matchers: require_relative '../../../kitchen/data/ spec_helper' 223 Wednesday, April 30, 14
for managing sandbox environments and truly verifying that a cookbook produces the intended results • But it does require spinning up an instance and performing a full Chef converge, which can take a long time • Use Test Kitchen judiciously. The other tools can provide more limited forms of feedback faster. 225 Wednesday, April 30, 14
your Chef coding style • It is designed to be used as you are writing Chef code - how’s that for freaking fast! • Written by Andrew Crump http://acrmp.github.com/footcritic 227 Wednesday, April 30, 14
your development workstation so you can give it a spin • Add Foodcritic to your Gemfile • Install the app with bundle install 228 Wednesday, April 30, 14
233 FC003: Check whether you are running with chef server before using server-specific features: cookbooks/apache/recipes/ip-logger.rb:1 FC008: Generated cookbook metadata needs updating: cookbooks/apache/metadata.rb:2 FC008: Generated cookbook metadata needs updating: cookbooks/apache/metadata.rb:3 Wednesday, April 30, 14
set of checks called rules • Foodcritic rules are documented at http:// acrmp.github.io/foodcritic/ • The default rules are a good start, and you can add new rules of your own easily 236 Wednesday, April 30, 14
rights reserved' description 'Installs/Configures apache' long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) version '0.2.0' Wednesday, April 30, 14
used to specify a list of rules for foodcritic to use •foodcritic -‐-‐tags FC001,FC002,FC008 • The tilde (~) modifier can be used to ignore specific rules •foodcritic -‐-‐tags ~FC003 Wednesday, April 30, 14
to check for issues that caused production outages/ performance degradation. • Good example for how to create your own custom rules • Documented here: https://github.com/etsy/foodcritic-rules Wednesday, April 30, 14
used with :upgrade action • ETSY002 - Execute resource used to run git commands • ETSY003 - Execute resource used to run curl or wget commands • ETSY004 - Execute resource defined without conditional or action :nothing • ETSY005 - Action :restart sent to a core service • ETSY006 - Execute resource used to run chef-provided command • ETSY007 - Package or yum_package resource used to install core package without specific version number 251 Wednesday, April 30, 14
Including Custom Rules ETSY005: Action :restart sent to a core service: ./recipes/default.rb:19 ETSY005: Action :restart sent to a core service: ./recipes/default.rb:32 ETSY007: Package or yum_package resource used to install core package without specific version number: ./recipes/default.rb:10 254 Wednesday, April 30, 14
to Ruby would like some guidance on how to write idiomatic Ruby • Get the same kind of feedback for Ruby using RuboCop that you get for Chef Code using Foodcritic (Chef code is Ruby) 257 Wednesday, April 30, 14
guide: https://github.com/bbatsov/ruby-style-guide • Looks at cookbooks for Ruby best practices, not the Chef DSL - that’s Foodcritic 259 Wednesday, April 30, 14
on your development workstation so you can give it a spin • Add RuboCop to your Gemfile • Install the app with bundle install 260 Wednesday, April 30, 14
C: Prefer single-quoted strings when you don't need string interpolation or special symbols. default["apache"]["sites"]["bears"] = { "port" => 81 } ^^^^^^^ attributes/default.rb:3:28: C: Prefer single-quoted strings when you don't need string interpolation or special symbols. default["apache"]["sites"]["bears"] = { "port" => 81 } ^^^^^^^ attributes/default.rb:3:41: C: Prefer single-quoted strings when you don't need string interpolation or special symbols. default["apache"]["sites"]["bears"] = { "port" => 81 } ^^^^^^ 7 files inspected, 52 offenses detected 265 Wednesday, April 30, 14
each item on the offense list • It also shows you what config setting can be used to mask each offense, which we’ll need to do for some of these, because Chef code conventions vary slightly from the Rubocop community standards 266 Wednesday, April 30, 14
single-quoted strings when you don't need string interpolation or special symbols. default["apache"]["sites"]["bears"] = { "port" => 81 } ^^^^^^^ attributes/default.rb:3:41: C: Prefer single-quoted strings when you don't need string interpolation or special symbols. default["apache"]["sites"]["bears"] = { "port" => 81 } ^^^^^^ 7 files inspected, 52 offenses detected Created rubocop-todo.yml. Run `rubocop --config rubocop-todo.yml`, or add inherit_from: rubocop-todo.yml in a .rubocop.yml file. 267 Wednesday, April 30, 14
RuboCop (similar to .kitchen.yml in Test Kitchen) • We’ll add a settings to ignore things, similar to what we did for Foodcritic, that don’t make as much sense for Chef. • Settings are documented in the RuboCop README: https://github.com/bbatsov/rubocop/blob/master/ README.md • Cop is the RuboCop equivalent of a rule 268 Wednesday, April 30, 14
the Cops from rubocop- todo.yml to .rubocop.yml for things that match Chef community standards (as opposed to the Ruby community standards) 272 Wednesday, April 30, 14
one space between the method name and the first argument. maintainer 'Mischa Taylor' ^^^^^^^ metadata.rb:4:8: C: Put one space between the method name and the first argument. license 'All rights reserved' ^^^^^^^^^^ metadata.rb:5:12: C: Put one space between the method name and the first argument. description 'Installs/Configures apache' ^^^^^^ metadata.rb:7:8: C: Put one space between the method name and the first argument. version '0.2.0' ^^^^^^^^^^ 7 files inspected, 11 offenses detected 281 Wednesday, April 30, 14
and diverts focus from more important changes • Even with Git, trailing whitespace can make merge conflicts more difficult to resolve 284 Wednesday, April 30, 14
to run RuboCop inside the editor (including Vim, GNU Emacs and Sublime Text). So you can get feedback even faster. • RuboCop includes great docs on editor configuration (which work for Foodcritic as well): https://github.com/bbatsov/rubocop#editor- integration Wednesday, April 30, 14
in something that you can’t execute is freaking hard! • While fixing bugs before writing code is cheap, finding them is expensive 287 Wednesday, April 30, 14
primary purpose is to help document and organize your code. • As a side effect, you’ll end up with a set of tests which can also be used to uncover bugs when changes are made. • Plus, your cookbook code will be improved when it is guided by tests. 288 Wednesday, April 30, 14
= ChefSpec::Runner.new.converge('apache::default') it ‘installs apache2’ do expect(chef_run).to install_package(‘httpd’) end end Wednesday, April 30, 14
httpd package installation • It just verifies the cookbook syntax that it instructs Chef to install the package • Good enough for well-tested primitives like the package resource 301 Wednesday, April 30, 14
= ChefSpec::Runner.new.converge('apache::default') it 'installs apache2' do expect(chef_run).to install_package('httpd') end end Test apache::default recipe 312 Wednesday, April 30, 14
= ChefSpec::Runner.new.converge('apache::default') it 'installs apache2' do expect(chef_run).to install_package('badhttpd') end end Did it really check anything? 315 Wednesday, April 30, 14
Failures: 1) apache::default installs apache2 Failure/Error: expect(chef_run).to install_package('badhttpd') expected "package[badhttpd]" with action :install to be in Chef run. Other package resources: package[httpd] # ./spec/default_spec.rb:7:in `block (2 levels) in <top (required)>' Finished in 0.00044 seconds 1 example, 1 failure 316 Wednesday, April 30, 14
= ChefSpec::Runner.new.converge('apache::default') it 'installs apache2' do expect(chef_run).to install_package('httpd') end end Restore back to working 317 Wednesday, April 30, 14
let(:chef_run) \ { ChefSpec::Runner.new.converge(described_recipe) } it 'installs apache2' do expect(chef_run).to install_package('httpd') end end Lazy evaluation Wednesday, April 30, 14
\ { ChefSpec::Runner.new.converge(described_recipe) } it 'installs apache2' do expect(chef_run).to install_package('httpd') end end Lazy evaluation 321 Wednesday, April 30, 14
describe 'apache::default' do let (:chef_run) \ { ChefSpec::Runner.new.converge(described_recipe) } it 'installs apache2' do expect(chef_run).to install_package('httpd') end end Adding resource report 324 Wednesday, April 30, 14
describe 'apache::default' do let(:chef_run) \ { ChefSpec::Runner.new.converge(described_recipe) } ... it 'creates clowns.conf' do expect(chef_run).to \ create_file('/etc/httpd/conf.d/clowns.conf') end end Checking clowns.conf files 328 Wednesday, April 30, 14
runnable documentation • It isn’t actually performing a Chef run to verify that clowns.conf was created • Instead it is just verifying that you told Chef to create the clowns.conf via the file resource, which you never did - you used the template resource Wednesday, April 30, 14
describe 'apache::default' do let(:chef_run) { ChefSpec::Runner.new.converge(described_recipe) } ... it 'creates clowns.conf' do expect(chef_run).to \ create_template('/etc/httpd/conf.d/clowns.conf') end end Checking clowns.conf file 333 Wednesday, April 30, 14
spec/ subtree, looking for tests, so you can create any directory structure you like underneath • We’ll move default_spec.rb to spec/recipes Wednesday, April 30, 14
(:chef_run) \ { ChefSpec::Runner.new.converge(described_recipe) } it 'installs apache2' do expect(chef_run).to install_package('httpd') end it 'creates clowns.conf' do expect(chef_run).to \ create_template('/etc/httpd/conf.d/clowns.conf') end end Checking clowns.conf file 340 Wednesday, April 30, 14
- Writing new Guardfile to /home/vagrant/ chef-fundamentals-repo/cookbooks/apache/Guardfile 02:45:32 - INFO - rubocop guard added to Guardfile, feel free to edit it 351 Wednesday, April 30, 14
https://github.com/guard/guard#readme guard :rubocop do watch(%r{.+\.rb$}) watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) } end Wednesday, April 30, 14
foodcritic-chefspec/ Foodcritic and Guard: Serverspec and Guard: https://micgo.net/serverspec-guard-and-test-kitchen-testing- servers-like-a-boss/ Wednesday, April 30, 14
the command line steps needed to create an app • Perfect for capturing all the commands you’ve learned in this class so others can run them easily, or in your continuous integration system (Jenkins, Bamboo, TeamCity, etc.) 361 Wednesday, April 30, 14
Rubocop' task :rubocop do sh 'bundle exec rubocop' end desc 'Run Chef style checks with Foodcritic' task :foodcritic do sh 'bundle exec foodcritic -t ~FC003 .' end Foodcritic Task 376 Wednesday, April 30, 14
it shouldn’t • Does not expose command line option to exclude directories: https://github.com/acrmp/foodcritic/issues/148 • When fixed, this should work: bundle exec foodcritic -‐X spec -‐t ~FC003 . 379 Wednesday, April 30, 14
Rubocop' task :rubocop do sh 'bundle exec rubocop' end require 'foodcritic' desc 'Run Chef style checks with Foodcritic' FoodCritic::Rake::LintTask.new(:foodcritic) do |t| t.options = { tags: ['~FC003'], excludes: ['test', 'spec', 'features'] } end Workaround - Use Ruby 380 Wednesday, April 30, 14
default • default runs when no parameters are supplied to rake • default (as well as any other task) can point to a list of other task names to execute task :default => [:foodcritic] 381 Wednesday, April 30, 14
'Run Ruby style checks with Rubocop' task :rubocop do sh 'bundle exec rubocop' end require 'foodcritic' desc 'Run Chef style checks with Foodcritic' FoodCritic::Rake::LintTask.new(:foodcritic) do |t| t.options = { tags: ['~FC003'], excludes: ['test', 'spec', 'features' ] } end Foodcritic Task 382 Wednesday, April 30, 14