Automation is iteration. First you'll find a way to make it work, and share your learnings - feedback and best practices help make it even better. When I first published my dotfiles - Document and automate your Macbook setup blog post, Nate suggested to use Homebrew bundle for a more clean management approach.
Homebrew bundle follows the same idea as known from Ruby bundle, has a Brewfile and specific keywords for packages to install.
First Steps with Homebrew Bundle
- tap: Add more brew third-party repos
- cask: Install application casks (Gimp, etc.)
- brew: Install packages
- mas: Install App store items (requires
brew install mas)
You can also override the default cask installation path:
$ vim Brewfile cask_args appdir: "/Applications" tap "homebrew/cask" cask "gimp" brew "git" mas "Slack", id: 803453959 Run it to see how it works.
$ brew bundle Using homebrew/cask Using gimp Using git Using Slack Homebrew Bundle complete! 4 Brewfile dependencies now installed. git from Homebrew is newer than the macOS Git binary.
$ git --version git version 2.29.2 $ /usr/bin/git --version git version 2.24.3 (Apple Git-128) Homebrew's Git is installed into /usr/local/bin which has a priority in the PATH environment variable.
$ which git /usr/local/bin/git $ echo $PATH /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin Existing Homebrew Setup? No Problem
bundle provides the dump sub command which writes a new Brewfile with your current setup.
brew bundle dump Homebrew automatically installs the bundle tap the first time the command is invoked, no extra preparations needed.
You can either use this file to continue working, or start fresh in your own Brewfile. You can also manually install software first and then analyse how a dump looks like.
Caveats with GNU tools (sed, tar, ...)
You can install GNU tools to avoid different parameters and behaviour with the native UNIX representation of sed, tar, etc. Homebrew provides binaries prefixed with the g character, so even an updated PATH variable won't help, requiring you to call gsed instead of sed. To keep compatibility with existing Linux scripts, I used symlinks created inside a brew setup script:
BREW_PREFIX=$(brew --prefix) ln -s "${BREW_PREFIX}/bin/gsed" "${BREW_PREFIX}/bin/sed" This isn't possible inside a Brewfile. Luckily this can be automated in your PATH, as the Homebrew formulas provide these symlink overrides on their own:
$ brew info gnu-sed GNU "sed" has been installed as "gsed". If you need to use it as "sed", you can add a "gnubin" directory to your PATH from your bashrc like: PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH" $ ls -la /usr/local/opt/gnu-sed/libexec/gnubin total 0 drwxr-xr-x 3 mfriedrich staff 96 Jan 15 2020 . drwxr-xr-x 5 mfriedrich staff 160 Jan 15 2020 .. lrwxr-xr-x 1 mfriedrich staff 14 Jan 15 2020 sed -> ../../bin/gsed Collect the inventory from all GNU tools and render an update for your environment file. You can automate this task with this inventory snippet added to .oh-my-zsh/custom/path.zsh or .zshrc:
# GNU utils path overrides as default CLI tools if type brew &>/dev/null; then HOMEBREW_PREFIX=$(brew --prefix) for d in ${HOMEBREW_PREFIX}/opt/*/libexec/gnubin; do export PATH=$d:$PATH; done fi If you prefer to use symlinks, you can do so too instead of the export. Keep in mind that the PATH environment is generated on each new terminal, while symlinks can run stale.
A complete example
Follow the iteration in this merge request and open the dotfiles repository to learn more.
My Brewfile focusses on my work as Developer Evangelist at GitLab with a local Linux-ified CLI environment and Docker. Heavier workloads are shifted into cloud environments. Image manipulation tools help with automating tasks for blog posts and workshops.
I'm also not pinning specific versions for packages, this is not supported by Homebrew bundle either.
cask_args appdir: "/Applications" # Tap Homebrew tap "homebrew/bundle" tap "homebrew/cask" tap "homebrew/cask-fonts" tap "homebrew/cask-versions" tap "homebrew/core" tap "homebrew/services" cask "java" cask "visual-studio-code" cask "firefox" cask "vlc" cask "wireshark" cask "gimp" cask "inkscape" cask "jitsi-meet" cask "handbrake" cask "vagrant" cask "spotify" # System brew "mas" brew "curl" brew "wget" brew "git" brew "vim" brew "openssl" brew "coreutils" brew "moreutils" brew "findutils" brew "binutils" brew "rename" brew "gnu-sed" brew "gnu-tar" brew "gawk" brew "gnutls" brew "gnu-indent" brew "gnu-getopt" brew "tree" brew "htop" brew "pidof" brew "pstree" brew "grep" brew "openssh" brew "rsync" brew "ssh-copy-id" brew "screen" brew "gmp" brew "nmap" brew "socat" brew "rlwrap" brew "dnstracer" # Images, Audio, Video brew "imagemagick" brew "gifsicle" brew "gifify" brew "ffmpeg" # Archive & Git brew "xz" brew "p7zip" brew "git" brew "git-lfs" brew "tig" brew "hub" # Extract rpm file content with rpm2cpio *.rpm | cpio -ivd brew "rpm2cpio" # JSON brew "jq" brew "jo" # Dev brew "ruby" brew "yarn" brew "rbenv" brew "python" brew "go" brew "cmake" brew "openjdk" brew "kind" # GitLab Pages brew "hugo" # App Store mas "1Password 7", id: 1333542190 mas "Slack", id: 803453959 mas "Telegram", id: 747648890 mas "uBlock", id: 1385985095
Top comments (0)