Automated MacBook Setup

I just started at Anchore and am eager to start digging into some coding problems as well as helping to cultivate an amazing engineering organization.

While setting up my new MacBook, I figured I should make setup easier for the next person, or even my future self. I learned about Homebrew’s Brewfile for easily installing a whole toolbox of software. I also recalled tricky and scary setup steps in the past and wanted to make sure that whatever I left behind was relatively safe to run blindly. That is, it would be idempotent (running multiple times would have the same effect as running once) and non-destructive.

While the Homebrew install instructions are really simple, I wanted to leave an even simpler script to combine several steps:

#!/usr/bin/env zsh
brew_major_version=$(brew –version | head -c 10)
if [ "$brew_major_version" = 'Homebrew 3' ]; then
echo 'Homebrew already installed'
echo 'Updating Homebrew'
brew update
else
echo 'Installing Homebrew'
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
echo 'Install and update packages in the Brewfile`
brew bundle
view raw homebrew-install.sh hosted with ❤ by GitHub

The Brewfile will probably get long, but here’s how a short one looks:

tap "homebrew/bundle"
tap "homebrew/cask"
tap "homebrew/core"
cask "docker"
cask "iterm2"
cask "visual-studio-code"
view raw Brewfile hosted with ❤ by GitHub

You can manually install from the Brewfile by running brew bundle and you can create a new one based on what you’ve currently installed with brew bundle dump. If you’re tracking the Brewfile in version control, then brew bundle dump --force is handy for overwriting it.

I haven’t used zsh before, but I knew I wanted to try oh-my-zsh as well as use what my teammates were using. Here’s the install script I wrote up for installing, setting plugins, and installing the Powerlevel10k theme:

#!/usr/bin/env zsh
export OMZ=~/.oh-my-zsh
if [ -d $OMZ ]; then
echo 'Oh My Zsh is already installed.'
else
echo 'Installing Oh My Zsh:'
sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
fi
export PLUGINS="alias-finder brew common-aliases git"
if grep -qF "plugins=(git)" ~/.zshrc; then
sed -i '' "s/plugins=(git)/plugins=($PLUGINS)/g" ~/.zshrc
echo 'Oh My Zsh plugins set to baseline.'
source ~/.zshrc
else
echo 'Oh My Zsh plugins left alone because they are not default. Current set of plugins:'
grep "^plugins=" ~/.zshrc
fi
if [ ! -d $ZSH_CUSTOM/themes/powerlevel10k ]; then
git clone –depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k
fi
echo 'Set ZSH_THEME="powerlevel10k/powerlevel10k" in ~/.zshrc if you want this awesome theme.'
view raw oh-my-zsh-install.sh hosted with ❤ by GitHub

I’m pretty happy with this so far and wanted to share.

If I end up with an important set of VS Code extensions (which is likely), I think I’ll lean toward providing them as recommended extensions in each code repo. If they seem important for initial setup, though, then I’m considering something along the lines of dumping the list to a text file with code --list-extensions and then automatically installing with cat vs_code_extensions_list.txt | xargs -n 1 code --install-extension.

Automated MacBook Setup