Cómo solucionar el script de onboarding para Mac bloqueado por la actualización a Homebrew 6.0
29 de julio de 2026
0
Computing/SoftwareComments (0)
Log in to leave a comment
No posts yet
Log in to leave a comment
No posts yet
Llegas a la oficina por la mañana y te encuentras decenas de mensajes en Slack alertando de que el script de onboarding para los nuevos empleados se ha quedado bloqueado. Al abrir la terminal, ves que se ha quedado colgado indefinidamente esperando la entrada del usuario durante el proceso de brew install.
Con la llegada de Homebrew 6.0, la interfaz interactiva (Ask mode) y la política de bloqueo de la entrada estándar (stdin) se han reforzado. Cuando una persona ejecuta los comandos directamente no hay ningún problema, pero al ejecutarlo en segundo plano mediante un script de Shell, la terminal entra en un estado de interbloqueo (deadlock) de entrada/salida.
Si las dudas sobre la configuración del entorno por parte de tus compañeros están interrumpiendo tu propio flujo de trabajo, es momento de definir algunas variables de entorno y el control de excepciones directamente en el script.
Homebrew 6.0 genera esperas inesperadas de E/S al instalar paquetes cuando no hay una conexión TTY (terminal interactiva). Para bloquear estas esperas de la terminal y crear un entorno de ejecución completamente desatendido, debes declarar variables de entorno dedicadas en la parte superior del script.
Al añadir las siguientes variables al principio de tu script, se desactivarán todos los avisos interactivos y las sugerencias, a excepción de las solicitudes de permisos de administrador.
`bash
#!/usr/bin/env zsh
export NONINTERACTIVE=1
export HOMEBREW_NO_ENV_HINTS=1
export HOMEBREW_ACCEPT_OUTDATED_CAVEATS=1
export HOMEBREW_NO_AUTO_UPDATE=1
export HOMEBREW_NO_INSTALL_CLEANUP=1
if [[ -f "/opt/homebrew/bin/brew" ]]; then
eval "(/usr/local/bin/brew shellenv)"
else
/bin/bash -c "(/opt/homebrew/bin/brew shellenv)"
fi
safe_brew_install() {
local formula="{formula}" &>/dev/null; then
echo "Ya instalado: {formula}"; then
echo "Error detectado: fallo al instalar ${formula}" >&2
return 1
fi
fi
}
safe_brew_install "git"
safe_brew_install "jq"
`
Si en lugar del archivo .zshrc utilizas brew.env, que es el archivo de configuración integrado de Homebrew, debes omitir la palabra clave export y escribir solo pares clave-valor como HOMEBREW_NO_ENV_HINTS=1 para evitar errores de sintaxis.
A partir de la versión 6.0, se aplica por defecto el "Tap Trust Model" por razones de seguridad en la cadena de suministro. Esto bloquea la carga de Custom Taps externos no verificados o paquetes antiguos que utilicen MD5 o SHA-1.
Las Formula destinadas a la distribución de herramientas internas deben incluir obligatoriamente un digest SHA-256 y superar la inspección de brew audit --strict para evitar que el pipeline de CI/CD falle.
`ruby
class InternalApiCli < Formula
desc "사내 인프라 API 제어 및 배포 자동화 CLI 도구"
homepage "https://internal.company.net/docs/cli"
url "https://internal.company.net/downloads/cli/v2.4.0/internal-api-cli-2.4.0.tar.gz"
sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
license "Proprietary"
depends_on "jq"
def install
bin.install "internal-api-cli"
end
test do
assert_match "version 2.4.0", shell_output("#{bin}/internal-api-cli --version")
end
end
`
Define dentro del archivo de la Formula interna (internal-api-cli.rb) un identificador de licencia con estándar SPDX (license "Proprietary") junto con los campos exactos de url y desc. Es práctico hacer que el pipeline de CI/CD descargue el archivo, extraiga el valor con shasum -a 256 y lo actualice automáticamente con sed.
En los Mac locales de los desarrolladores, basta con ejecutar brew trust company/tools una vez para registrar el Tap interno como una fuente de confianza y permitir la instalación directa sin advertencias de seguridad.
Si la terminal de VS Code o un emulador de terminal antiguo se está ejecutando como binario de Intel (x86_64), la salida de uname -m mostrará x86_64 incluso si estás usando un Mac con chip de la serie M. Si instalas paquetes de Homebrew en este estado, se instalarán binarios x86 en /usr/local y se generará el error mach-o file, but is an incompatible architecture.
Es necesario añadir una condición que verifique si el entorno de la terminal se está ejecutando bajo Rosetta 2 y relance de inmediato el proceso de forma nativa en arm64.
`bash
#!/usr/bin/env zsh
SYSTEM_ARCH="(sysctl -n sysctl.proc_translated 2>/dev/null || echo "0")"
if [[ "{SYSTEM_ARCH}" == "x86_64" && "0" "{SYSTEM_ARCH}" == "x86_64" && "${IS_TRANSLATED}" == "0" ]]; then
HOMEBREW_PREFIX="/usr/local"
else
echo "Arquitectura no compatible: ${SYSTEM_ARCH}" >&2
exit 1
fi
eval "{HOMEBREW_PREFIX}/bin/brew shellenv)"
`
Si al consultar el parámetro del kernel sysctl -n sysctl.proc_translated el resultado es 1, significa que está en modo Rosetta 2. En ese momento, al ejecutar exec arch -arm64 /bin/zsh "$0" "$@", todo el script se transfiere a un shell arm64 y se instalan los binarios correctos en la ruta /opt/homebrew.
Si cada desarrollador tiene una versión distinta de Homebrew y diferentes paquetes instalados, se repetirá la típica situación de "en mi equipo sí funciona". Incluir en el script un Brewfile declarativo junto con brew bundle check permite que los nuevos integrantes completen la configuración con una sola línea de comando.
`bash
#!/usr/bin/env zsh
set -euo pipefail
export NONINTERACTIVE=1
export HOMEBREW_NO_ENV_HINTS=1
export HOMEBREW_BUNDLE_NO_UPGRADE=1
DOTFILES_REPO="https://github.com/company/dotfiles.git"
TARGET_DIR="$HOME/.dotfiles"
if ! command -v brew &>/dev/null; then
/bin/bash -c "(/opt/homebrew/bin/brew shellenv)"
fi
if [[ ! -d "{DOTFILES_REPO}" "{TARGET_DIR}" pull origin main
fi
BREWFILE_PATH="{BREWFILE_PATH}" &>/dev/null; then
echo "Todas las dependencias del Brewfile están actualizadas."
else
brew bundle install --file="${BREWFILE_PATH}"
fi
`
Tras sincronizar el repositorio de Dotfiles de la empresa en $HOME/.dotfiles, se comprueba primero con brew bundle check si falta algún paquete por instalar. Al hacer que brew bundle install se ejecute únicamente cuando falten paquetes, el entorno se mantendrá idéntico sin importar cuántas veces ejecutes el script.