taw's blog

The best kittens, technology, and video games blog in the world.

Monday, May 09, 2016

autoreporter gem

The latest in kitten eyeware. by shadow planet from flickr (CC-NC-ND)
Many times I wanted to display status of something in terminal tab. The obvious way to do so would be something like:

while true
  system "clear" # Clear the screen
  system "rake status" # run command reporting status
  sleep 60
end

Which is nearly ruby -e one-liner with some golfing.

This is good enough if rake status is close to instantaneous. Unfortunately if it does anything nontrivial - like checking with external network service, searching filesystem and so on - then most of the time when you switch to status tab you'll be seeing empty or incomplete screen instead of probably much more useful previous minute's report.

And so I created autoreporter script, which I now packaged into a gem of the same name. To use it open terminal tab and run autoreporter rake status or whatever you want it to run to get status. It will manage screen refreshes, STDERR redirection and such, and has command line switches for things like delay and verbosity.

I used it for over a year now. Initially I thought it will need fancy features like multiple independent report sources, watching file changes, forcing refresh by some keyboard shortcut, and so on, but in reality I never needed any of that.

Before I wrote autoreporter I tried to use rerun but lack of output buffering really kills it.

Saturday, May 07, 2016

Test-Driven Development for Optimists

Happy cat by loicdupasquier from flickr (CC-NC-ND)

If you do proper Test-Driven Development, writing your tests first, then your machine will call your code - and by extension you as well -a  failure. Over and over, every day you code, and use nasty red color for it just to drive the message:

Failures:

  1) HelloWorld says hello
     Failure/Error: expect(hello).to eq("Hello, world!")

     NameError:
       undefined local variable or method `hello' for #<RSpec::ExampleGroups::HelloWorld>
     # ./spec/hello_spec.rb:3:in `block (2 levels) in '

Finished in 0.00054 seconds (files took 0.13016 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/hello_spec.rb:2 # HelloWorld says hello

This kind of endless negativity cannot possibly be good for anyone - and you'll get it not just for minor mistakes you make, you'll get it for every single test. No wonder people burn out, switch to test-last development, or start making excuses for not writing tests:


Fortunately it's mostly just a matter of phrasing. Thanks to gem install rspec-half_full and setting up proper .rspec:

--color
--require rspec/half_full
--format RSpec::HalfFull

You can enjoy much more positive attitude:

Future successes:

  1) HelloWorld says hello
     Future Success: expect(hello).to eq("Hello, world!")
     NameError:
       undefined local variable or method `hello' for #<RSpec::ExampleGroups::HelloWorld>
     # ./spec/hello_spec.rb:3:in `block (2 levels) in '

Finished in 0.00084 seconds
1 example, 1 future success

Rerun on next step to success:

rspec ./spec/hello_spec.rb:2 # HelloWorld says hello

And not only is this psychologically healthier, it's also more accurate - specs you're writing are not failures, they're just description of future successful code you're planning to write.

Hopefully it will make you at least a little bit happier.

Wednesday, May 04, 2016

Continuous Integration for personal projects

The Cat by marcinlachowicz.com from flickr (CC-NC-ND)
This seems really obvious in retrospect (so I blame you guys for not telling me earlier), but somehow I never connected the dots before yesterday.

CI is really useful, but it's a massive pain in the ass to set it up for personal projects on own servers. Fortunately it turns out pretty much every CI service website offers CI for free for any software that's open source.

Somehow I have 51 public repositories on github, not counting forks (as well as some private code, but much less of that). Some of them are fairly seriously maintained, a lot is just random stuff I wrote once and I probably will never use again, but I had no reason not to post online.

