Tech Thoughts

Automate Your Setup

Automating the setup of your applications is a good investment. This post will show you why.

It's very natural for growing apps to gain dependencies over time. However each dependency makes it a harder to set up. Gradually this results in a lot of lost time by people setting up the app. Either because they have to figure out the dependencies, or because they're asking others for help.

That's why automation is a good investment. Even if the script only handles the happy path, it will save each new person a couple of minutes.

I prefer to use bash to have as little dependencies as possible. But if you want to do it in a scripting language, then just add its install instructions to the README and go for it. The point is that it should be more productive than installing manually.

To provide an example: Below is a script that's a simplified version of what we use in our Ruby on Rails apps. It installs MySQL if Homebrew is present, helps the user if ruby isn't installed, automatically tries to install bundler, and sets up the database with some seed data.

set -e

function msg() {
  echo "*** $1"

function err() {
  echo "ERROR: $1" >&2

# Checks if a shell command is available
function is_installed() {
  command -v $1 > /dev/null

# Install some dependencies automatically if homebrew is installed
is_installed brew && {
  msg "Homebrew is installed"
  is_installed mysql || {
    brew install mysql && brew services start mysql

# Check if MySQL is installed properly before running
is_installed mysql && msg "MySQL is installed" || {
  err "MySQL isn't installed or not in your \$PATH"
  err "PATH=$PATH"
  exit 1

# Ensure ruby is installed
is_installed ruby && msg "Ruby is installed: $(ruby -v)" || {
  err "Ruby isn't installed. Run this and try again:"
  err ""
  err "  brew install rbenv ruby-build"
  err "  rbenv install 2.4.1"
  err ""
  exit 1

# Ensure bundler is installed
is_installed bundle && msg "Bundler is installed" || {
  msg "Installing bundler..."
  gem install bundler || {
    err "Failed to install bundler. Run this and try again:"
    err ""
    err "  gem install bundler"
    err ""
    exit 1

msg "Running bundle install..."
bundle install

msg "Setting up database via rake"
bin/rake db:create db:schema:load db:seed
msg "Done!"

Notice that it isn't perfect in any way. For instance, it wouldn't install mysql if your ran it on a Ubuntu machine, because none of us run Ubuntu locally.