Today I Learned

7 posts by arturopie

Chef override attributes vs chef-client -j switch

When applying recipes via chef-client, you can override attributes via the --json-attributes (or -j) switch. However, the override_attributes option on roles, environments and recipes has higher precedence over the --json-attributes switch.

For more info about Chef attribute precedence, use this as a reference. The attributes set via --json-attributes are normal attribute types.

Fixing ZDT Deploys with Monitoring-Driven Develop.

We were debugging a bug in our zero downtime deploy script. We tested the deploy using Chef, Kitchen and Vagrant. The bug was causing an error page to show for less than 3 seconds at the very end of the deploy.

We used Monitoring Driven Development to consistently reproduce the bug (the red phase), and to validate our fix (the green phase). Here were the steps:

Preparation:

  1. kitchen login # ssh to the vagrant box
  2. sudo tail -fn100 /var/log/nginx/go.access.log # to see the response codes from the server. If all responses show 200 code during the deploy, the deploy is working.
  3. Open other terminal window
  4. kitchen login # ssh to the vagrant box
  5. watch -n 1 "curl localhost" # make a request every 1 second

Then we followed this feedback loop

On the host computer:

  1. Make changes to the deploy recipe
  2. kitchen converge # this will run our deploy
  3. Check the output of the logs to see the result of the changes
  4. Repeat the loop until bug is fixed

Passing all env. variables to a shell command

Some of the methods in the Kernel module allows you to pass environment variables to a shell command. So rather than doing:

system("RAILS_ENV=test rake do_stuff")

You can do

system({ "RAILS_ENV" => "test" }, "rake do_stuff")  

This is particularly useful when we want to pass all environment variables on our current process.

system(ENV, "rake do_stuff")

Attach to Local Ruby Process with Debugger

RubyMine has a nice feature that allows you to debug a Rails app without restarting the server.

With the server running,

1) Run the Attach to Local Process.. action from RubyMine

2) RubyMine will show a list of Ruby processes running. Pick the one running your server

3) Wait for RubyMine to connect to the process

4) Add a break point in RubyMine

5) Execute the action on the web application that hits that breakpoint

6) Execution will stop on that line. Now you can use all the nice tools the RubyMine debugger gives you.

I'm really exited with this new feature and I hope you are too. You can read more about it in here

RubyMine Attaches to Local Ruby Process

Show definition of a method at runtime in Ruby

Many people know about method(:foo).source_location to find where a method is defined at runtime. I just found a better way by using pry.

From the pry console, run:

[8] pry(main)> show-source Bar.scoped.where
From: /Users/arturo/.rvm/gems/ruby-2.2.6/gems/activerecord-3.2.22.1/lib/active_record/relation/query_methods.rb @ line 132:
Owner: ActiveRecord::QueryMethods
Visibility: public
Number of lines: 7

def where(opts, *rest)
  return self if opts.blank?

  relation = clone
  relation.where_values += build_where(opts, rest)
  relation
end

Happy Hacking!

Quickly find the git commit that broke a test

Git bisect is a very cool tool that automate a binary search for you to find the first bad commit. Here is an example on how to find a commit that broke a test:

  1. git bisect start
  2. git bisect good <good_sha> # <good_sha> is any commit where the test is passing
  3. git bisect bad <bad_sha> # <bad_sha> is any commit where the test is failing
  4. git bisect run zeus rspec <broken test> # remove zeus if you don't use it

Git bisect will perform a binary search and run the test on every step. It uses rspec exit status to know if the commit is good or bad (0 exit status means good, otherwise it's bad). When it's done it will print the first bad commit:

a5cf29ac1dd64e5ce05336f28aa0ffc17e57fc10 is the first bad commit
commit a5cf29ac1dd64e5ce05336f28aa0ffc17e57fc10
Author: Arturo Pie <example@example.com>
Date:   Fri Apr 1 08:55:31 2016 -0400

    This is the commit message

:040000 040000 b2399ed1361548a743d95aa6aa95e42096f5ffd3 b500421bbfb9bb3dfebee1e45ff2197a7f32a43e M  app
bisect run success

When you are done debugging, run git bisect reset to end the bisect.

Happy Hacking!

RSpec option to quickly fix transient failures

Problem:

How do I quickly find the smallest set of tests to reproduce a transient RSpec failure?

Context:

Sometimes, we find non-deterministic RSpec failures in our test suite that we often call transient failures. These tests only fail when they are run in a specific order (aka, using the same RSpec order seed), and they always pass when run in isolation.

Solution:

RSpec provides an option to find the minimum number of tests to run to reproduce the failure by doing bisection.

To use it, run RSpec with the order seed of one of the fail runs, and the --bisect option. For example,

rspec spec/cool_feature_spec.rb --seed 21952 --bisect

and RSpec will find the minimum reproduction command.

....
The minimal reproduction command is:
  rspec './spec/cool_feature_spec.rb[1:1:1,1:1:2]' --seed 21952