Using Homebrew to Manage Project Development Scripts
When a project becomes sufficiently large in size you will undoubtedly encounter the need to simplify certain tasks, such as managing external dependencies or configuring environment parameters. Within the MyBuilder code-base we have required these kinds of processes for some time.
Initially starting with a dev-upload
function, it soon grew to a shared shell script which all users had to manually update (think ‘old-school’ copy n’ paste dependency management).
This was not ideal and we pondered on several different solutions to manage this problem, such as using Composer scripts.
We eventually settled on taking advantage of Homebrew (the Mac package manager), thanks to a podcast that Gavin had listened to.
Using this approach allows us to not only manage scripts, but far more complex installation requirements in the future.
In this post I would like to discuss how we went about creating a personal Homebrew Tap and Formula, configured to provide the desired up-to-date scripts which aid in managing the project.
Defining the Formula
Homebrew is well suited to accessing and downloading Taps found on GitHub, providing you abide by some conventions.
The repository name (Tap) should begin with homebrew-
and include all Formulas within a root Formula
directory.
Below is a simple Formula definiton which provides access to two scripts along with ‘keg-only’ access to a common
script file which is used in both.
class ProjectDevTools < Formula
desc "Provides scripts to make it easier to work with the code-base"
url 'https://github.com/eddmann/homebrew-project-dev-tools.git'
def install
prefix.install "src/common"
bin.install "src/dev-rebuild", "src/dev-tools-update"
end
end
Setting up the Example Scripts
Now that we have a mechanism to manage the development scripts lets create some example scripts.
I have found it beneficial to be able to reuse an environment variable guard and run
function within each of the subsequent scripts.
The run
function provides us with the ability to conditional suppress command invocation output, if verbose mode is not enabled.
#!/bin/bash
ERROR='\033[41;1;37m'
BLUE='\033[0;34m'
GREEN='\033[0;32m'
NC='\033[0m'
if [[ -z "$PROJECT_ROOT_DIR" || ! -d "$PROJECT_ROOT_DIR" ]]; then
printf "⚠️ Make sure you have ${ERROR}PROJECT_ROOT_DIR${NC} set\n"
exit 1
fi
for arg in "$@"; do
shift
if [[ "$arg" == "-v" ]]; then
VERBOSE_MODE=1
continue # remove `-v` from args
fi
set -- "$@" "$arg"
done
function run()
{
if [[ $VERBOSE_MODE -eq 1 ]]; then
echo "$" "$@"
eval $(printf '%q ' "$@")
else
eval $(printf '%q ' "$@") &> /dev/null
if [ $? -ne 0 ]; then
printf "${ERROR}⚠️ Error${NC}\n"
exit 1
else
printf "✓\n"
fi
fi
}
With this script now in-place, we can move on to defining the required steps to rebuild the contrived project.
You will notice below that we attempt to source the common
file from the local src
directory first, this is so throughout development we can easily work with pending changes.
#!/bin/bash
source src/common 2> /dev/null || source $(brew --prefix project-dev-tools)/common
APP_NAME="${1:-*}"
for app in $PROJECT_ROOT_DIR/app/$APP_NAME/; do
[[ ! -d "$app" ]] && continue
name=$(basename "$app")
printf "💾 ${GREEN}$name${NC} ${BLUE}[$app]${NC}\n"
printf "> running composer install... "
run composer install -d "$app"
printf "> clearing cache... "
run rm -fr "${app}cache/*"
printf "\n"
done
printf "🎉 Rebuild Complete!\n"
exit 0
Another useful script that we have found is the ability to update the Formula without the need to understand how Homebrew works. Using the script below - the Tap is updated and Formula re-installed, to ensure that we are using the latest version available within the repository.
#!/bin/bash
source src/common 2> /dev/null || source $(brew --prefix project-dev-tools)/common
printf "> reinstalling project-dev-tools... "
run brew reinstall project-dev-tools
printf "🎉 Update Complete!\n"
exit 0
With this now all in-place we can use the following commands to initially install the new Formula on a development machine.
Once this has been successfully run, we can move over to use the newly installed dev-tools-update
script for future updates.
brew tap eddmann/project-dev-tools
brew install project-dev-tools
Demo
The example Tap and Formula can be found within this GitHub repository. You can see an interactive example of installing and using the scripts created below: