diff --git a/Brewfile b/Brewfile index cd81e03..675029d 100644 --- a/Brewfile +++ b/Brewfile @@ -9,6 +9,17 @@ tap 'homebrew/services' brew 'hub' +brew 'awscli' +brew 'gpg' +brew 'opensc' +brew 'jq' +brew 'packer' +brew 'docker' +brew 'docker-machine' +brew 'ykman' +brew 'coreutils' +brew 'rbenv' + tap 'cloudfoundry/homebrew-tap' brew 'cf-cli' @@ -16,3 +27,7 @@ cask 'chromedriver' cask 'docker' cask 'slack' +cask 'chef/chef/chefdk' +cask 'aws-vault' +cask 'session-manager-plugin' +cask 'xmlstarlet' diff --git a/mac b/mac index 7e655e6..5b0618d 100755 --- a/mac +++ b/mac @@ -1,23 +1,37 @@ #!/bin/bash +################### +### by "unknown" +### update 6/10/2022 Paul Borowicz +################### + +##DEBUG lines (uncomment next 2 lines) +#set -x +#trap read debug + # Welcome to the 18F laptop script! # Be prepared to turn your laptop (or desktop) # into an awesome development machine. +#script should run from home +cd ~/ + +# function to improve readabliity fancy_echo() { # shellcheck disable=SC2039 local fmt="$1"; shift - # shellcheck disable=SC2059 printf "\n$fmt\n" "$@" } +# function to append to file append_to_file() { # shellcheck disable=SC2039 local file="$1" # shellcheck disable=SC2039 local text="$2" + if [ "$file" = "$HOME/.zshrc" ]; then if [ -w "$HOME/.zshrc.local" ]; then file="$HOME/.zshrc.local" @@ -31,10 +45,12 @@ append_to_file() { fi } +# function to append to a specified file append_to_shell_file() { append_to_file "$shell_file" "$1" } +# function to create a file if it does not exist create_and_set_shell_file() { shell_file="$1" if [ ! -f "$shell_file" ]; then @@ -42,14 +58,17 @@ create_and_set_shell_file() { fi } +# function to create .zshrc for zsh shelle create_zshrc_and_set_it_as_shell_file() { create_and_set_shell_file "$HOME/.zshrc" } +# function to create .fishrc for fish shell create_fishconfig_and_set_it_as_shell_file() { create_and_set_shell_file "$HOME/.config/fish/config.fish" } +# function to create .bashrc for bash shell create_bash_profile_and_set_it_as_shell_file() { create_and_set_shell_file "$HOME/.bash_profile" } @@ -57,12 +76,15 @@ create_bash_profile_and_set_it_as_shell_file() { # shellcheck disable=SC2154 trap 'ret=$?; test $ret -ne 0 && printf "failed\n\n" >&2; exit $ret' EXIT +# exit immeditly if a pipeline set -e +# make .bin in home directory if it does not exist if [ ! -d "$HOME/.bin/" ]; then mkdir "$HOME/.bin" fi +#check if shell is fish, zsh, bash, defaults to bash if not fish or zsh but complains vociferously case "$SHELL" in */fish) : create_fishconfig_and_set_it_as_shell_file @@ -109,14 +131,17 @@ case "$SHELL" in ;; esac +#function to check if specific brew package is installed brew_is_installed() { brew list -1 | grep -Fqx "$1" } +# function to check if specific homebrew tap is installed tap_is_installed() { brew tap | grep -Fqx "$1" } +# function to check gems an install or update if necessary gem_install_or_update() { if gem list "$1" | grep "^$1 ("; then fancy_echo "Updating %s ..." "$1" @@ -127,18 +152,22 @@ gem_install_or_update() { fi } +# function to find latest ruby version installed latest_installed_ruby() { find "$HOME/.rubies" -maxdepth 1 -name 'ruby-*' | tail -n1 | grep -E -o '\d+\.\d+\.\d+' } +#function to switch to latest ruby version - REPLACE with rbenv switch_to_latest_ruby() { # shellcheck disable=SC1091 . /usr/local/share/chruby/chruby.sh chruby "ruby-$(latest_installed_ruby)" } - +# define location of laptop script laptop_script_url="https://raw.githubusercontent.com/18F/laptop/master/laptop" + +# case statement to add laptop script to shell rc file case "$SHELL" in */fish) : append_to_shell_file "alias laptop='bash (curl -s $laptop_script_url|psub)'" @@ -152,10 +181,12 @@ case "$SHELL" in ;; esac +# check for homebrew and install if necessary if ! command -v brew >/dev/null; then fancy_echo "Installing Homebrew ..." /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" +# fix bash for shells other then fish case "$SHELL" in */fish) : # noop, fish ships with /usr/local/bin in a good spot in the path @@ -179,9 +210,11 @@ if tap_is_installed 'caskroom/versions'; then brew untap caskroom/versions fi +# update homebrew fancy_echo "Updating Homebrew..." brew update +# Verify homebrew is good fancy_echo "Verifying the Homebrew installation..." if brew doctor; then fancy_echo "Your Homebrew installation is good to go." @@ -191,10 +224,12 @@ else echo "Otherwise, review the Homebrew messages to see if any action is needed." fi +# remove cloudfoundry-cli if brew_is_installed 'cloudfoundry-cli'; then brew uninstall --force cloudfoundry-cli fi +# verify everything is installed fancy_echo "Installing formulas and casks from the Brewfile ..." if brew bundle --file="$HOME/Brewfile"; then fancy_echo "All formulas and casks were installed successfully." @@ -204,6 +239,7 @@ else echo "in which case, you can ignore these errors." fi + case "$SHELL" in */fish) : mkdir -p "$HOME/.config/fish/functions" @@ -222,13 +258,17 @@ case "$SHELL" in fancy_echo "We recommend following the steps at https://github.com/FabioAntunes/fish-nvm to install nvm in fish" ;; esac + +# check nvm installed with homebrew and install if not if ! brew_is_installed "node"; then if command -v n > /dev/null; then fancy_echo "We recommend using \`nvm\` and not \`n\`." fancy_echo "See https://pages.18f.gov/frontend/#install-npm" elif ! command -v nvm > /dev/null; then fancy_echo 'Installing nvm and lts Node.js and npm...' - curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.0/install.sh | bash + # install NVM + # see git repo https://github.com/nvm-sh/nvm/ + curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.39.1/install.sh | bash export NVM_DIR="$HOME/.nvm" # shellcheck source=/dev/null [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" @@ -255,6 +295,7 @@ fancy_echo '...Finished Node.js installation checks.' fancy_echo 'Checking on Python installation...' +# verify python3 installed and install if not if ! brew_is_installed "python3"; then brew bundle --file=- <> "$file" + fi +} + +# function to append to a specified file +append_to_shell_file() { + append_to_file "$shell_file" "$1" +} + +# function to create a file if it does not exist +create_and_set_shell_file() { + shell_file="$1" + if [ ! -f "$shell_file" ]; then + touch "$shell_file" + fi +} + +# function to create .zshrc for zsh shelle +create_zshrc_and_set_it_as_shell_file() { + create_and_set_shell_file "$HOME/.zshrc" +} + +# function to create .fishrc for fish shell +create_fishconfig_and_set_it_as_shell_file() { + create_and_set_shell_file "$HOME/.config/fish/config.fish" +} + +# function to create .bashrc for bash shell +create_bash_profile_and_set_it_as_shell_file() { + create_and_set_shell_file "$HOME/.bash_profile" +} + +# shellcheck disable=SC2154 +trap 'ret=$?; test $ret -ne 0 && printf "failed\n\n" >&2; exit $ret' EXIT + +# exit immeditly if a pipeline +set -e + +# make .bin in home directory if it does not exist +if [ ! -d "$HOME/.bin/" ]; then + mkdir "$HOME/.bin" +fi + +#check if shell is fish, zsh, bash, defaults to bash if not fish or zsh but complains vociferously +case "$SHELL" in + */fish) : + create_fishconfig_and_set_it_as_shell_file + ;; + */zsh) : + create_zshrc_and_set_it_as_shell_file + ;; + *) + create_bash_profile_and_set_it_as_shell_file + if [ -z "$CI" ]; then + bold=$(tput bold) + normal=$(tput sgr0) + echo "Want to switch your shell from the default ${bold}bash${normal} to ${bold}zsh${normal}?" + echo "Both work fine for development, and ${bold}zsh${normal} has some extra " + echo "features for customization and tab completion." + echo "If you aren't sure or don't care, we recommend ${bold}zsh${normal}." + echo "Note that you can always switch back to ${bold}bash${normal} if you change your mind." + echo "Please see the README for instructions." + echo -n "Press ${bold}y${normal} to switch to zsh, ${bold}n${normal} to keep bash: " + read -r -n 1 response + if [ "$response" = "y" ]; then + create_zshrc_and_set_it_as_shell_file + if grep "$(command -v zsh)" > /dev/null 2>&1 < /etc/shells; then + fancy_echo "=== Getting ready to change your shell to zsh. Please enter your password to continue. ===" + echo "=== Note that there won't be visual feedback when you type your password. Type it slowly and press return. ===" + echo "=== Press control-c to cancel ===" + chsh -s "$(command -v zsh)" + else + printf "\n\n" + echo "Can't switch shells automatically in this case. The path to zsh isn't in" + echo "the list of allowed shells. To manually switch to zsh, enter the following" + echo "two lines into your terminal (in another tab, or when this script is done):" + echo "" + echo "sudo echo \"\$(command -v zh)\" >> /etc/shells" + echo "chsh -s \"\$(command -v zs)\"" + sleep 3 + fi + else + fancy_echo "Shell will not be changed." + fi + else + fancy_echo "CI System detected, will not change shells" + fi + ;; +esac + +#function to check if specific brew package is installed +brew_is_installed() { + brew list -1 | grep -Fqx "$1" +} + +# function to check if specific homebrew tap is installed +tap_is_installed() { + brew tap | grep -Fqx "$1" +} + +# function to check gems an install or update if necessary +gem_install_or_update() { + if gem list "$1" | grep "^$1 ("; then + fancy_echo "Updating %s ..." "$1" + gem update "$@" + else + fancy_echo "Installing %s ..." "$1" + gem install "$@" + fi +} + +# function to find latest ruby version installed +latest_installed_ruby() { + find "$HOME/.rubies" -maxdepth 1 -name 'ruby-*' | tail -n1 | grep -E -o '\d+\.\d+\.\d+' +} + +#function to switch to latest ruby version - REPLACE with rbenv +switch_to_latest_ruby() { + # shellcheck disable=SC1091 + . /usr/local/share/chruby/chruby.sh + chruby "ruby-$(latest_installed_ruby)" +} + +# define location of laptop script +laptop_script_url="https://raw.githubusercontent.com/18F/laptop/master/laptop" + +# case statement to add laptop script to shell rc file +case "$SHELL" in + */fish) : + append_to_shell_file "alias laptop='bash (curl -s $laptop_script_url|psub)'" + # shellcheck disable=SC2016 + append_to_shell_file 'set -xg PATH $HOME/.bin $PATH' + ;; + *) : + append_to_shell_file "alias laptop='bash <(curl -s $laptop_script_url)'" + # shellcheck disable=SC2016 + append_to_shell_file 'export PATH="$HOME/.bin:$PATH"' + ;; +esac + +# check for homebrew and install if necessary +if ! command -v brew >/dev/null; then + fancy_echo "Installing Homebrew ..." + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" + +# fix bash for shells other then fish + case "$SHELL" in + */fish) : + # noop, fish ships with /usr/local/bin in a good spot in the path + ;; + *) : + # shellcheck disable=SC2016 + append_to_shell_file 'export PATH="/usr/local/bin:$PATH"' + ;; + esac +else + fancy_echo "Homebrew already installed. Skipping ..." +fi + +# Remove brew-cask since it is now installed as part of brew tap caskroom/cask. +# See https://github.com/caskroom/homebrew-cask/releases/tag/v0.60.0 +if brew_is_installed 'brew-cask'; then + brew uninstall --force 'brew-cask' +fi + +if tap_is_installed 'caskroom/versions'; then + brew untap caskroom/versions +fi + +# update homebrew +fancy_echo "Updating Homebrew..." +brew update + +# Verify homebrew is good +fancy_echo "Verifying the Homebrew installation..." +if brew doctor; then + fancy_echo "Your Homebrew installation is good to go." +else + fancy_echo "Your Homebrew installation reported some errors or warnings." + echo "If the warnings are related to Python, you can ignore them." + echo "Otherwise, review the Homebrew messages to see if any action is needed." +fi + +# remove cloudfoundry-cli +if brew_is_installed 'cloudfoundry-cli'; then + brew uninstall --force cloudfoundry-cli +fi + +# verify everything is installed +fancy_echo "Installing formulas and casks from the Brewfile ..." +if brew bundle --file="$HOME/Brewfile"; then + fancy_echo "All formulas and casks were installed successfully." +else + fancy_echo "Some formulas or casks failed to install." + echo "This is usually due to one of the Mac apps being already installed," + echo "in which case, you can ignore these errors." +fi + + +case "$SHELL" in + */fish) : + mkdir -p "$HOME/.config/fish/functions" + hub alias fish > "$HOME/.config/fish/functions/git.fish" + ;; + *) : + # shellcheck disable=SC2016 + append_to_shell_file 'eval "$(hub alias -s)"' + ;; +esac + +fancy_echo 'Checking on Node.js installation...' + +case "$SHELL" in + */fish) : + fancy_echo "We recommend following the steps at https://github.com/FabioAntunes/fish-nvm to install nvm in fish" + ;; +esac + +# check nvm installed with homebrew and install if not +if ! brew_is_installed "node"; then + if command -v n > /dev/null; then + fancy_echo "We recommend using \`nvm\` and not \`n\`." + fancy_echo "See https://pages.18f.gov/frontend/#install-npm" + elif ! command -v nvm > /dev/null; then + fancy_echo 'Installing nvm and lts Node.js and npm...' + # install NVM + # see git repo https://github.com/nvm-sh/nvm/ + curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.39.1/install.sh | bash + export NVM_DIR="$HOME/.nvm" + # shellcheck source=/dev/null + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + # nvm is a bash script itself, some commands of which may fail WITHOUT + # causing the whole operation to fail. To accomdate that, disable exit on + # any nonzero exit code while nvm runs. + set +e + + nvm install --lts + + # Turn it back on when nvm is done, since the rest of this script may have + # been written assuming this behavior. + set -e + else + fancy_echo 'version manager detected. Skipping...' + fi +else + brew bundle --file=- < /dev/null; then eval "$(pyenv init -)"; fi' + # shellcheck disable=SC2016 + append_to_shell_file 'if which pyenv-virtualenv-init > /dev/null; then eval "$(pyenv virtualenv-init -)"; fi' + esac + + # pyenv currently doesn't have a convenience version to use, e.g., "latest", + # so we check for the latest version against Homebrew instead. + latest_python_3="$(brew info python3 | grep -E -o "3\.\d+\.\d+" | head -1)" + + if ! pyenv versions | ag "$latest_python_3" > /dev/null; then + # Starting with macOS 10.14 (Mojave), the header files for system libraries + # have been moved. Rather than hack the header paths based on OS version, + # just install zlib with brew and build against that directly for now. + brew install zlib + export LDFLAGS="-L/usr/local/opt/zlib/lib" + export CPPFLAGS="-I/usr/local/opt/zlib/include" + pyenv install "$latest_python_3" + pyenv global "$latest_python_3" + pyenv rehash + fi +else + brew bundle --file=- < /dev/null; then + case "$SHELL" in + */fish) : + fancy_echo "virtualenvwrapper is not compatible with fish" + ;; + *) : + fancy_echo 'Installing virtualenvwrapper...' + pip3 install virtualenvwrapper + append_to_shell_file 'export VIRTUALENVWRAPPER_PYTHON=/usr/local/bin/python3' + append_to_shell_file 'export VIRTUALENVWRAPPER_VIRTUALENV=/usr/local/bin/virtualenv' + append_to_shell_file 'source /usr/local/bin/virtualenvwrapper.sh' + ;; + esac + fi +fi + +fancy_echo '...Finished Python installation checks.' + + +fancy_echo 'Checking on Ruby installation...' + +append_to_file "$HOME/.gemrc" 'gem: --no-document' + +case "$SHELL" in + */fish) : + fancy_echo "We recommend following the steps at https://github.com/JeanMertz/chruby-fish to install chruby in fish" + ;; + + # For all other shells, install chruby as long as rbenv is not installed + *) : + if command -v rbenv >/dev/null || command -v rvm >/dev/null; then + fancy_echo 'We recommend chruby and ruby-install over RVM or rbenv' + else + if ! brew_is_installed "chruby"; then + fancy_echo 'Installing chruby, ruby-install, and the latest Ruby...' + + brew bundle --file=- < /dev/null + latest_stable_ruby="$(cat < "$HOME/.cache/ruby-install/ruby/stable.txt" | tail -n1)" + + if ! [ "$latest_stable_ruby" = "$(latest_installed_ruby)" ]; then + fancy_echo "Installing latest stable Ruby version: $latest_stable_ruby" + ruby-install ruby + else + fancy_echo 'You have the latest version of Ruby' + fi + fi + fi +esac + +## Install rbenv 2.7 +rbenv init +rbenv install 2.7 +rbenv alias 2.7 2.7.0 + +fancy_echo 'Updating Rubygems...' +gem update --system + +gem_install_or_update 'bundler' + +fancy_echo "Configuring Bundler ..." +number_of_cores=$(sysctl -n hw.ncpu) +bundle config --global jobs $((number_of_cores - 1)) + +fancy_echo '...Finished Ruby installation checks.' + +curl -s https://raw.githubusercontent.com/18F/laptop/master/seekrets-install | sh - + +if [ -f "$HOME/.laptop.local" ]; then + # shellcheck source=/dev/null + . "$HOME/.laptop.local" +fi + +fancy_echo 'All done!'