Day 10 - Create a bin/setup script

Remember those changes we made to your README on day 1? A common area for improvement was around setup instructions.

Know what’s even better than a list of setup instructions to follow? A setup script that does them for you!

Here’s an example that I’ve used on Rails apps to good success:

I name this script setup and throw it in the bin directory.

Ideally, this one command is all someone needs to run before developing on your app or using your tool. But even if you can’t reach this ideal, a bin/setup script will save your users or team members time and frustration.

Today, please spend 20 minutes creating a similar script. You should be able to crib heavily from the example above, but here are a few ideas for things you might include:

  • Download and install dependencies
  • Create necessary databases
  • Seed the database with useful data, like an admin account
  • Set up useful git remotes
  • Set configuration variables / copy config files
  • Print helpful info

If you already have a setup script, try cloning your app into a new directory and running the script. Make sure it still works, and consider if you should add anything to it.

When you’re done, please chime in. Did you think of anything particularly creative to add to your script that others might want to steal? Please share!

I just happen to have been working on this lately.

In our case, we only have a single primary application that everyone works on. We’re considering having the setup script install all the brew dependencies as well.

Here is the script I have so far. We may keep this somewhere else as part of the on-boarding setup, but I thought it might be useful to share as part of this exercise.


# Cause the script to abort if any command fails. This means we don't
# need to chain commands with && as much.
set -e

missing() {
  echo -n "-- Checking for $1... "

  if eval $2 > /dev/null; then
    echo ✔︎
    echo ✗

preinstall_check() {
  echo -n "$1 is missing. Install it? (y/n) "
  read install

  [ "$install" == "y" ]

echo "== Homebrew =="
if missing Homebrew "which brew"; then
  if preinstall_check Homebrew; then
    /usr/bin/ruby -e "$(curl -fsSL"
    echo "Homebrew is required for this setup script. Please install it first."

echo -n "  Updating Homebrew... "
brew update > /dev/null
echo ✔︎

echo "== Brew dependencies =="

if missing PostgreSQL "which postgres"; then
  if preinstall_check PostgreSQL; then
    echo "Installing postgresql..."
    brew install postgresql

if missing "Puma Dev" "which puma-dev"; then
  if preinstall_check "Puma Dev"; then
    echo "Installing puma-dev..."
    brew install puma/puma/puma-dev
    echo "Setting up puma-dev..."
    sudo puma-dev -setup
    puma-dev -install -d test

if missing Redis "which redis-server"; then
  if preinstall_check Redis; then
    echo "Installing redis..."
    brew install redis
    echo "Setting up redis to run in the background at all times..."
    brew services start redis

if missing "ElasticSearch 5.6" "elasticsearch --version | grep 5.6"; then
  if preinstall_check "ElasticSearch 5.6"; then
    echo "Installing ElasticSearch 5.6 and the mapper-attachments plugin..."
    brew install elasticsearch@5.6
    brew link elasticsearch@5.6 --force
    elasticsearch-plugin install mapper-attachments

if missing "Heroku Toolbelt" "which heroku"; then
  echo "Installing the Heroku toolbelt..."
  brew install heroku

if missing "Foreman" "which foreman"; then
  echo "Installing foreman..."
  gem install foreman

echo "All done! You should be good to run the bin/setup script now."

Our code base has setup and discussed many times and moved into wiki pages.

I’ve effectively gone through our setup process and moved it almost whole meal into the setup script, including installation of RVM, binaries, databases, etc.

There were some steps I had issue with and couldn’t quite get to behave, but I’ve simply added these as additional instructions with the hope of reviewing it again another time - perhaps next CQC, but who knows?

We had a new starter coming in soon, so will hopefully have a real world spin at getting this to work.

Anyone have pointers on the easiest way to get a clean setup? (I’m on macOS High Sierra – I was thinking a docker container might be the least destructive way to go to confirm the setup script without having to blow things away locally?)

Well, that took more than 20 minutes :wink:

On the bring side, next time we onboard someone they should be able to get up & running much more easily.

Or they’ll find the bugs in the setup script.