From 1bbaa4f6ad57a4331f535d5745b0c43a5091d7e1 Mon Sep 17 00:00:00 2001 From: Brendon Smith Date: Sun, 5 Nov 2023 19:19:44 -0500 Subject: [PATCH] WIP: Enable non-admin and non-sudo `bootstrap.sh` usage --- .github/workflows/ci.yml | 53 +++++++- README.md | 11 +- bootstrap.sh | 274 ++++++++++++++++++++++----------------- 3 files changed, 215 insertions(+), 123 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 16693e8..33d5b7b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,6 +53,7 @@ jobs: needs: [check] runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: os: [macos-14, ubuntu-latest] timeout-minutes: 100 @@ -69,6 +70,11 @@ jobs: run: | # mitigate https://github.com/actions/runner-images/issues/6283 echo "/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin" >>"$GITHUB_PATH" + - name: Set bootstrap script URL + run: | + STRAP_SCRIPT_URL="https://raw.githubusercontent.com/$STRAP_GITHUB_USER/dotfiles/$STRAP_DOTFILES_BRANCH/bootstrap.sh" + echo "STRAP_SCRIPT_URL=$STRAP_SCRIPT_URL" + echo "STRAP_SCRIPT_URL=$STRAP_SCRIPT_URL" >>"$GITHUB_ENV" - name: Clean up Homebrew run: | command -v brew &>/dev/null && brew test-bot --only-cleanup-before || @@ -78,12 +84,53 @@ jobs: run: | sudo rm -rf /usr/local/Caskroom /usr/local/Homebrew /usr/local/bin/brew \ /usr/local/.??* /Applications/Xcode.app /Library/Developer/CommandLineTools - - name: Run bootstrap.sh + - name: Create a non-admin user account + run: | + username=standard-user + if ${{ runner.os == 'Linux' }}; then + sudo adduser --disabled-password --gecos "" $username + home_prefix=/home + elif ${{ runner.os == 'macOS' }}; then + # TODO: admin user is being created + sudo sysadminctl -addUser $username + home_prefix=/Users + fi + echo "NON_ADMIN_USER=$username" >>"$GITHUB_ENV" + echo "NON_ADMIN_USER_HOME=$home_prefix/$username" >>"$GITHUB_ENV" + - name: > + Run bootstrap.sh with a non-admin non-sudo user without Homebrew installed + (Homebrew installation requires sudo) + id: bootstrap-non-admin-non-sudo run: | - bootstrap_script_url="https://raw.githubusercontent.com/$STRAP_GITHUB_USER/dotfiles/$STRAP_DOTFILES_BRANCH/bootstrap.sh" - /usr/bin/env bash -c "$(curl -fsSL $bootstrap_script_url)" + sudo \ + --preserve-env=STRAP_CI,STRAP_DEBUG,STRAP_DOTFILES_BRANCH,STRAP_GIT_EMAIL,STRAP_GIT_NAME,STRAP_GITHUB_USER,STRAP_SCRIPT_URL \ + -u "$NON_ADMIN_USER" bash -c '/usr/bin/env bash -c "$(curl -fsSL ${{ env.STRAP_SCRIPT_URL }})"' + working-directory: ${{ env.NON_ADMIN_USER_HOME }} + continue-on-error: true + - name: Run bootstrap.sh with a non-admin sudo user without Homebrew installed + run: | + if ${{ runner.os == 'Linux' }}; then + # sudo usermod -aG sudo "$NON_ADMIN_USER" + SUDOERS_FILE="/etc/sudoers.d/$NON_ADMIN_USER" + echo "$NON_ADMIN_USER ALL=(ALL) NOPASSWD:ALL" | sudo tee "$SUDOERS_FILE" + sudo chmod 0440 "$SUDOERS_FILE" + elif ${{ runner.os == 'macOS' }}; then + echo "TODO: need macOS command for adding sudo" + fi + sudo \ + --preserve-env=STRAP_CI,STRAP_DEBUG,STRAP_DOTFILES_BRANCH,STRAP_GIT_EMAIL,STRAP_GIT_NAME,STRAP_GITHUB_USER,STRAP_SCRIPT_URL \ + -u "$NON_ADMIN_USER" bash -c '/usr/bin/env bash -c "$(curl -fsSL ${{ env.STRAP_SCRIPT_URL }})"' + working-directory: ${{ env.NON_ADMIN_USER_HOME }} + - name: Run bootstrap.sh + run: /usr/bin/env bash -c "$(curl -fsSL $STRAP_SCRIPT_URL)" - name: Rerun bootstrap.sh to test idempotence run: bash "$HOME/.dotfiles/bootstrap.sh" + - name: Rerun bootstrap.sh with a non-admin user after Homebrew has been installed + run: | + sudo \ + --preserve-env=STRAP_CI,STRAP_DEBUG,STRAP_DOTFILES_BRANCH,STRAP_GIT_EMAIL,STRAP_GIT_NAME,STRAP_GITHUB_USER,STRAP_SCRIPT_URL \ + -u "$NON_ADMIN_USER" bash -c '/usr/bin/env bash "${{ env.NON_ADMIN_USER_HOME }}/.dotfiles/bootstrap.sh"' + working-directory: ${{ env.NON_ADMIN_USER_HOME }} - name: Check Homebrew configuration run: brew config - name: Check for potential problems with brew doctor diff --git a/README.md b/README.md index 719ef7c..c276cb7 100644 --- a/README.md +++ b/README.md @@ -64,9 +64,16 @@ The following environment variables can be used to configure _bootstrap.sh_, and - `STRAP_DOTFILES_URL`: URL from which the dotfiles repo will be cloned. Defaults to `https://github.com/$STRAP_GITHUB_USER/dotfiles`, but any [Git-compatible URL](https://www.git-scm.com/docs/git-clone#_git_urls) can be used, so long as it is accessible at the time the script runs. - `STRAP_DOTFILES_BRANCH`: Git branch to check out after cloning dotfiles repo. Defaults to `main`. -_bootstrap.sh_ will set up macOS and Homebrew, run scripts in the _scripts/_ directory, and install Homebrew packages and casks from the _[Brewfile](Brewfile)_. +There are some additional variables for advanced usage. Consult the _[bootstrap.sh](bootstrap.sh)_ script to see all supported variables. -A Brewfile is a list of [Homebrew](https://brew.sh/) packages and casks (applications) that can be installed in a batch by [Homebrew Bundle](https://github.com/Homebrew/homebrew-bundle). The Brewfile can even be used to install Mac App Store apps with the `mas` CLI. Note that you must sign in to the App Store ahead of time for `mas` to work. +_bootstrap.sh_ will set up macOS and Homebrew, run scripts in the _scripts/_ directory, and install Homebrew packages and casks from the _[Brewfile](Brewfile)_. A Brewfile is a list of [Homebrew](https://brew.sh/) packages and casks (applications) that can be installed in a batch by [Homebrew Bundle](https://github.com/Homebrew/homebrew-bundle). The Brewfile can even be used to install Mac App Store apps with the `mas` CLI. Note that you must sign in to the App Store ahead of time for `mas` to work. + +The following list is a brief summary of permissions related to _bootstrap.sh_. + +- Initial setup of Homebrew itself does not require an admin user account, but does require `sudo`. See the [Homebrew installation docs](https://docs.brew.sh/Installation), [Homebrew/install#312](https://github.com/Homebrew/install/issues/312), and [Homebrew/install#315](https://github.com/Homebrew/install/pull/315/files). +- [After Homebrew setup, use of `sudo` with `brew` commands is discouraged](https://docs.brew.sh/FAQ#why-does-homebrew-say-sudo-is-bad). +- After Homebrew setup, commands such as `brew bundle install --global` should be run from the same user account used for setup. Attempts to run `brew` commands from another user account will result in errors, because directories that need to be updated are owned by the setup account. If access to the setup account is not routinely available, an alternative approach could be to change ownership of Homebrew directories to a group that includes the user account used for Homebrew setup as well as other users that need to run Homebrew commands. +- _bootstrap.sh_ can run with limited functionality on non-admin and non-`sudo` user accounts. A plausible use case could exist in which an admin runs `bootstrap.sh` to configure the system initially, then a non-admin runs `bootstrap.sh` to configure their own account. In this use case, the non-admin user should not need admin or `sudo` privileges, because all the pertinent setup (FileVault disk encryption, XCode developer tools, Homebrew, etc) is already complete. Users with more complex needs for multi-environment dotfiles management might consider a tool like [`chezmoi`](https://www.chezmoi.io/). diff --git a/bootstrap.sh b/bootstrap.sh index cc33251..f758f0b 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -27,6 +27,8 @@ Linux) esac [[ -z $HOMEBREW_PREFIX ]] && HOMEBREW_PREFIX="$DEFAULT_HOMEBREW_PREFIX" +STRAP_ADMIN=${STRAP_ADMIN:-0} +if groups | grep -qE "\b(admin)\b"; then STRAP_ADMIN=1; else STRAP_ADMIN=0; fi STRAP_CI=${STRAP_CI:=0} STRAP_DEBUG=${STRAP_DEBUG:-0} [[ $1 = "--debug" || -o xtrace ]] && STRAP_DEBUG=1 @@ -40,6 +42,7 @@ DEFAULT_DOTFILES_URL="https://github.com/$STRAP_GITHUB_USER/dotfiles" STRAP_DOTFILES_URL=${STRAP_DOTFILES_URL:="$DEFAULT_DOTFILES_URL"} STRAP_DOTFILES_BRANCH=${STRAP_DOTFILES_BRANCH:="main"} STRAP_SUCCESS="" +STRAP_SUDO=0 sudo_askpass() { if [ -n "$SUDO_ASKPASS" ]; then @@ -51,8 +54,10 @@ sudo_askpass() { cleanup() { set +e - sudo_askpass rm -rf "$CLT_PLACEHOLDER" "$SUDO_ASKPASS" "$SUDO_ASKPASS_DIR" - sudo --reset-timestamp + if [ -n "$SUDO_ASKPASS" ]; then + sudo_askpass rm -rf "$CLT_PLACEHOLDER" "$SUDO_ASKPASS" "$SUDO_ASKPASS_DIR" + sudo --reset-timestamp + fi if [ -z "$STRAP_SUCCESS" ]; then if [ -n "$STRAP_STEP" ]; then echo "!!! $STRAP_STEP FAILED" >&2 @@ -73,18 +78,41 @@ else Q="$STRAP_QUIET_FLAG" fi -# Prompt for sudo password and initialize (or reinitialize) sudo -sudo --reset-timestamp - clear_debug() { set +x } + reset_debug() { if [ "$STRAP_DEBUG" -gt 0 ]; then set -x fi } +abort() { + STRAP_STEP="" + echo "!!! $*" >&2 + exit 1 +} + +escape() { + printf '%s' "${1//\'/\'}" +} + +log_no_sudo() { + STRAP_STEP="$*" + echo "--> $*" +} + +logk() { + STRAP_STEP="" + echo "OK" +} + +logn_no_sudo() { + STRAP_STEP="$*" + printf -- "--> %s " "$*" +} + logskip() { STRAP_STEP="" echo "SKIPPED" @@ -92,13 +120,15 @@ logskip() { } sudo_init() { - if [ "$STRAP_INTERACTIVE" -eq 0 ]; then return; fi + if [ "$STRAP_INTERACTIVE" -eq 0 ]; then + sudo -n -l mkdir &>/dev/null && export STRAP_SUDO=1 + return + fi # Check and, if necessary, enable sudo authentication using TouchID. # Don't care about non-alphanumeric filenames when doing a specific match # shellcheck disable=SC2010,SC2086 if ls /usr/lib/pam | grep $Q "pam_tid.so"; then - STRAP_STEP="Configuring sudo authentication using TouchID:" - echo "--> $STRAP_STEP" + logn_no_sudo "Configuring sudo authentication using TouchID:" if [[ -f /etc/pam.d/sudo_local || -f /etc/pam.d/sudo_local.template ]]; then # New in macOS Sonoma, survives updates. PAM_FILE="/etc/pam.d/sudo_local" @@ -147,8 +177,9 @@ sudo_init() { chmod 700 "$SUDO_ASKPASS_DIR" "$SUDO_ASKPASS" bash -c "cat > '$SUDO_ASKPASS'" <<<"$SUDO_PASSWORD_SCRIPT" unset SUDO_PASSWORD_SCRIPT + STRAP_SUDO=1 reset_debug - export SUDO_ASKPASS + export STRAP_SUDO SUDO_ASKPASS fi } @@ -159,40 +190,30 @@ sudo_refresh() { else sudo_init fi + echo "STRAP_SUDO=$STRAP_SUDO" reset_debug } -abort() { - STRAP_STEP="" - echo "!!! $*" >&2 - exit 1 -} log() { STRAP_STEP="$*" sudo_refresh echo "--> $*" } + logn() { STRAP_STEP="$*" sudo_refresh printf -- "--> %s " "$*" } -logk() { - STRAP_STEP="" - echo "OK" -} -escape() { - printf '%s' "${1//\'/\'}" -} # Given a list of scripts in the dotfiles repo, run the first one that exists run_dotfile_scripts() { - if [ -d ~/.dotfiles ]; then + if [ -d "$HOME/.dotfiles" ]; then ( - cd ~/.dotfiles + cd "$HOME/.dotfiles" for i in "$@"; do if [ -f "$i" ] && [ -x "$i" ]; then - log "Running dotfiles $i:" + log_no_sudo "Running dotfiles $i:" if [ "$STRAP_DEBUG" -eq 0 ]; then "$i" 2>/dev/null else @@ -208,7 +229,7 @@ run_dotfile_scripts() { [ "$USER" = "root" ] && abort "Run bootstrap.sh as yourself, not root." # shellcheck disable=SC2086 -if [ "$MACOS" -gt 0 ]; then +if [ "$MACOS" -gt 0 ] && [ "$STRAP_ADMIN" -gt 0 ]; then [ "$STRAP_CI" -eq 0 ] && caffeinate -s -w $$ & groups | grep $Q -E "\b(admin)\b" || abort "Add $USER to admin." logn "Configuring security settings:" @@ -235,23 +256,21 @@ if [ "$MACOS" -gt 0 ]; then fi # Check for and enable full-disk encryption -logn "Checking full-disk encryption status:" -VAULT_MSG="FileVault is (On|Off, but will be enabled after the next restart)." -# shellcheck disable=SC2086 -if fdesetup status | grep $Q -E "$VAULT_MSG"; then - logk -elif [ "$MACOS" -eq 0 ] || [ "$STRAP_CI" -gt 0 ]; then - echo - logn "Skipping full-disk encryption." -elif [ "$STRAP_INTERACTIVE" -gt 0 ]; then - echo - log "Enabling full-disk encryption on next reboot:" - sudo_askpass fdesetup enable -user "$USER" | - tee ~/Desktop/"FileVault Recovery Key.txt" - logk -else - echo - abort "Run 'sudo fdesetup enable -user \"$USER\"' for full-disk encryption." +if [ "$MACOS" -eq 0 ] || [ "$STRAP_ADMIN" -eq 0 ] || [ "$STRAP_CI" -gt 0 ]; then + logskip "Skipping full-disk encryption." +elif [ "$MACOS" -gt 0 ] && [ "$STRAP_ADMIN" -gt 0 ]; then + logn "Checking full-disk encryption status:" + VAULT_MSG="FileVault is (On|Off, but will be enabled after the next restart)." + # shellcheck disable=SC2086 + if fdesetup status | grep $Q -E "$VAULT_MSG"; then + logk + elif sudo_askpass fdesetup enable -user "$USER" | + tee ~/Desktop/"FileVault Recovery Key.txt"; then + log "Full-disk encryption will be enabled after next reboot:" + logk + else + abort "Run 'sudo fdesetup enable -user \"$USER\"' for full-disk encryption." + fi fi # Set up Xcode Command Line Tools @@ -296,96 +315,100 @@ check_xcode_license() { fi } -if [ "$MACOS" -gt 0 ]; then +check_software_updates() { + log "Checking for software updates:" + # shellcheck disable=SC2086 + if softwareupdate -l 2>&1 | grep $Q "No new software available."; then + logk + else + if [ "$MACOS" -gt 0 ] && [ "$STRAP_CI" -eq 0 ]; then + echo + log "Installing software updates:" + sudo_askpass softwareupdate --install --all + check_xcode_license + else + logskip "Skipping software updates." + fi + logk + fi +} + +if [ "$MACOS" -gt 0 ] && [ "$STRAP_ADMIN" -gt 0 ]; then install_xcode_clt check_xcode_license + check_software_updates else - log "Not macOS. Xcode CLT install and license check skipped." + logskip "Xcode Command-Line Tools install and license check skipped." fi configure_git() { - logn "Configuring Git:" - if [ "$STRAP_CI" -gt 0 ]; then - git config --global commit.gpgsign false - git config --global gpg.format openpgp - fi - if [ -n "$STRAP_GIT_NAME" ] && ! git config user.name >/dev/null; then - git config --global user.name "$STRAP_GIT_NAME" - fi - if [ -n "$STRAP_GIT_EMAIL" ] && ! git config user.email >/dev/null; then - git config --global user.email "$STRAP_GIT_EMAIL" - fi - if [ -n "$STRAP_GITHUB_USER" ] && - [ "$(git config github.user)" != "$STRAP_GITHUB_USER" ]; then - git config --global github.user "$STRAP_GITHUB_USER" - fi - # Set up GitHub HTTPS credentials - # shellcheck disable=SC2086 - if git credential-osxkeychain 2>&1 | grep $Q "git.credential-osxkeychain"; then - # Execute credential in case it's a wrapper script for credential-osxkeychain - if git "credential-$(git config --global credential.helper 2>/dev/null)" 2>&1 | - grep -v $Q "git.credential-osxkeychain"; then - git config --global credential.helper osxkeychain + log_no_sudo "Configuring Git:" + if [ "$STRAP_ADMIN" -gt 0 ]; then + # git config --global commands may require access to + # global .gitconfig files owned by admin accounts + if [ -n "$STRAP_GIT_NAME" ] && ! git config user.name >/dev/null; then + git config --global user.name "$STRAP_GIT_NAME" fi - if [ -n "$STRAP_GITHUB_USER" ] && [ -n "$STRAP_GITHUB_TOKEN" ]; then - PROTOCOL="protocol=https\\nhost=github.com" - printf "%s\\n" "$PROTOCOL" | git credential reject - printf "%s\\nusername=%s\\npassword=%s\\n" \ - "$PROTOCOL" "$STRAP_GITHUB_USER" "$STRAP_GITHUB_TOKEN" | - git credential approve - else - log "Skipping Git credential setup." + if [ -n "$STRAP_GIT_EMAIL" ] && ! git config user.email >/dev/null; then + git config --global user.email "$STRAP_GIT_EMAIL" fi - logk + if [ -n "$STRAP_GITHUB_USER" ] && + [ "$(git config github.user)" != "$STRAP_GITHUB_USER" ]; then + git config --global github.user "$STRAP_GITHUB_USER" + fi + # Set up GitHub HTTPS credentials + # shellcheck disable=SC2086 + if git credential-osxkeychain 2>&1 | grep $Q "git.credential-osxkeychain"; then + # Execute credential in case it's a wrapper script for credential-osxkeychain + if git "credential-$(git config --global credential.helper 2>/dev/null)" 2>&1 | + grep -v $Q "git.credential-osxkeychain"; then + git config --global credential.helper osxkeychain + fi + fi + fi + if [ -n "$STRAP_GITHUB_USER" ] && [ -n "$STRAP_GITHUB_TOKEN" ]; then + PROTOCOL="protocol=https\\nhost=github.com" + printf "%s\\n" "$PROTOCOL" | git credential reject + printf "%s\\nusername=%s\\npassword=%s\\n" \ + "$PROTOCOL" "$STRAP_GITHUB_USER" "$STRAP_GITHUB_TOKEN" | + git credential approve + else + logskip "Skipping Git credential setup." fi + logk } # The first call to `configure_git` is needed for cloning the dotfiles repo. configure_git -# Check for and install any remaining software updates -logn "Checking for software updates:" -# shellcheck disable=SC2086 -if softwareupdate -l 2>&1 | grep $Q "No new software available."; then - logk -else - if [ "$MACOS" -gt 0 ] && [ "$STRAP_CI" -eq 0 ]; then - echo - log "Installing software updates:" - sudo_askpass softwareupdate --install --all - check_xcode_license - else - log "Skipping software updates." - fi - logk -fi - # Set up dotfiles # shellcheck disable=SC2086 if [ ! -d "$HOME/.dotfiles" ]; then if [ -z "$STRAP_DOTFILES_URL" ] || [ -z "$STRAP_DOTFILES_BRANCH" ]; then abort "Please set STRAP_DOTFILES_URL and STRAP_DOTFILES_BRANCH." fi - log "Cloning $STRAP_DOTFILES_URL to ~/.dotfiles." - git clone $Q "$STRAP_DOTFILES_URL" ~/.dotfiles + log_no_sudo "Cloning $STRAP_DOTFILES_URL to $HOME/.dotfiles." + git clone $Q "$STRAP_DOTFILES_URL" "$HOME/.dotfiles" fi strap_dotfiles_branch_name="${STRAP_DOTFILES_BRANCH##*/}" -log "Checking out $strap_dotfiles_branch_name in ~/.dotfiles." +log_no_sudo "Checking out $strap_dotfiles_branch_name in $HOME/.dotfiles." # shellcheck disable=SC2086 ( - cd ~/.dotfiles + cd "$HOME/.dotfiles" git stash git fetch $Q git checkout "$strap_dotfiles_branch_name" git pull $Q --rebase --autostash ) -run_dotfile_scripts scripts/symlink.sh -logk - -# The second call to `configure_git` is needed for CI use cases when certain +# This call to `git config` is needed for CI use cases in which certain # aspects of the `.gitconfig` cannot be used (like signing commits with SSH). # See commit c0542397e817fc1bd711984619eb73a6fdc937b2. -configure_git +if [ "$STRAP_CI" -gt 0 ] && git rev-parse 2>/dev/null; then + git config commit.gpgsign false + git config gpg.format openpgp +fi +run_dotfile_scripts scripts/symlink.sh +logk # shellcheck disable=SC2086 install_homebrew() { @@ -424,7 +447,7 @@ install_homebrew() { set_up_brew_skips() { local brewfile_path casks ci_skips mas_ids mas_prefix - log "Setting up Homebrew Bundle formula installs to skip." + log_no_sudo "Setting up Homebrew Bundle formula installs to skip." ci_skips="awscli black jupyterlab mkvtoolnix zsh-completions" [ "$STRAP_CI" -gt 0 ] && HOMEBREW_BUNDLE_BREW_SKIP="$ci_skips" if [ -f "$HOME/.Brewfile" ]; then @@ -434,16 +457,16 @@ set_up_brew_skips() { else abort "No Brewfile found" fi - log "Setting up Homebrew Bundle cask installs to skip." + log_no_sudo "Setting up Homebrew Bundle cask installs to skip." if [ "$MACOS" -gt 0 ] && [ "$brewfile_path" == "$HOME/.Brewfile" ]; then casks="$(brew bundle list --global --cask --quiet | tr '\n' ' ')" elif [ "$MACOS" -gt 0 ] && [ "$brewfile_path" == "Brewfile" ]; then casks="$(brew bundle list --cask --quiet | tr '\n' ' ')" else - log "Cask commands are only supported on macOS." + log_no_sudo "Cask commands are only supported on macOS." fi HOMEBREW_BUNDLE_CASK_SKIP="${casks%% }" - log "Setting up Homebrew Bundle Mac App Store (mas) installs to skip." + log_no_sudo "Setting up Homebrew Bundle Mac App Store (mas) installs to skip." mas_ids="" mas_prefix='*mas*, id: ' while read -r brewfile_line; do @@ -451,9 +474,9 @@ set_up_brew_skips() { [[ $brewfile_line == *$mas_prefix* ]] && mas_ids+="${brewfile_line##$mas_prefix} " done <"$brewfile_path" HOMEBREW_BUNDLE_MAS_SKIP="${mas_ids%% }" - log "HOMEBREW_BUNDLE_BREW_SKIP='$HOMEBREW_BUNDLE_BREW_SKIP'" - log "HOMEBREW_BUNDLE_CASK_SKIP='$HOMEBREW_BUNDLE_CASK_SKIP'" - log "HOMEBREW_BUNDLE_MAS_SKIP='$HOMEBREW_BUNDLE_MAS_SKIP'" + log_no_sudo "HOMEBREW_BUNDLE_BREW_SKIP='$HOMEBREW_BUNDLE_BREW_SKIP'" + log_no_sudo "HOMEBREW_BUNDLE_CASK_SKIP='$HOMEBREW_BUNDLE_CASK_SKIP'" + log_no_sudo "HOMEBREW_BUNDLE_MAS_SKIP='$HOMEBREW_BUNDLE_MAS_SKIP'" export HOMEBREW_BUNDLE_BREW_SKIP="$HOMEBREW_BUNDLE_BREW_SKIP" export HOMEBREW_BUNDLE_CASK_SKIP="$HOMEBREW_BUNDLE_CASK_SKIP" export HOMEBREW_BUNDLE_MAS_SKIP="$HOMEBREW_BUNDLE_MAS_SKIP" @@ -506,17 +529,32 @@ run_brew_installs() { fi } -# Install Homebrew: https://docs.brew.sh/Installation -script_url="https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh" -NONINTERACTIVE=$STRAP_CI \ - /usr/bin/env bash -c "$(curl -fsSL $script_url)" || install_homebrew - -# Set up Homebrew on Linux: https://docs.brew.sh/Homebrew-on-Linux -[ "$LINUX" -gt 0 ] && run_dotfile_scripts scripts/linuxbrew.sh - -run_brew_installs || abort "Homebrew installs were not successful." +# Install Homebrew +# https://docs.brew.sh/Installation +# https://docs.brew.sh/Homebrew-on-Linux +# Homebrew installs require `sudo`, but not necessarily admin +# https://docs.brew.sh/FAQ#why-does-homebrew-say-sudo-is-bad +# https://github.com/Homebrew/install/issues/312 +# https://github.com/Homebrew/install/pull/315/files +if [ "$STRAP_SUDO" -eq 0 ]; then + # sudo_init || logskip "Skipping Homebrew installation (requires sudo)." + # WIP + sudo_init || abort "Skipping Homebrew installation (requires sudo)." +else + if [ "$MACOS" -gt 0 ]; then + script_url="https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh" + NONINTERACTIVE=$STRAP_CI \ + /usr/bin/env bash -c "$(curl -fsSL $script_url)" || install_homebrew + logk + elif [ "$LINUX" -gt 0 ]; then + # Set up Homebrew on Linux: https://docs.brew.sh/Homebrew-on-Linux + run_dotfile_scripts scripts/linuxbrew.sh + logk + fi + run_brew_installs || abort "Homebrew installs were not successful." +fi run_dotfile_scripts scripts/strap-after-setup.sh STRAP_SUCCESS=1 -log "Your system is now bootstrapped!" +log_no_sudo "Your system is now bootstrapped!"