From 732f6ca10d3980547a956171480e945b74f63804 Mon Sep 17 00:00:00 2001 From: Ramesh Padmanabhaiah <22363102+codeforester@users.noreply.github.com> Date: Wed, 19 Aug 2026 17:25:17 +0530 Subject: [PATCH] refactor: share Homebrew install policy --- bootstrap.sh | 32 +++++ .../subcommands/setup_macos_homebrew.sh | 117 ++++++---------- .../commands/basectl/tests/setup-common.bats | 2 + install.sh | 31 +++++ lib/base/homebrew_install.sh | 125 ++++++++++++++++++ 5 files changed, 234 insertions(+), 73 deletions(-) create mode 100644 lib/base/homebrew_install.sh diff --git a/bootstrap.sh b/bootstrap.sh index 71691ab2..71e886e8 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -4,6 +4,12 @@ BASE_DEFAULT_HOMEBREW_INSTALLER_URL="https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh" +bootstrap_script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" +if [[ -f "$bootstrap_script_dir/lib/base/homebrew_install.sh" ]]; then + # shellcheck source=/dev/null + source "$bootstrap_script_dir/lib/base/homebrew_install.sh" +fi + bootstrap_usage() { cat <<'EOF' Usage: @@ -343,9 +349,35 @@ bootstrap_install_homebrew() { local installer local installer_url local installer_sha256 + local pinned_selected=false + local pinned_url_selected=false + local pinned_sha256_selected=false installer_url="$(bootstrap_homebrew_installer_url)" installer_sha256="$(bootstrap_homebrew_installer_sha256)" + + if declare -F base_homebrew_install >/dev/null 2>&1; then + bootstrap_homebrew_pinned_selected && pinned_selected=true + bootstrap_homebrew_pinned_url_selected && pinned_url_selected=true + bootstrap_homebrew_pinned_sha256_selected && pinned_sha256_selected=true + base_homebrew_install \ + "$installer_url" \ + "$installer_sha256" \ + "${BASE_BOOTSTRAP_DRY_RUN:-false}" \ + "$pinned_selected" \ + "$pinned_url_selected" \ + "$pinned_sha256_selected" \ + bootstrap_log \ + bootstrap_die \ + bootstrap_log_homebrew_mutable_policy \ + bootstrap_fetch_homebrew_installer \ + base_homebrew_run_mutable_installer \ + "$result_var" + return $? + fi + + # A raw bootstrap.sh download has no adjacent Base checkout to source. + # Keep this standalone fallback for that first-mile invocation. bootstrap_log "Installing Homebrew." if bootstrap_homebrew_pinned_selected; then bootstrap_homebrew_pinned_url_selected && diff --git a/cli/bash/commands/basectl/subcommands/setup_macos_homebrew.sh b/cli/bash/commands/basectl/subcommands/setup_macos_homebrew.sh index 42074c7b..1ecde587 100644 --- a/cli/bash/commands/basectl/subcommands/setup_macos_homebrew.sh +++ b/cli/bash/commands/basectl/subcommands/setup_macos_homebrew.sh @@ -14,6 +14,9 @@ _base_setup_macos_homebrew_sourced=1 readonly _base_setup_macos_homebrew_sourced +# shellcheck source=/dev/null +source "$BASE_HOME/lib/base/homebrew_install.sh" + setup_python_formula() { printf '%s\n' "${BASE_SETUP_PYTHON_FORMULA:-python@3.13}" } @@ -211,46 +214,39 @@ setup_fetch_homebrew_installer() { esac } -setup_run_verified_homebrew_installer() { +setup_homebrew_install_fatal() { + base_std_fatal_error "$1" +} + +setup_homebrew_mutable_fatal() { + base_std_log_error "$(setup_recovery_homebrew)" + base_std_fatal_error "$1" +} + +setup_run_mutable_homebrew_installer() { local installer_url="$1" - local expected_sha256="$2" - local installer_file - local checksum - local actual_sha256 local exit_code - base_std_make_temp_file installer_file base-homebrew-installer || base_std_fatal_error "Failed to create a temporary Homebrew installer file." - setup_fetch_homebrew_installer "$installer_url" "$installer_file" || { - base_std_fatal_error "Failed to read pinned Homebrew installer content from '$installer_url'." - } - - command -v shasum >/dev/null 2>&1 || { - base_std_fatal_error "shasum is required to verify pinned Homebrew installer content." - } - checksum="$(shasum -a 256 "$installer_file")" || { - base_std_fatal_error "Failed to compute Homebrew installer checksum." - } - actual_sha256="${checksum%% *}" - if [[ "$actual_sha256" != "$expected_sha256" ]]; then - base_std_fatal_error "Homebrew installer checksum mismatch (expected $expected_sha256, got $actual_sha256)." + if [[ -n "${BASE_SETUP_HOMEBREW_INSTALLER_SCRIPT:-}" ]]; then + setup_reject_test_hook_if_disallowed BASE_SETUP_HOMEBREW_INSTALLER_SCRIPT + "$BASE_SETUP_HOMEBREW_INSTALLER_SCRIPT" + exit_code=$? + if ((exit_code)); then + base_std_log_error "$(setup_recovery_homebrew)" + fi + base_std_exit_if_error "$exit_code" "Homebrew installation failed." + return 0 fi - /bin/bash "$installer_file" - exit_code=$? - if ((exit_code)); then - base_std_log_error "$(setup_recovery_homebrew)" - fi - base_std_exit_if_error "$exit_code" "Homebrew installer failed." + base_homebrew_run_mutable_installer "$installer_url" setup_homebrew_mutable_fatal } setup_install_homebrew() { - # Trust decision: Base follows Homebrew's official install command, which - # intentionally fetches the installer from the mutable HEAD ref. Pinning a - # reviewed commit would reduce mutability risk, but would also make Base own - # installer refreshes and drift from Homebrew's supported bootstrap path. local installer_url local installer_sha256 - local exit_code + local pinned_selected=false + local pinned_url_selected=false + local pinned_sha256_selected=false installer_url="$(setup_homebrew_installer_url)" installer_sha256="$(setup_homebrew_installer_sha256)" @@ -261,49 +257,24 @@ setup_install_homebrew() { return 0 fi - if setup_homebrew_pinned_selected; then - setup_homebrew_pinned_url_selected && - setup_homebrew_pinned_sha256_selected && - [[ -n "$installer_url" && -n "$installer_sha256" ]] || - base_std_fatal_error "Pinned Homebrew installer URL and SHA-256 are both required." - base_std_log_info "Installing Homebrew." - base_std_log_info "Using pinned Homebrew installer from $installer_url." - if setup_is_dry_run; then - base_std_log_info "[DRY-RUN] Would verify Homebrew installer SHA-256 $installer_sha256" - base_std_log_info "[DRY-RUN] Would run: /bin/bash " - return 0 - fi - setup_run_verified_homebrew_installer "$installer_url" "$installer_sha256" - setup_refresh_brew_path || base_std_fatal_error "Homebrew installation finished, but 'brew' was not found on PATH. $(setup_recovery_brew_path)" - return 0 - fi - - setup_log_homebrew_mutable_policy - if setup_is_dry_run; then - base_std_log_info "[DRY-RUN] Would run: /bin/bash -c " - return 0 - fi - - base_std_log_info "Installing Homebrew." - - if [[ -n "${BASE_SETUP_HOMEBREW_INSTALLER_SCRIPT:-}" ]]; then - setup_reject_test_hook_if_disallowed BASE_SETUP_HOMEBREW_INSTALLER_SCRIPT - "$BASE_SETUP_HOMEBREW_INSTALLER_SCRIPT" - exit_code=$? - if ((exit_code)); then - base_std_log_error "$(setup_recovery_homebrew)" - fi - base_std_exit_if_error "$exit_code" "Homebrew installation failed." - else - command -v curl >/dev/null 2>&1 || base_std_fatal_error "curl is required to install Homebrew. Install curl or install Homebrew manually from https://brew.sh/, then rerun 'basectl setup'." - /bin/bash -c "$(curl -fsSL "$installer_url")" - exit_code=$? - if ((exit_code)); then - base_std_log_error "$(setup_recovery_homebrew)" - fi - base_std_exit_if_error "$exit_code" "Homebrew installation failed." - fi - + setup_homebrew_pinned_selected && pinned_selected=true + setup_homebrew_pinned_url_selected && pinned_url_selected=true + setup_homebrew_pinned_sha256_selected && pinned_sha256_selected=true + base_homebrew_install \ + "$installer_url" \ + "$installer_sha256" \ + "$(setup_is_dry_run && printf true || printf false)" \ + "$pinned_selected" \ + "$pinned_url_selected" \ + "$pinned_sha256_selected" \ + base_std_log_info \ + setup_homebrew_install_fatal \ + setup_log_homebrew_mutable_policy \ + setup_fetch_homebrew_installer \ + setup_run_mutable_homebrew_installer + local install_status=$? + ((install_status == 0)) || return "$install_status" + setup_is_dry_run && return 0 setup_refresh_brew_path || base_std_fatal_error "Homebrew installation finished, but 'brew' was not found on PATH. $(setup_recovery_brew_path)" } diff --git a/cli/bash/commands/basectl/tests/setup-common.bats b/cli/bash/commands/basectl/tests/setup-common.bats index 3581be30..4d479f36 100644 --- a/cli/bash/commands/basectl/tests/setup-common.bats +++ b/cli/bash/commands/basectl/tests/setup-common.bats @@ -140,6 +140,8 @@ run_setup_common_script() { source "$BASE_HOME/cli/bash/commands/basectl/subcommands/setup_macos_homebrew.sh" source "$BASE_HOME/cli/bash/commands/basectl/subcommands/setup_macos_homebrew.sh" for helper in \ + base_homebrew_install \ + base_homebrew_run_verified_installer \ setup_find_brew_bin \ setup_install_homebrew \ setup_collect_macos_base_check_results \ diff --git a/install.sh b/install.sh index 19f81913..c5230b31 100755 --- a/install.sh +++ b/install.sh @@ -4,6 +4,12 @@ BASE_DEFAULT_HOMEBREW_INSTALLER_URL="https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh" +install_script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" +if [[ -f "$install_script_dir/lib/base/homebrew_install.sh" ]]; then + # shellcheck source=/dev/null + source "$install_script_dir/lib/base/homebrew_install.sh" +fi + install_usage() { cat <<'EOF' Usage: @@ -218,9 +224,34 @@ install_homebrew() { local installer local installer_url local installer_sha256 + local pinned_selected=false + local pinned_url_selected=false + local pinned_sha256_selected=false installer_url="$(install_homebrew_installer_url)" installer_sha256="$(install_homebrew_installer_sha256)" + + if declare -F base_homebrew_install >/dev/null 2>&1; then + install_homebrew_pinned_selected && pinned_selected=true + install_homebrew_pinned_url_selected && pinned_url_selected=true + install_homebrew_pinned_sha256_selected && pinned_sha256_selected=true + base_homebrew_install \ + "$installer_url" \ + "$installer_sha256" \ + "${BASE_INSTALL_DRY_RUN:-false}" \ + "$pinned_selected" \ + "$pinned_url_selected" \ + "$pinned_sha256_selected" \ + install_log \ + install_die \ + install_log_homebrew_mutable_policy \ + install_fetch_homebrew_installer \ + base_homebrew_run_mutable_installer + return $? + fi + + # A raw install.sh download has no adjacent Base checkout to source. Keep + # this standalone fallback for that first-mile invocation. install_log "Installing Homebrew." if install_homebrew_pinned_selected; then install_homebrew_pinned_url_selected && diff --git a/lib/base/homebrew_install.sh b/lib/base/homebrew_install.sh new file mode 100644 index 00000000..40d9e955 --- /dev/null +++ b/lib/base/homebrew_install.sh @@ -0,0 +1,125 @@ +#!/usr/bin/env bash + +# Shared Homebrew installer policy and execution helpers. +# +# First-mile callers may source this file when the Base checkout is available. +# bootstrap.sh and install.sh retain a standalone fallback for the case where +# the script was downloaded before the repository exists locally. + +[[ -n "${_base_homebrew_install_sourced:-}" ]] && return 0 +_base_homebrew_install_sourced=1 +readonly _base_homebrew_install_sourced + +base_homebrew_run_verified_installer() { + local installer_url="$1" + local expected_sha256="$2" + local fetch_fn="$3" + local fatal_fn="$4" + local installer_file + local checksum + local actual_sha256 + local exit_code + + installer_file="$(mktemp "${TMPDIR:-/tmp}/base-homebrew-installer.XXXXXX")" || { + "$fatal_fn" "Failed to create a temporary Homebrew installer file." + return 1 + } + "$fetch_fn" "$installer_url" "$installer_file" || { + rm -f "$installer_file" + "$fatal_fn" "Failed to read pinned Homebrew installer content from '$installer_url'." + return 1 + } + + command -v shasum >/dev/null 2>&1 || { + rm -f "$installer_file" + "$fatal_fn" "shasum is required to verify pinned Homebrew installer content." + return 1 + } + checksum="$(shasum -a 256 "$installer_file")" || { + rm -f "$installer_file" + "$fatal_fn" "Failed to compute Homebrew installer checksum." + return 1 + } + actual_sha256="${checksum%% *}" + if [[ "$actual_sha256" != "$expected_sha256" ]]; then + rm -f "$installer_file" + "$fatal_fn" "Homebrew installer checksum mismatch (expected $expected_sha256, got $actual_sha256)." + return 1 + fi + + /bin/bash "$installer_file" + exit_code=$? + rm -f "$installer_file" + if ((exit_code)); then + "$fatal_fn" "Homebrew installer failed." + return 1 + fi +} + +base_homebrew_run_mutable_installer() { + local installer_url="$1" + local fatal_fn="$2" + local installer + + command -v curl >/dev/null 2>&1 || { + "$fatal_fn" "curl is required to install Homebrew." + return 1 + } + installer="$(curl -fsSL "$installer_url")" || { + "$fatal_fn" "Failed to download the Homebrew installer." + return 1 + } + /bin/bash -c "$installer" || { + "$fatal_fn" "Homebrew installer failed." + return 1 + } +} + +base_homebrew_set_dry_run_result() { + local result_var="$1" + + [[ -n "$result_var" ]] || return 0 + printf -v "$result_var" '%s' brew +} + +base_homebrew_install() { + local installer_url="$1" + local installer_sha256="$2" + local dry_run="$3" + local pinned_selected="$4" + local pinned_url_selected="$5" + local pinned_sha256_selected="$6" + local log_fn="$7" + local fatal_fn="$8" + local mutable_policy_fn="$9" + local fetch_fn="${10}" + local mutable_runner_fn="${11}" + local result_var="${12:-}" + + "$log_fn" "Installing Homebrew." + if [[ "$pinned_selected" == true ]]; then + [[ "$pinned_url_selected" == true && "$pinned_sha256_selected" == true && + -n "$installer_url" && -n "$installer_sha256" ]] || { + "$fatal_fn" "Pinned Homebrew installer URL and SHA-256 are both required." + return 1 + } + "$log_fn" "Using pinned Homebrew installer from $installer_url." + if [[ "$dry_run" == true ]]; then + "$log_fn" "[DRY-RUN] Would verify Homebrew installer SHA-256 $installer_sha256" + "$log_fn" "[DRY-RUN] Would run: /bin/bash " + base_homebrew_set_dry_run_result "$result_var" + return 0 + fi + base_homebrew_run_verified_installer "$installer_url" "$installer_sha256" "$fetch_fn" "$fatal_fn" + return $? + fi + + "$mutable_policy_fn" + if [[ "$dry_run" == true ]]; then + "$log_fn" "[DRY-RUN] Would run: /bin/bash -c " + base_homebrew_set_dry_run_result "$result_var" + return 0 + fi + + "$mutable_runner_fn" "$installer_url" "$fatal_fn" +}