Updating Open Source Software

Published on

Note — 2014-10-12 The bundle command for brew seems to have been deprecated, and thus, parts of this Rakefile won’t be of much use. I’ll be updating this post accordingly soon.

Keeping all of your Ruby gems, Homebrew packages and dotfiles up-to-date and organized can be a bit of a chore. I put together a little system that seems to be working well, and I wanted to share my system with the world. I suppose it should have a catchy name, but it doesn’t so oh well.

The linchpin in the system is Rake. I’ve got a Rakefile in my “~/Dropbox/dotfiles” directory that handles all the updating. My Rakefile looks like this:

task :default => :update

desc "Update packages"
task :update => [:rm_conflicted, :rcm, :brew, :gems, :vim]

namespace :brew do
  desc "Run setup Homebrew commands"
  task :setup do
    sh "brew bundle Setupfile"

  desc "Install Homebrew packages"
  task :packages => ["brew:setup"] do
    sh "brew bundle Brewfile 2> /dev/null"

  desc "Install Homebrew casks"
  task :cask => ["brew:setup"] do
    sh "brew bundle Caskfile 2> /dev/null"

  desc "Clean up after Homebrew"
  task :teardown => ["brew:packages"] do
    sh "brew bundle Teardownfile"

desc "Run all Homebrew tasks"
multitask :brew => ["brew:setup", "brew:packages", "brew:teardown"]

desc "Update rc files"
multitask :rcm do
  sh "rcdn && rcup"

desc "Update Vim plugins"
task :vim do
  sh "vim +PlugInstall +PlugUpdate +quit +quit; clear"

desc "Tidy conflicted Dropbox files"
task :rm_conflicted do
  sh "clear"
  sh "rm_conflict.sh"

desc "Install Minion"
task :minion do
  sh "cd ~; git clone https://github.com/edthedev/minion"

desc "Update installed gems"
multitask :gems do
  sh "gem update --no-document && gem update --system"

desc "Update npm packages"
multitask :npm do
  sh "sudo npm update -g"

namespace :install do
  desc "Install Homebrew"
  task :homebrew do
    sh "ruby -e \"$(curl -fsSL https://raw.github.com/mxcl/homebrew/go/install)\""
    sh "brew bundle Brewfile Caskfile"
  desc "Install rbenv"
  task :rbenv do
    sh "git clone https://github.com/sstephenson/rbenv.git ~/.rbenv"
    sh "git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build"
    sh "rbenv install #{RBENV_VERSION}"
    sh "rbenv global #{RBENV_VERSION}"
    sh "git clone https://github.com/sstephenson/rbenv-gem-rehash.git ~/.rbenv/plugins/rbenv-gem-rehash"
    sh "git clone https://github.com/ianheggie/rbenv-binstubs.git ~/.rbenv/plugins/rbenv-binstubs"
    sh "gem install bundler"
    sh "bundle install"
  desc "Install zsh"
  task :zsh do
    sh "git clone git://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh"
    sh "chsh -s /bin/zsh"
    sh "./defaults.sh"
  desc "Install Plug.vim"
  task :plug do
    sh "mkdir -p ~/.vim/autoload"
    sh "curl -fLo ~/.vim/autoload/plug.vim https://raw.github.com/junegunn/vim-plug/master/plug.vim"
  desc "Install FZF"
  task :fzf do
    sh "git clone https://github.com/junegunn/fzf.git ~/.fzf"
    sh "~/.fzf/install"
  desc "Install Shellcheck"
  task :shellcheck do
    sh "cabal update"
    sh "cabal install cabal-install"
    sh "cabal install shellcheck"

desc "Set up a new Mac"
task :setup_mac => ["install:homebrew", :rcm, "install:rbenv", "install:zsh", "install:plug", "install:fzf", "install:shellcheck", :vim]

There first thing that runs is rcup, which is the command for Thoughtbot’s rcm program that manages your dotfiles, this runs first, because I realized that if you’re changing settings and environment stuff, sometimes you’re dotfiles might get out of whack. Next, I’ve divvied up my Homebrew tasks into a Setupfile that does all the prep work for updating, then a Brewfile for Homebrew packages and a Caskfile for OS X apps installed with Homebrew Cask, and finally a Teardownfile that just cleans up everything after all the installs are finished. Dependencies are set with Rake and everything runs in the proper order. Lastly, RubyGems updates all my installed gems and then updates RubyGems itself. I wonder if it shouldn’t’ be the other way around though. I played with updating npm packages at the end as well, but I get so many errors with npm that I didn’t bother including it in the end.

I’ve aliased this to ru in my ~/.zshrc and that will cd into my dotfiles directory and simply run rake. I’ve been using this for a few weeks and it’s working out pretty well.