|
| 1 | +#!/usr/bin/env bash |
| 2 | +# Install Node (via nvm + Node.js 24 when Node is missing), enable Corepack, |
| 3 | +# install GitHub CLI when missing, and install @patternfly/patternfly-cli globally. |
| 4 | + |
| 5 | +set -euo pipefail |
| 6 | + |
| 7 | +if [ -z "${HOME:-}" ]; then |
| 8 | + printf '\nERROR: HOME is not set. Set it to your home directory and re-run this script.\n\n' >&2 |
| 9 | + exit 1 |
| 10 | +fi |
| 11 | + |
| 12 | +NVM_VERSION="${NVM_VERSION:-v0.40.3}" |
| 13 | + |
| 14 | +error() { |
| 15 | + printf '\n[%s] ERROR: %s\n\n' "$(date -u +'%Y-%m-%dT%H:%M:%SZ')" "$*" >&2 |
| 16 | + exit 1 |
| 17 | +} |
| 18 | + |
| 19 | +info() { |
| 20 | + printf '[install] %s\n' "$*" |
| 21 | +} |
| 22 | + |
| 23 | +warn() { |
| 24 | + printf '[install] WARNING: %s\n' "$*" >&2 |
| 25 | +} |
| 26 | + |
| 27 | +require_cmd() { |
| 28 | + command -v "$1" >/dev/null 2>&1 |
| 29 | +} |
| 30 | + |
| 31 | +# Run a command with elevation only when needed (non-root). Root can omit sudo. |
| 32 | +run_as_root() { |
| 33 | + if [ "$(id -u)" -eq 0 ]; then |
| 34 | + "$@" |
| 35 | + else |
| 36 | + require_cmd sudo || error "sudo is required to install system packages (install sudo or run this script as root)." |
| 37 | + sudo "$@" |
| 38 | + fi |
| 39 | +} |
| 40 | + |
| 41 | +ensure_nvm_loaded() { |
| 42 | + export NVM_DIR="${NVM_DIR:-$HOME/.nvm}" |
| 43 | + if [ -s "$NVM_DIR/nvm.sh" ]; then |
| 44 | + # shellcheck source=/dev/null |
| 45 | + . "$NVM_DIR/nvm.sh" |
| 46 | + return 0 |
| 47 | + fi |
| 48 | + return 1 |
| 49 | +} |
| 50 | + |
| 51 | +install_node_via_nvm() { |
| 52 | + info "Node.js not found. Installing nvm (${NVM_VERSION}) and Node.js 24." |
| 53 | + if ! require_cmd curl && ! require_cmd wget; then |
| 54 | + error "Need curl or wget to install nvm. Install one of them and re-run this script." |
| 55 | + fi |
| 56 | + |
| 57 | + if [ ! -d "$HOME/.nvm" ]; then |
| 58 | + local install_url="https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh" |
| 59 | + if require_cmd curl; then |
| 60 | + curl -fsSL "$install_url" | bash || error "Failed to install nvm." |
| 61 | + else |
| 62 | + wget -qO- "$install_url" | bash || error "Failed to install nvm." |
| 63 | + fi |
| 64 | + else |
| 65 | + info "nvm is already present at ${HOME}/.nvm" |
| 66 | + fi |
| 67 | + |
| 68 | + ensure_nvm_loaded || error "nvm was installed but nvm.sh could not be loaded from ${NVM_DIR}/nvm.sh." |
| 69 | + |
| 70 | + nvm install 24 || error "nvm failed to install Node.js 24." |
| 71 | + nvm use 24 || error "nvm failed to activate Node.js 24." |
| 72 | + nvm alias default 24 2>/dev/null || true |
| 73 | + |
| 74 | + info "Node.js $(node --version) and npm $(npm --version) are ready (npm ships with this Node release)." |
| 75 | +} |
| 76 | + |
| 77 | +ensure_node() { |
| 78 | + if require_cmd node && require_cmd npm && require_cmd corepack; then |
| 79 | + info "Node.js is already installed: $(command -v node) ($(node --version)), npm $(npm --version)" |
| 80 | + return 0 |
| 81 | + fi |
| 82 | + if require_cmd node; then |
| 83 | + error "Node.js is on PATH but this installer also requires npm and Corepack (corepack). Install a full Node.js toolchain, then re-run." |
| 84 | + fi |
| 85 | + install_node_via_nvm |
| 86 | +} |
| 87 | + |
| 88 | +ensure_nvm_in_path_for_npm_globals() { |
| 89 | + # If node came from nvm but this shell never sourced nvm, try to load it. |
| 90 | + if ! require_cmd node; then |
| 91 | + ensure_nvm_loaded && nvm use default >/dev/null 2>&1 || true |
| 92 | + fi |
| 93 | + if require_cmd node; then |
| 94 | + return 0 |
| 95 | + fi |
| 96 | + error "Node.js is not available in PATH after setup." |
| 97 | +} |
| 98 | + |
| 99 | +install_gh_macos() { |
| 100 | + if require_cmd brew; then |
| 101 | + info "Installing GitHub CLI with Homebrew." |
| 102 | + brew install gh || error "Homebrew failed to install gh. See messages above." |
| 103 | + return 0 |
| 104 | + fi |
| 105 | + error "GitHub CLI is not installed and Homebrew was not found. Install Homebrew from https://brew.sh then re-run, or install gh manually from https://cli.github.com/." |
| 106 | +} |
| 107 | + |
| 108 | +install_gh_linux_apt() { |
| 109 | + info "Installing GitHub CLI with apt (Debian/Ubuntu)." |
| 110 | + run_as_root apt-get update -y || error "apt-get update failed." |
| 111 | + if ! require_cmd curl; then |
| 112 | + run_as_root apt-get install -y curl || error "Failed to install curl (needed for GitHub CLI apt setup)." |
| 113 | + fi |
| 114 | + run_as_root install -d -m 755 /etc/apt/keyrings |
| 115 | + curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | |
| 116 | + run_as_root tee /etc/apt/keyrings/githubcli-archive-keyring.gpg >/dev/null || error "Failed to add GitHub CLI apt key." |
| 117 | + run_as_root chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg |
| 118 | + echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | |
| 119 | + run_as_root tee /etc/apt/sources.list.d/github-cli.list >/dev/null || error "Failed to add GitHub CLI apt source." |
| 120 | + run_as_root apt-get update -y || error "apt-get update failed after adding GitHub CLI source." |
| 121 | + run_as_root apt-get install -y gh || error "apt failed to install gh." |
| 122 | +} |
| 123 | + |
| 124 | +install_gh_linux_dnf() { |
| 125 | + info "Installing GitHub CLI with dnf (Fedora/RHEL-compatible)." |
| 126 | + run_as_root dnf install -y 'dnf-command(config-manager)' || warn "dnf-command(config-manager) may already be installed; continuing." |
| 127 | + run_as_root dnf config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo || error "Failed to add gh dnf repository." |
| 128 | + run_as_root dnf install -y gh || error "dnf failed to install gh." |
| 129 | +} |
| 130 | + |
| 131 | +install_gh_linux_yum() { |
| 132 | + info "Installing GitHub CLI with yum (older RHEL/CentOS)." |
| 133 | + run_as_root yum install -y yum-utils || error "yum-utils installation failed." |
| 134 | + run_as_root yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo || error "Failed to add gh yum repository." |
| 135 | + run_as_root yum install -y gh || error "yum failed to install gh." |
| 136 | +} |
| 137 | + |
| 138 | +install_gh_linux_pacman() { |
| 139 | + info "Installing GitHub CLI with pacman (Arch)." |
| 140 | + run_as_root pacman -Syu --noconfirm github-cli || error "pacman failed to install github-cli." |
| 141 | +} |
| 142 | + |
| 143 | +install_gh_linux_zypper() { |
| 144 | + info "Installing GitHub CLI with zypper (openSUSE)." |
| 145 | + run_as_root zypper refresh |
| 146 | + run_as_root zypper install -y gh || error "zypper failed to install gh." |
| 147 | +} |
| 148 | + |
| 149 | +install_gh_linux_apk() { |
| 150 | + info "Installing GitHub CLI with apk (Alpine)." |
| 151 | + run_as_root apk add --no-cache github-cli || error "apk failed to install github-cli." |
| 152 | +} |
| 153 | + |
| 154 | +install_gh_linux() { |
| 155 | + if [ ! -r /etc/os-release ]; then |
| 156 | + error "Cannot read /etc/os-release. Install gh manually: https://cli.github.com/manual/installation" |
| 157 | + fi |
| 158 | + # shellcheck source=/dev/null |
| 159 | + . /etc/os-release |
| 160 | + local id_lc |
| 161 | + id_lc="$(printf '%s' "${ID:-unknown}" | tr '[:upper:]' '[:lower:]')" |
| 162 | + |
| 163 | + case "$id_lc" in |
| 164 | + ubuntu | debian | linuxmint | pop | elementary | zorin | kali) |
| 165 | + install_gh_linux_apt |
| 166 | + ;; |
| 167 | + fedora | nobara | ultramarine) |
| 168 | + install_gh_linux_dnf |
| 169 | + ;; |
| 170 | + rhel | centos | rocky | almalinux) |
| 171 | + if require_cmd dnf; then |
| 172 | + install_gh_linux_dnf |
| 173 | + else |
| 174 | + install_gh_linux_yum |
| 175 | + fi |
| 176 | + ;; |
| 177 | + arch | manjaro | endeavouros) |
| 178 | + install_gh_linux_pacman |
| 179 | + ;; |
| 180 | + opensuse-tumbleweed | opensuse-leap | sled | sles) |
| 181 | + install_gh_linux_zypper |
| 182 | + ;; |
| 183 | + alpine) |
| 184 | + install_gh_linux_apk |
| 185 | + ;; |
| 186 | + *) |
| 187 | + if printf '%s' "${ID_LIKE:-}" | tr '[:upper:]' '[:lower:]' | grep -qE '(debian|ubuntu)'; then |
| 188 | + install_gh_linux_apt |
| 189 | + elif printf '%s' "${ID_LIKE:-}" | tr '[:upper:]' '[:lower:]' | grep -q 'fedora'; then |
| 190 | + install_gh_linux_dnf |
| 191 | + elif printf '%s' "${ID_LIKE:-}" | tr '[:upper:]' '[:lower:]' | grep -q 'rhel\|centos'; then |
| 192 | + if require_cmd dnf; then |
| 193 | + install_gh_linux_dnf |
| 194 | + else |
| 195 | + install_gh_linux_yum |
| 196 | + fi |
| 197 | + else |
| 198 | + error "Unsupported Linux distribution: ${ID:-unknown}. Install gh manually from https://cli.github.com/manual/installation" |
| 199 | + fi |
| 200 | + ;; |
| 201 | + esac |
| 202 | +} |
| 203 | + |
| 204 | +ensure_gh() { |
| 205 | + if require_cmd gh; then |
| 206 | + info "GitHub CLI is already installed: $(command -v gh) ($(gh --version 2>/dev/null | head -n1 || echo 'version unknown'))" |
| 207 | + return 0 |
| 208 | + fi |
| 209 | + |
| 210 | + case "$(uname -s)" in |
| 211 | + Darwin) |
| 212 | + install_gh_macos |
| 213 | + ;; |
| 214 | + Linux) |
| 215 | + install_gh_linux |
| 216 | + ;; |
| 217 | + *) |
| 218 | + error "Unsupported OS: $(uname -s). Install gh manually from https://cli.github.com/." |
| 219 | + ;; |
| 220 | + esac |
| 221 | +} |
| 222 | + |
| 223 | +enable_corepack_step() { |
| 224 | + info "Enabling Corepack." |
| 225 | + corepack enable || error "corepack enable failed. Ensure Node.js is recent enough (16.9+) and try again." |
| 226 | +} |
| 227 | + |
| 228 | +install_patternfly_cli() { |
| 229 | + info "Installing @patternfly/patternfly-cli globally from npm." |
| 230 | + npm install -g @patternfly/patternfly-cli || error "npm failed to install @patternfly/patternfly-cli globally. Check permissions and your network." |
| 231 | +} |
| 232 | + |
| 233 | +main() { |
| 234 | + info "Starting PatternFly CLI environment setup." |
| 235 | + ensure_node |
| 236 | + ensure_nvm_in_path_for_npm_globals |
| 237 | + enable_corepack_step |
| 238 | + ensure_gh |
| 239 | + install_patternfly_cli |
| 240 | + |
| 241 | + printf '\n' |
| 242 | + printf 'SUCCESS: PatternFly CLI is installed.\n' |
| 243 | + printf '\n' |
| 244 | + printf 'Run the CLI with:\n' |
| 245 | + printf ' patternfly-cli --help\n' |
| 246 | + printf '\n' |
| 247 | + printf 'If you just installed nvm, open a new terminal or run:\n' |
| 248 | + printf ' export NVM_DIR="%s/.nvm" && [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"\n' "${HOME}" |
| 249 | + printf '\n' |
| 250 | +} |
| 251 | + |
| 252 | +main "$@" |
0 commit comments