Created
April 15, 2026 08:33
-
-
Save mrflory/da0c82c9ee3e84da4b4549a4a829cd38 to your computer and use it in GitHub Desktop.
Script to update all packages on macOS (brew, node.js via nvm, npm, python via uv, uv tools)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| confirm() { | |
| local prompt="$1" | |
| read -r -p "$prompt [y/N]: " answer | |
| case "$answer" in | |
| [Yy]|[Yy][Ee][Ss]) return 0 ;; | |
| *) return 1 ;; | |
| esac | |
| } | |
| run_step() { | |
| local title="$1" | |
| shift | |
| echo | |
| echo "==> $title" | |
| if confirm "Continue with: $title?"; then | |
| "$@" | |
| echo "Done: $title" | |
| else | |
| echo "Skipped: $title" | |
| fi | |
| } | |
| update_brew() { | |
| if ! command -v brew >/dev/null 2>&1; then | |
| echo "Homebrew not found, step will be skipped." | |
| return 0 | |
| fi | |
| echo "Currently installed Homebrew packages:" | |
| brew list --versions | |
| brew update | |
| local outdated | |
| outdated="$(brew outdated || true)" | |
| if [ -z "$outdated" ]; then | |
| echo "No outdated Homebrew packages found." | |
| return 0 | |
| fi | |
| echo "Outdated Homebrew packages:" | |
| echo "$outdated" | |
| if confirm "Upgrade the listed Homebrew packages now?"; then | |
| brew upgrade | |
| else | |
| echo "Homebrew upgrade skipped after showing the list." | |
| fi | |
| } | |
| load_nvm() { | |
| if command -v nvm >/dev/null 2>&1; then | |
| return 0 | |
| fi | |
| export NVM_DIR="${NVM_DIR:-$HOME/.nvm}" | |
| if [ -s "$NVM_DIR/nvm.sh" ]; then | |
| # shellcheck disable=SC1090 | |
| . "$NVM_DIR/nvm.sh" | |
| command -v nvm >/dev/null 2>&1 | |
| return $? | |
| fi | |
| return 1 | |
| } | |
| update_node_nvm() { | |
| if ! load_nvm; then | |
| echo "nvm not found, step will be skipped." | |
| return 0 | |
| fi | |
| echo "Currently installed Node versions:" | |
| nvm list | |
| local current | |
| local target_lts | |
| current="$(nvm current 2>/dev/null || true)" | |
| target_lts="$(nvm version-remote --lts 2>/dev/null || true)" | |
| if [ -n "$current" ] \ | |
| && [ "$current" != "none" ] \ | |
| && [ "$current" != "system" ] \ | |
| && [ -n "$target_lts" ] \ | |
| && [ "$target_lts" != "N/A" ] \ | |
| && [ "$current" != "$target_lts" ]; then | |
| nvm install --lts --reinstall-packages-from="$current" | |
| else | |
| nvm install --lts | |
| fi | |
| nvm alias default "lts/*" | |
| nvm use --lts >/dev/null | |
| } | |
| update_npm_global() { | |
| if ! command -v npm >/dev/null 2>&1; then | |
| echo "npm not found, step will be skipped." | |
| return 0 | |
| fi | |
| echo "Currently installed global npm packages:" | |
| npm list -g --depth=0 | |
| npm -g update | |
| } | |
| update_uv_python() { | |
| if ! command -v uv >/dev/null 2>&1; then | |
| echo "uv not found, step will be skipped." | |
| return 0 | |
| fi | |
| echo "Currently installed Python versions via uv:" | |
| uv python list | |
| if uv python upgrade --help >/dev/null 2>&1; then | |
| uv python upgrade | |
| else | |
| echo "uv does not support 'uv python upgrade', step will be skipped." | |
| fi | |
| } | |
| update_uv_global() { | |
| if ! command -v uv >/dev/null 2>&1; then | |
| echo "uv not found, step will be skipped." | |
| return 0 | |
| fi | |
| echo "Currently installed global uv tools:" | |
| uv tool list | |
| uv tool upgrade --all | |
| } | |
| echo "Interactive update script started." | |
| run_step "Update Homebrew packages" update_brew | |
| run_step "Update Node.js (nvm, LTS)" update_node_nvm | |
| run_step "Update global npm packages" update_npm_global | |
| run_step "Update Python via uv" update_uv_python | |
| run_step "Update global uv tools" update_uv_global | |
| echo | |
| echo "All steps completed." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment