A simple example of git bisect run with ruby

git bisect run is my favourite git command, and I'll find any excuse to use it.

If you're not familiar with this tool, the git manpage succinctly describes it as:

git-bisect - Find by binary search the change that introduced a bug

And Bisect run as:

Bisect run
    If you have a script that can tell if the current source code is good or
    bad, you can bisect by issuing the command:

        $ git bisect run my_script arguments

    Note that the script (my_script in the above example) should exit with
    code 0 if the current source code is good, and exit with a code between
    1 and 127 (inclusive), except 125, if the current source code is bad.

An example

One of the applications at Zendesk uses a very handy gem called Phony that has the noble and non-trivial aim of formatting any phone number in the world, here's an example:

# United States
> puts Phony.format('14155556666')
+1 415 555 6666
# United Kingdom
> puts Phony.format('441914980000')
+44 191 498 0000
# France
> puts Phony.format('33123456789')
+33 1 23 45 67 89

It's really cool.

Recently I updated our application to use the latest version of Phony and some tests started to fail, specifically the ones around emergency numbers. After a bit of investigation in the rails console I discovered that the following command ran successfully before the version bump and failed afterwards.

# Using v1.9.0
> Phony.normalize("999")
=> "999"

# Using v2.10.0
> Phony.normalize("999")
Phony::NormalizationError: Phony could not normalize the given number. Is it a phone number?
    from .../phony-2.10.0/lib/phony.rb:102:in `rescue in normalize!'
    from .../phony-2.10.0/lib/phony.rb:100:in `normalize!'
    from .../phony-2.10.0/lib/phony.rb:97:in `normalize'
    ...

I cloned Phony locally and tried the same thing within the gem. I was able to write a one-line script that I could run from my bash prompt:

# Using v1.9.0
$ phony ((v1.9.0))> ruby -e 'require "./lib/phony"; Phony.normalize("999")'
$ phony ((v1.9.0))> echo $?
0

# Using v2.10.0
$ phony (master)> ruby -e 'require "./lib/phony"; Phony.normalize("999")'
./phony/lib/phony.rb:102:in `rescue in normalize!': Phony could not normalize the given number. Is it a phone number? (Phony::NormalizationError)
    from ./lib/phony.rb:100:in `normalize!'
    from ./lib/phony.rb:97:in `normalize'
    from -e:1:in `<main>'
$ phony (master)> echo $?
1

As you can see from the output of echo $?, the script had an exit code of 0 in version 1.9.0, while in version 2.10.0 the script had an exit code of 1.

So now I knew of one 'good' commit and one 'bad' commit, and I had a script that I could run which exited with 0 on a good commit and 1 on a bad commit.

Next I wanted to find out at which point Phony started treating the number '999' differently.

The basic process for starting a bisect goes like this:

$ phony (master)> git bisect start
$ phony (master|BISECTING)> git bisect bad
$ phony (master|BISECTING)> git bisect good v1.9.0

Bisecting: 221 revisions left to test after this (roughly 8 steps)
[164dfc36f83b5d0c5b3c11073395a3324622449f] Add Rubinius performance tool.

$ phony ((164dfc3...)|BISECTING)> 

At this point if I hadn't had a script that I could run I could have checked this version of the code manually and then marked it as good or bad myself:

$ phony ((164dfc3...)|BISECTING)> git bisect [good/bad]

But fortunately I had a script! So I ran:

$ phony ((164dfc3...)|BISECTING)> git bisect run ruby -e 'require "./lib/phony"; Phony.normalize("999")'

At this point git took over and jumped through commits, executing this script until it found the first commit that caused this script to fail. Here's a video of the process:

The final message that git output was:

9b4234a5024780f3b781b9a68e9c12104dea9c94 is the first bad commit
commit 9b4234a5024780f3b781b9a68e9c12104dea9c94
Author: Florian R. Hanke <florian.hanke@gmail.com>
Date:   Sat Sep 13 14:23:18 2014 +0200

    Add reserved keyword to Phony DSL.

:100644 100644 dbbb2f6a5a2db77645c622256d42dac45f187a3e 0ddb203544988f2c5f76e53a17b30788716abaeb M  history.textile
:040000 040000 7aee4152514e4aa8540bac2b5aab02de07fbc4a7 26952552d99a3e3387afb88ed84cab47eabf1a0a M  lib
:100644 100644 84cd8783223cbac50acdceec0a2d9790f40cf4ae c36a4c9f458a8516fadd7ae2f4a50e8bed9f0557 M  phony.gemspec
bisect run success

So now I knew the first commit that caused Phony.normalize('999') to behave differently!

Next steps

The commit in question implied that the change was intentional, and that Phony would no longer allow any operations on the number '999'.

I didn't want to make any assumptions, so I created an issue on the Phony repo and the author, Florian explained that this really was the intended behaviour, and that according to E.164, '999' is not considered an international number (and technically neither is '911', but this didn't cause any tests to fail because +91 is the country code for India, and +911 is currently considered to be a valid number).

Thanks to the feedback from Florian I changed our application to handle all emergency numbers in a different way.

I hope this was useful! If you have any feedback send me an email at paul at paulboxley dot com or tweet me at @baxt3r.

The Chemistry of Cast Iron Seasoning

Griswold skillet

Years ago my Dad gave me a wok and showed me how to season it, but I'd never really thought about the chemical reaction that happens when we season metal pans until I read Sheryl Canter's blog post about the chemistry of cast iron seasoning:

I’ve read dozens of Web pages on how to season cast iron, and there is no consensus in the advice. Some say vegetable oils leave a sticky surface and to only use lard. Some say animal fat gives a surface that is too soft and to only use vegetable oils. Some say corn oil is the only fat to use, or Crisco, or olive oil. [...]

They are all wrong. It does matter what oil you use, and the oil that gives the best results is not in this list.

Sunny Eggy is the most amazing Facebook sticker set

I was chatting to Kristie on Facebook Messenger when she sent me the following sticker:

Spa eggy

I spent a while looking at it, and I just couldn't figure out what it was supposed to be, until she explained that it was an egg in a face mask, and introduced me to the wonderful world of Sunny Eggy.

Facebook stickers are a strange concept to begin with, but the Sunny Eggy sticker set is especially strange. Every sticker is of an egg. Not an egg in a shell, but the yolk and white of an egg, with a little face and arms and legs.

Some eggys are happy:

Happy eggys

Some are industrious and hard working:

Busy eggys

Some are... unusual:

Unusual eggys

This eggy in particular is tripping and its face is falling off:

Eggy losing face

The more I look through the Sunny Eggy images the more I feel like I am just scratching the surface. I tried to find out where these stickers came from – Facebook lists the author of the stickers as "Kangaroo" but various searches for combinations of the words "Sunny", "Eggy" and "Kangaroo" have not lead to any useful information so far.

The images use a lot of manga iconography, like the little angry cruciform, that makes me suspect that the stickers are Japanese in origin, but that's not a lot to go on.

I want to understand the secrets of Sunny Eggy. If you have any information that might help, then tweet me @baxt3r.

Until then I'll be trying to fathom the origins of these little eggy creatures.

Wanderers

I love this beautiful video by Erik Wernquist, set to the voice of Carl Sagan. I watched it again today and thought to myself, "what am I doing to make this future happen?"

Archives

Years ago I started a blog called "End Of Level Boss" and I recently found a backup of some of its posts. A lot of them were uninteresting, but I decided to re-post some of them here with the original dates.

It's strange reading things that I wrote 7, 8 or 9 years ago. I remember I used to take a long time to publish posts because I wanted to make sure everything was perfect, but reading them back now the language that I use seems awkward, and there are a few typos that I've corrected. I'm sure there's a lesson in there somewhere!

Here are some of the highlights:

Plumen 002

I had no idea that Plumen had released a new bulb.

Plumen 002

It's an interesting design, chunkier than the original Plumen, and according to their website it produces a much warmer glow:

Plumen 002 is a more simplistic and poetic design, to suit its warmer, softer light and the more ambient surroundings it was created for. Luminosity is equivalent to a 30W incandescent bulb and the colour is 2500k which is warmer than the Plumen 001 that is 2700k.

The Plumen 002 would look great in one of Grovemade's desk lamps (I'm not a fan of using the extremely inefficient 'squirrel-cage' incandescent bulbs that seem to have become popular lately).

Monument Valley

Monument Valley – Ida

Monument Valley is a puzzle game for iOS (and soon Android) that tasks you with helping Ida on her journey through the ruins of a colourful, geometrically impossible kingdom.

This is a beautiful game - the art style is minimalist and polygonal without being difficult to interpret and it looks as though every pixel was carefully placed, even when you're manipulating the world by rotating towers or pulling at parapets to make new paths.

And the games' sound design is great as well, subtle sound effects make the world feel tangible, and when you slide your finger to pull a platform you hear feedback in the form of gentle, relaxing musical notes.

The world is filled with optical illusions like Penrose triangles and platforms that only align from a certain angle, where the perspective of the player determines whether a path is walkable or not.

Monument Valley – a rotating platform creates a Penrose triangle

Perhaps the most impressive part of Monument Valley is that it never feels too difficult. I don't think many people will be tempted to stop and come back to it later because it's too hard, or find a particular puzzle so frustrating that they'll want to look online for a solution (although I did have to stop and think for a while on the later levels), but equally the puzzles never feel unsatisfying either.

Monument Valley – waves batter a tiny island

The game only takes about 2 hours to complete (to be honest I lost track of time while playing) but still manages to tell a story – not a very complex story, and a lot is left to the imagination, but I still felt moments of joy and sadness as I helped Ida on her quest.

In summary I loved Monument Valley. It's a great game, definitely worthy of the price in my opinion, and I'm looking forward to seeing what else ustwo games come up with in the future.

Visualizing Git Concepts with D3

Visualize git with d3

I love this visualisation of git! It's really cool being able to actually see the difference between commands.

I recommend trying both a git pull and a git pull --rebase on the git fetch example.

I also noticed in the "Update Private Local Branch with Latest from Origin" example that you can rebase your branch against master without pulling master. Doing a git fetch and then a git rebase origin/master is all that you need. I've always checked out and pulled master explicitly. Good to know!

Maps + video from space

Mapbox have combined their Streets map with this footage captured from Skybox's SkySat-1.

There's a discussion on Hacker News about the difficulties and implications of the technology.

Aelita

Aelita

Today at the Zendesk Dublin office we had a Hackday, and David, Alan and myself built this web-based "soyuz"/monome clone, that we called Aelita.

It was a lot of fun, even though we were the only group in the office that didn't build something practical!

The source code is on github, let me know what you think.