So I opened free account on Semaphore and setup CI for 4 of them. It mostly required specifying dependencies in Gemfiles (I'm not committing Gemfile.lock files to repositories, this causes more problems than it solves) in a bit more detail, but wasn't too difficult.

The only nontrivial problem was with z3 gem, which depends on z3 library which isn't available on two year old Ubuntu 14.04 LTS which semaphore uses as its only option, so I had to use build instructions like:

echo "deb http://archive.ubuntu.com/ubuntu/ xenial main" | sudo tee -a /etc/apt/sources.list
echo "deb http://archive.ubuntu.com/ubuntu/ xenial universe" | sudo tee -a /etc/apt/sources.list
sudo apt-get update

Followed by apt-get install libz3-dev; bundle install; bundle exec rake spec which do the actual job.

I plan to go through 51 public repositories and decide one by one which are worth getting CI and which probably aren't.

Sensible git diff for json files

cat #1227 by K-nekoTR from flickr (CC-NC-ND)
JSON is rarely great for anything, but it's very often good enough, so one thing you'll often run into is JSON in git repositories.

Human-edited JSON (for which you should probably use something like JSON5 instead) is reasonable to work with.

Unfortunately typical machine-generated JSON is completely undiffable - it's all one big line, so trying to run git diff or git log -p will produce full content on before and after side, and you'll have no idea what actually changed without copying both before and after to external files, formatting them, and diffing the result - fairly slow and messy process.

Fortunately this is solvable. First, get latest version of my unix-utilities repositories for json_pp script for pretty-printing JSON (or any other json pretty-printer) and put it somewhere in your $PATH.

Then tell git to treat json as special file for purpose of diffing.

To do it globally:

echo "*.json diff=json" >> ~/.gitattributes
git config --global core.attributesfile ~/.gitattributes
git config --global diff.json.textconv json_pp

Or instead you can do it for just one project:

echo "*.json diff=json" >> .gitattributes
git config diff.json.textconv json_pp

You can use similar technique for other sort-of-text-but-not-really files like machine-generated XML.

textconv is only applied for human readable command output, so it doesn't affect any internal workings of git, and if you want to see raw diffs for any reasons you can always use --no-textconv argument to git diff.

Saturday, April 30, 2016

Fun and Balance mod for EU4 1.16.3

king of the castle by allenthepostman from flickr (CC-SA)
Fun and Balance is available updated for 1.16.3:
Not counting minor bug fix with partial westernization (which is disabled by default anyway), it's just compatibility update.

Full feature list and links to older versions in case you want them are all here.

For all my CK2 and EU4 mods, check my Steam Workshop page

Thursday, April 21, 2016

Dealing with transient test failures due to database results order

Fox by kindl_jiri from flickr (CC-ND)
The most #mildlyinfuriating aspect of testing are tests which work most of the time, but fail occasionally. Even worse are tests which always work when you run them individually, but sometimes fail when ran as part of a test suite.

The most common category of transient test errors I've seen are Capybara Javascript testing, and I don't have a great solution for those, but there's another category of really obnoxious tests - tests which expect results from database to be in specific order.

They usually work, as databases do the laziest thing possible, so when you ask one for a bunch of records without specifying any particular ordering, it will usually return them in whichever order they are physically on the disk, which usually corresponds to order of their creation, which then usually corresponds to their serial or GUID primary key, so you get that implicit ORDER BY id, most of the time.

Which is just fine, except once in a while the database will reorder physical records to compact tables, causing physical order of record to no longer correspond to primary key order, and test to fail.

Then you rerun it individually over and over, and it works every time, as this kind of reordering is not going to happen mid-test, only once enough repeatedly created and deleted data accumulated in the table. Like once every 20 full test runs, each half an hour long. Very frustrating to debug.

What if you could force such tests to reveal themselves somehow? Most databases won't be of much help, and ORM is standing in the way of adding ORDER BY to every query which doesn't have one, but fortunately it's not too difficult to tell ActiveRecord to shuffle results of everything that didn't request specific order, by placing this kind of code in your spec/spec_helper.rb or equivalent:

Rails.application.eager_load!
ObjectSpace.each_object(Class) do |cls|
  if cls.ancestors[1..-1].include?(ActiveRecord::Base)
    begin
      cls.instance_eval do
        default_scope { order('rand()') }
      end
    rescue
      warn "Can't order #{cls}"
    end
  end
end

I wouldn't recommend running it like that every time, and especially not in production, as ORDER BY RAND() everywhere is going to have annoying performance impact, but enabling it temporarily just to debug already existing transient test failures might be just the right tool.

Wednesday, April 20, 2016

Patterns for testing command line scripts

Lab Mouse checkin out the camera by Rick Eh? from flickr (CC-NC-ND)
It's relatively easy to test code which lives in the same process as test suite, but a lot of the time you'll be writing standalone scripts, and it's a bit more complicated to test those. Let's talk about some patterns for testing them.

Examples in RSpec, but none of these patterns depend on test framework.

Manual Testing Only

That's actually perfectly legitimate. If your script is a few lines of straightforward code, you can just check that it works manually a few times, and then completely forget about it. Usefulness of automated tests in such case probably won't be very high.

I'd recommend not relying on just that for more complicated scripts.

STDOUT testing

A lot of scripts take arguments from command line or STDIN, and output results to STDOUT, possibly STDERR or exit code as well.

A bunch of expect(`script --input`).to eq("output\n") style tests are very easy to use and can go very far.

If you need to test a bit more complicated interactions - setting environmental variables, writing to STDIN, reading from both STDOUT and STDERR, checking error code etc. - IO.popen and Open3 module offer reasonably convenient APIs.

Of course only certain category of scripts can be reasonably tested this way, but it's a fairly big category.

Testing as library code

A fairly common pattern is to move most of the code from "script" file to a separate "library" file, which can be required by both. It's a bit awkward, as script no longer lives in one file.

It's not always obvious where to divide the library from the script - if you put everything in the library, it makes it pretty much useless for anything except program itself. If you keep things like parsing command line arguments separate, that results in possibly useful "library", but leaves more "script" code untested.

if __FILE__ == $0

It used to be a very common pattern which I don't see that often these days. What if we have a file which works as a library you can require, but it acts as a script if it's ran directly? Here's the typical code for such script:

class Script
  def initialize(*args)
    ...
  end
  def run!
     ...
  end
  ...
end

if __FILE__ == $0
  Script.new(*ARGV).run!
end

Depending on how you feel you might do command line argument parsing either in initializer, or in if __FILE__ == $0 block.

Code written in this style generally doesn't intend to be used as a library, and this hook is there primarily for sake of testing.

Temporary directory

Frequently scripts interact with files. That's more complicated to setup. Don't try anything silly like using current directory or single tmp where leftovers from previous test runs might be left.

I'd recommend creating new temporary directory and going there. Add code like this to your test helpers:

def Pathname.in_temporary_directory(*args)
  Dir.mktmpdir(*args) do |dir|
    Dir.chdir(dir) do
      yield(Pathname(dir))
    end
  end
end

Then you can then use Pathname.in_temporary_directory do |dir| ... end in your tests, and it will handle switching back to previous directory and removing temporary one automatically.

In every such block you can write files you want, run command, and check any generated files, without worrying about contaminating filesystem anywhere.

There's just a minor complication here - you'll be changing your working directory, so you'll need to call your script using absolute rather than relative path. Simply do something like:

let(:script) { Pathname(__dir__) + "../bin/script"  }

To get absolute path to your script and then use that.

Mocking network

All that covers most of possible scripts, but I recently figured out one really fun trick - how to test scripts which read from network?

Within our tests we have gems like webmock and vcr can fake network communication, but what if we want to run a script? Well, just save this file as mock_network.rb:


require "webmock"
require "vcr"

VCR.configure do |config|
  config.cassette_library_dir = Pathname(__dir__) + "vcr"
  config.hook_into :webmock
end

VCR.insert_cassette('network', :record => ENV["RECORD"] ? :new_episodes : :none)

END { VCR.eject_cassette }

And then run your script as system "ruby -r#{__dir__}/mock_network #{script} #{arguments}", possibly in conjunction with any other of the techniques presented here.

To record network traffic you can run your tests with RECORD=1 rspec, then once you're finished just run rspec normally and it will use recorded requests.

Mocking other programs

Previous pattern assumed the script was using some Ruby library like net/http or open-uri for network requests. But it's very common to use a program like curl or wget instead.

In such case:
  • write your mock curl, doing whatever you'd like it to do for such test
  • within test, change ENV["PATH"] to point to directory containing your mock curl as first element
  • run script under test
This works reasonably well, as almost all programs call each other via ENV["PATH"] search, not by absolute paths, and usually expect fairly simple interactions.

Like all heavy handed mocking, this can fail miserably if the program decides to pass slightly different options to curl etc., and unlike webmock this style of interaction doesn't block network access so you can miss something.

All these patterns leak

None of these pattern are perfect - they assume how script is going to interact, and they don't actually isolate script from network, filesystem (outside temporary directory you created), Unix utilities etc., so a buggy script can still rm -rf your home directory.

For testing very complicated interactions, you might need to use virtual machine, or some OS-specific isolation mechanism like chroot. Fortunately only relatively few scripts really need such techniques.

Tuesday, April 19, 2016

Automatically managing db/schema.rb

peering thru the bed rails watching coco play by damselfly58 from flickr (CC-NC-ND)
I've been living in schemaless NoSQL wonderland for quite a while, but I'm currently working on some mysql-based Rails applications, and managing db/schema.rb is a massive pain.

It's an automatically generated file, and such conventionally don't go into version control, but it also literally says "It's strongly recommended that you check this file into your version control system" in it. I'm still not completely convinced it's the right thing to do, but let's assume we follow the recommendations.

The problem is that you're probably not starting a fresh database for every branch - or carefully rolling back to master schema before you switch - you'll be switching branches a lot, and migrations will be applied in a different order than what they'd end up on master - so whenever you generate db/schema.rb you'll need to look at it manually to figure out what should be committed and what shouldn't. It's a very error prone process for something as frequent as writing migrations.

You could drop your database and recreate it from migrations every now and then, but you probably have some data you'd rather keep there.

Fortunately there's a solution! Oh, you can't just switch your team to a schemaless database? Well, in such case use this script:

Script regenerate_schema_rb:

#!/usr/bin/env ruby

require "fileutils"
require "pathname"

fake_database_yml = Pathname(__dir__) + "database.yml"
real_database_yml = Pathname("config/database.yml")

unless real_database_yml.exist?
  STDERR.puts "It doesn't seem like you're in a Rails application"
  exit 1
end

unless `git status` =~ /nothing to commit, working directory clean/
  STDERR.puts "Do not run this script unless git status says clean"
  exit 1
end

system "echo 'DROP DATABASE IF EXISTS schema_db_regeneration' | mysql -uroot"
system "echo 'CREATE DATABASE schema_db_regeneration' | mysql -uroot"

FileUtils.cp fake_database_yml, real_database_yml

system "rake db:migrate"
system "git checkout #{real_database_yml}"

Fake database.yml:

development:
  adapter: mysql2
  encoding: utf8
  database: schema_db_regeneration
  pool: 5
  username: root
  password:

What it does is very straightforward - it keeps your existing database, and simply repoints database.yml at a fake one, and runs all the migrations against it. No manual edits necessary, and your next_tumblr_development database is safe.

Sunday, February 28, 2016

Let's Play Civilization 5 on Tamriel as the Khajiit - post-campaign retrospective

Biting the brother in the neck! by Tambako the Jaguar from flickr (CC-ND)

Unfortunately due to changing circumstances my Youtube channel is probably going to be somewhat less active for at least first half of the year.

My most recent and so far the only series on it was Let's Play Civilization 5 on Tamriel as the Khajiit, which is now slowly coming to a close, so it's time for some retrospective.

Balance between civilizations

I've chosen civilization based on a quick look at who seemed to have interesting gameplay potential - and also because I haven't played as cats before. I thought other civilizations are gonig to have comparable power level, but it's not ever close, and Khajiit are insanely overpowered. Here's what they do:
  • caravan range doubled
  • land military units (but not workers, settlers, great generals etc.) +1 movement and +1 sight
  • workshop replacement with +2 happiness, +1 culture, +2 science/jungle (stacking with University for +4 science/jungle), on top of the usual bonuses
  • caravansary replacement with +2 happiness, +1 culture, double trade range bonus, and the usual gold bonus
In other words:
  • ridiculously powerful happiness bonus (+4 per city), all available fairly early in game, making happiness maybe not quite irrelevant, but a secondary consideration even for highly expansionistic empires
  • ridiculously powerful military bonus (+1 movement and +1 sight is stronger than most UUs - and Khajiit get it for every land unit in every era.
    • To make it even more extreme, Tamriel map is almost all land, so lack of bonuses for ships matters little - and extra movement and sight is still quite effective at shooting ships with your missile units
    • Early game the Bosmer whom I was fighting built Great Wall - possibly the most obnoxious wonder in the game - that extra movement point more or less invalidated their wonder
  • fairly strong science bonus - requiring access to a lot of judge would make it somewhat situational, but guess what - that's precisely the kind of terrain Khajiit start with in every direction
  • fairly strong gold bonus - it's not that huge, mostly it lets you use caravans where others would use cargo ships, which on some maps would be fairly inconsequential, but Tamriel is basically Pangea, so it's especially strong on this map
  • modest culture bonus - +2 culture / city is very good value
  • and all of that requires very little effort - you start with military bonus and you'd be building workshops everywhere anyway - so now you just need to build caravansaries in places you wouldn't otherwise
This is all "way above Korea and Poland" tier.

It would be all right if everybody had comparable bonuses, but as far as I can tell, everybody else's are rather mediocre.

Back when I was playing Ravnica civs, half of them were really overpowered, but they matched each other reasonably well, and I don't think any of them were Khajiit tier.

This unfortunately means I'm not so inclined to give Tamriel another try. Other civs seem not only underpowered, but also rather boring.

Truce Breaking Bug

Civilization 5 won't let you break truces no matter how much you'd like to do so. However I ran into this bug:
  • I wanted to attack Orsimer, but they were a bit strong, so I asked Skyrim to attack them together
  • Skyrim said yes, but give us 10 turns
  • Well, I couldn't wait, so I attacked Orsimer on my own
  • They offered far less resistance than expected, so I took what I wanted and peaced them out
  • Next turn Skyrim came back to me with "10 turns is up, let's attack Orsimer together" dialog, and war started.
  • As far as I can tell, there were no negative diplomatic consequences of this truce breaking, because game didn't even consider truce breaking to be a possibility

Playing with 13 civilizations


The game had 13 civilizations on Standard sized maps (as opposed to the usual 8), so I expected a bloodbath fighting for what little land there was available. Three civilizations (Bretons, Orsimer, Hammerfell) had their capital so close I'd expect them to DoW each other before getting Composite Bowmen.

It turns out that number of tiles is Standard sized, but amount of land is much bigger, so there was plenty available for everyone - and map had a lot of strategically places mountains to slow down early warfare as well.

Unfortunately 13 civs on Immortal meant it was completely pointless to go after wonders, religions, or domination victory, while making research agreements and science victory a lot stronger.

I think I had 8 research agreements at one point, with +50% science from research agreement thanks to Porcelain Tower stacked on top of +25% from relevant Rationalism policy. That in addition to all my science bonuses, funded by my gold bonuses.

I think 13 civs is generally too many, and it would be better to play with a smaller subset.

Minor mods

I'm increasingly thinking that I should uninstall all promotions mods and just play with vanilla promotions. There's really very little value in it, and it replaces one optimal formula (accuracy/barrage 1-2-3, logistics, range) with another (unlock 1-3, range, unlock 4, logistics).

I'm less convinced that I should be playing with captureable settlers, as that makes things a bit easy with AI stupidity. I still enjoy capturing other great people a lot, so I'd need to customize that.

Other issues

Science victory is a bit boring, so I spent far too much time fighting completely pointless wars late game. I could have finished the campaign a lot faster if I just ignored everybody else and built space ship.

I only just realized I misspelled "Khajiit" as "Khajit". Oh well.

How to configure OSX 10.11 El Captain for software development

Cats by sokole oko from flickr (CC-NC-ND)

With every new Macbook, I'm updating the guide, previous version is here. A few thing changed - mostly some links which used to work have been taken over by malware. OSX is turning into Windows more and more.

Basics

  • Go to Settings > Security > FireVault, turn on FireVault. This will restart your computer.
  • Install some sensible browser like Chrome or Firefox.
  • Afterwards either sign up into your account on which you hopefully have your AdBlock setup, or install some. Most popular seems to be uBlock Origin these days, but pretty much any of them will do just fine.
  • Install whichever cloud sync service you're using like Dropbox etc. And start syncing your stuff.
  • Install iTerm2 for sensible terminal emulator.
  • Clean up all crap from dock. Other than Launchpad and System Settings, everything else should be gone. Add iTerm2, your browser, and your text editor, and any application you wish to install there instead of stock Apple crap.
  • It's also a good idea to disable Spotlight as soon as possible by running sudo mdutil -i off / - before it tries to index all of your dropbox and generally ruin performance of your machine.

Editor

Install some sensible text editor like Sublime Text (requires license key) or Atom (free, a bit slower).

Whichever editor you choose, you'll definitely need to configure it to your liking.

Then symlink it so you can use it from command line

  mkdir -p ~/bin
 ln -s "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl" ~/bin/subl

Settings

Default Mac settings are totally awful, time to fix that.
  • Max brightness
  • Settings > Security > Allow apps downloaded from: > Anywhere
  • Settings > Mouse > Max out "Fast" setting on everything
  • Settings > Keyboard > Key Repeat > Fast
  • Settings > Keyboard > Delay Until Repeat > Short
  • Settings > Keyboard > Use all F1, F2, etc. keys as standard function key
  • Settings > Keyboard > Text > Disable "Correct spelling automatically"
  • Settings > Sound > Disable "Play user interface sound effects"
  • Settings > Sound > Alert volume > 0% (for Terminal ping)
  • Settings > Trackpad > Scroll & Zoom > Disable "Scroll direction: natural"
  • Settings > Energy Saver > Power Adapter > Display sleep > Never
  • Settings > Displays > Built-in Retina Display > Disable "Automatically adjust brightness"
  • Settings > Displays > Arrangement > drag and drop your external monitors into desired order
  • Settings > Dock > enable "Automatically hide and show the Dock"
  • Menu bar > Battery icon in task bar > Enable "Show Percentage"
  • iTerm > Preferences... > Profiles > Terminal > Unlimited Scrollback
Press Ctrl-Up arrow, add a few desktops (or "spaces" as they were used to know), then go to Settings > Keyboard > Shortcuts > Mission Control - and enable their keyboard shortcuts Ctrl-1 to Ctrl-6 or however many you have there.

Drivers

OSX already includes drivers for laptop itself, but you might need some for peripheral hardware.

If you need any keyboard drivers like for Microsoft Keyboard (otherwise Cmd key is in the wrong place) or just about any external keyboard, get necessary drivers.

If you need any special keyboard layouts, get them too.

Standard paths

OSX renames a lot of directories. While in theory scripts could just use env vars to find proper paths, it's more reliable to symlink all the things:

  sudo ln -s /Volumes /mnt
  sudo ln -s /Volumes /media
  sudo mv /home /home-old
  sudo ln -s /Users /home

Development tools

First, you'll need Xcode. Run xcode-select --install from command line to install it.

Now it's time for a package manager. They're all somewhat disappointing if you're used to apt-get. homebrew seems somewhat more popular than others these days, so you might just as well try that. You need to tell homebrew to not spy on you with brew analytics off command.

You'll also need X11 server like XQuartz.

Create new SSH key pair

Before you do that, name your computer something memorable with sudo scutil --set HostName your_host_name command.

Open Terminal and run ssh-keygen to create ~/.ssh/id_rsa, then upload the generated key to any place that needs to know about it like github, bitbucket, or whatever else you use.

Checkout your dotfiles

Hopefully you're storing your dotfiles somewhere. If it's a git repository, or your Dropbox account, get them now and symlink them all properly.

If there are any other repositories you might need, checkout them too.

Install homebrew packages

Your list might vary. Here's mine (fun story - order you install homebrew packages matters, every packaging system that's not apt-get sucks so hard):

brew install mongodb mysql postgresql rbenv ruby-build wget htop unrar mc mplayer coreutils libxml2 libxslt bash poppler redis qt youtube-dl trash rabbitmq pcre exiftool lame id3v2 sox jq git bash-completion p7zip imagemagick

Then enable all services you installed, unless you want to start them manually:

  ln -sfv /usr/local/opt/*/*.plist ~/Library/LaunchAgents/

And install non-system ruby, so you can install gems without sudo:

  rbenv install 2.4.0-dev
  rbenv global 2.4.0-dev

To make that actually work, you need to make sure ~/.rbenv/shims is in your $PATH.

Due to OSX limitations you'll need to run sudo htop if you want to use htop.

Sane bash and coreutils

bash version shipped with OSX is ancient and BSD utilities are all awful. In previous steps you installed proper versions, now you need to tell the system to use it.

Add homebrew version of bash as allowed shell by appending /usr/local/bin/bash at end of /etc/shells

Then set it as your shell: chsh -s /usr/local/bin/bash $USER

Then make sure to add GNU coreutils to your PATH:

  export PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"
  export MANPATH="/usr/local/opt/coreutils/libexec/gnuman:$MANPATH"

You'll also probably want to touch ~/.hushlogin to prevent some worthless spam on every open terminal tab.

Install gems

Again, your list my vary. Here's mine:

gem install beeminder moneta octokit term-ansicolor pry-plus rak objectiveflickr hpricot color nokogiri bundler

All other software

Sadly OSX window manager is extremely dubious for keyboard use. Fortunately programs to make it usable exist. I recommend installing these two:
  • ShiftIt - for tiling by keyboard shortcuts.
  • HyperSwitch - for sane alt-tab window switching. (there's also Witch, but it has issues with 10.10)
You'll need to give them necessary access. To do so:
  • Settings > Security & Privacy > Privacy > Allow the apps below to control your computer > enable them both
You'll probably need these or similar programs:
Once upon a time Open Source Mac website contained links to a lot of useful software, but these days targets seem to be malware infested crap a lot. Don't go there.

Enjoy

Once you go through this list, and successfully get everything going, I'd recommend modifying it to your liking and reposting your version on your blog. Everybody's needs are different, so guide like this is just a starting point.