Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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 &&
Expand Down
117 changes: 44 additions & 73 deletions cli/bash/commands/basectl/subcommands/setup_macos_homebrew.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
}
Expand Down Expand Up @@ -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)"
Expand All @@ -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 <verified Homebrew installer from $installer_url>"
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 <Homebrew installer from $installer_url>"
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)"
}

Expand Down
2 changes: 2 additions & 0 deletions cli/bash/commands/basectl/tests/setup-common.bats
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
31 changes: 31 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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 &&
Expand Down
125 changes: 125 additions & 0 deletions lib/base/homebrew_install.sh
Original file line number Diff line number Diff line change
@@ -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 <verified Homebrew installer from $installer_url>"
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 <Homebrew installer from $installer_url>"
base_homebrew_set_dry_run_result "$result_var"
return 0
fi

"$mutable_runner_fn" "$installer_url" "$fatal_fn"
}
Loading