Остання активність 3 weeks ago

Interactive developer environment bootstrapper using official upstream downloads and signed OS-vendor packages.

weehong ревизій цього gist 3 months ago. До ревизії

1 file changed, 13 insertions, 7 deletions

menu.sh

@@ -5,13 +5,19 @@
5 5 # =======================================================
6 6 if [ -z "${_PREFER_ZSH_BOOTSTRAPPED:-}" ]; then
7 7 export _PREFER_ZSH_BOOTSTRAPPED=1
8 - if command -v zsh >/dev/null 2>&1; then
9 - exec zsh "$0" "$@"
10 - elif command -v bash >/dev/null 2>&1; then
11 - exec bash "$0" "$@"
12 - else
13 - echo "Error: Neither Zsh nor Bash is installed. Exiting."
14 - exit 1
8 +
9 + # Only attempt to re-execute if $0 is an actual file on disk.
10 + # This prevents the 'can't open input file' error when running
11 + # from memory via `bash -c "$(curl ...)"` or `zsh -c`.
12 + if [ -f "$0" ]; then
13 + if command -v zsh >/dev/null 2>&1; then
14 + exec zsh "$0" "$@"
15 + elif command -v bash >/dev/null 2>&1; then
16 + exec bash "$0" "$@"
17 + else
18 + echo "Error: Neither Zsh nor Bash is installed. Exiting."
19 + exit 1
20 + fi
15 21 fi
16 22 fi
17 23

weehong ревизій цього gist 3 months ago. До ревизії

1 file changed, 117 insertions, 90 deletions

menu.sh

@@ -1,39 +1,72 @@
1 1 #!/usr/bin/env bash
2 +
3 + # =======================================================
4 + # 1. BOOTSTRAPPER: PREFER ZSH, FALLBACK TO BASH
5 + # =======================================================
6 + if [ -z "${_PREFER_ZSH_BOOTSTRAPPED:-}" ]; then
7 + export _PREFER_ZSH_BOOTSTRAPPED=1
8 + if command -v zsh >/dev/null 2>&1; then
9 + exec zsh "$0" "$@"
10 + elif command -v bash >/dev/null 2>&1; then
11 + exec bash "$0" "$@"
12 + else
13 + echo "Error: Neither Zsh nor Bash is installed. Exiting."
14 + exit 1
15 + fi
16 + fi
17 +
2 18 set -u
3 19
4 - # =============================
20 + # =======================================================
21 + # 2. CROSS-SHELL NORMALIZATION
22 + # =======================================================
23 + if [ -n "${ZSH_VERSION:-}" ]; then
24 + # Zsh: Enable Bash-like word splitting for unquoted variables (menu input)
25 + setopt shwordsplit 2>/dev/null || true
26 + CURRENT_SHELL="zsh"
27 + PROFILE_FILE="$HOME/.zshrc"
28 + elif [ -n "${BASH_VERSION:-}" ]; then
29 + # Bash
30 + CURRENT_SHELL="bash"
31 + PROFILE_FILE="$HOME/.bashrc"
32 + else
33 + # Fallback POSIX
34 + CURRENT_SHELL="sh"
35 + PROFILE_FILE="$HOME/.profile"
36 + fi
37 +
38 + # =======================================================
5 39 # COLORS & LOGGING
6 - # =============================
40 + # =======================================================
7 41 GREEN="\033[0;32m"
8 42 RED="\033[0;31m"
9 43 YELLOW="\033[1;33m"
10 44 BLUE="\033[0;34m"
11 45 NC="\033[0m"
12 46
13 - log() { echo -e "${GREEN}▶ $*${NC}"; }
14 - warn() { echo -e "${YELLOW}⚠ $*${NC}"; }
15 - err() { echo -e "${RED}✖ $*${NC}"; }
16 - info() { echo -e "${BLUE}ℹ $*${NC}"; }
47 + log() { printf "${GREEN}▶ %s${NC}\n" "$*"; }
48 + warn() { printf "${YELLOW}⚠ %s${NC}\n" "$*"; }
49 + err() { printf "${RED}✖ %s${NC}\n" "$*"; }
50 + info() { printf "${BLUE}ℹ %s${NC}\n" "$*"; }
17 51
18 - # =============================
52 + # =======================================================
19 53 # HELPERS & SYSTEM DETECTION
20 - # =============================
54 + # =======================================================
21 55 require_cmd() { command -v "$1" >/dev/null 2>&1; }
22 56
23 57 add_to_path_config() {
24 58 local label=$1
25 59 local path_line=$2
26 - local target_file="${3:-$HOME/.pathrc}"
60 + local target_file="${3:-$PROFILE_FILE}"
27 61
28 62 if [[ -f "$target_file" ]]; then
29 63 if ! grep -q "$label" "$target_file"; then
30 - echo -e "\n# $label\n$path_line" >> "$target_file"
64 + printf "\n# %s\n%s\n" "$label" "$path_line" >> "$target_file"
31 65 log "Added $label to $target_file"
32 66 fi
33 67 else
34 - echo -e "\n# $label\n$path_line" >> "$HOME/.bashrc"
35 - [[ -f "$HOME/.zshrc" ]] && echo -e "\n# $label\n$path_line" >> "$HOME/.zshrc"
36 - log "Added $label to shell profiles."
68 + printf "\n# %s\n%s\n" "$label" "$path_line" >> "$PROFILE_FILE"
69 + log "Added $label to shell profile ($PROFILE_FILE)."
37 70 fi
38 71 }
39 72
@@ -59,14 +92,14 @@ detect_os_arch() {
59 92 OS="Unknown"
60 93 OS_LOWER="unknown"
61 94 fi
62 - log "Detected: $OS ($ARCH)"
95 + log "Detected: $OS ($ARCH) running $CURRENT_SHELL"
63 96 }
64 97
65 98 detect_os_arch
66 99
67 - # =============================
100 + # =======================================================
68 101 # CORE RUNTIMES & MANAGERS
69 - # =============================
102 + # =======================================================
70 103
71 104 install_build_tools() {
72 105 log "Installing Build Essentials & Core Dependencies..."
@@ -80,6 +113,8 @@ install_build_tools() {
80 113 install_brew() {
81 114 if require_cmd brew; then warn "Homebrew already installed"; return; fi
82 115 log "Installing Homebrew from Official Source..."
116 +
117 + # Homebrew's installer specifically requires Bash execution, regardless of current shell
83 118 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
84 119
85 120 if [[ "$OS_LOWER" == "linux" ]]; then
@@ -97,45 +132,31 @@ install_nvm() {
97 132 if [ -d "$NVM_DIR" ]; then
98 133 warn "NVM is already installed."
99 134 else
100 - log "Installing NVM..."
101 - curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
135 + log "Installing NVM via $CURRENT_SHELL..."
136 + curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | $CURRENT_SHELL
102 137 fi
103 138
104 - # Load NVM for the current session to ensure the 'nvm' command is available immediately
105 139 [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
106 140
107 - echo -e "\n${YELLOW}Which version of Node.js would you like to install?${NC}"
108 - echo " 1) LTS (Long Term Support - Recommended for stability)"
109 - echo " 2) Latest (Current features - Recommended for testing new APIs)"
110 - echo " 3) Skip installing Node.js right now"
111 - read -p "Select (1/2/3): " node_choice
141 + printf "\n${YELLOW}Which version of Node.js would you like to install?${NC}\n"
142 + printf " 1) LTS (Long Term Support - Recommended for stability)\n"
143 + printf " 2) Latest (Current features - Recommended for testing new APIs)\n"
144 + printf " 3) Skip installing Node.js right now\n"
145 +
146 + printf "Select (1/2/3): "
147 + read node_choice
112 148
113 149 case "$node_choice" in
114 - 2)
115 - log "Installing Latest Node.js..."
116 - nvm install node
117 - nvm alias default node
118 - nvm use node
119 - ;;
120 - 3)
121 - log "Skipping Node.js installation."
122 - ;;
123 - *)
124 - log "Installing Latest LTS Node.js..."
125 - nvm install --lts
126 - nvm alias default 'lts/*'
127 - nvm use --lts
128 - ;;
150 + 2) log "Installing Latest Node.js..."; nvm install node; nvm alias default node; nvm use node ;;
151 + 3) log "Skipping Node.js installation." ;;
152 + *) log "Installing Latest LTS Node.js..."; nvm install --lts; nvm alias default 'lts/*'; nvm use --lts ;;
129 153 esac
130 154 }
131 155
132 156 install_python() {
133 157 log "Fetching latest stable Python version..."
134 158
135 - # Scrape the main downloads page for the official 'Download' button text
136 159 LATEST_PY=$(curl -s https://www.python.org/downloads/ | grep -o 'Download Python 3\.[0-9]\{1,2\}\.[0-9]\{1,2\}' | head -1 | grep -o '3\.[0-9]\{1,2\}\.[0-9]\{1,2\}')
137 -
138 - # Fallback just in case curl fails
139 160 [[ -z "$LATEST_PY" ]] && LATEST_PY="3.12.3"
140 161
141 162 log "Detected Stable Version: $LATEST_PY"
@@ -200,19 +221,19 @@ install_go() {
200 221
201 222 install_sdkman() {
202 223 if [ -d "$HOME/.sdkman" ]; then warn "SDKMAN already exists"; return; fi
203 - log "Installing SDKMAN..."
204 - curl -s "https://get.sdkman.io" | bash
224 + log "Installing SDKMAN via $CURRENT_SHELL..."
225 + curl -s "https://get.sdkman.io" | $CURRENT_SHELL
205 226 }
206 227
207 228 install_dotnet() {
208 229 log "Installing .NET from official script..."
209 - curl -fsSL https://dot.net/v1/dotnet-install.sh | bash
230 + curl -fsSL https://dot.net/v1/dotnet-install.sh | $CURRENT_SHELL
210 231 add_to_path_config "DOTNET_TOOLS" 'export PATH="$PATH:$HOME/.dotnet/tools"'
211 232 }
212 233
213 - # =============================
234 + # =======================================================
214 235 # CLOUD & INFRASTRUCTURE
215 - # =============================
236 + # =======================================================
216 237
217 238 install_docker() {
218 239 if require_cmd docker; then log "Docker exists"; else
@@ -231,20 +252,16 @@ install_docker() {
231 252 open /Applications/Docker.app
232 253 log "Please complete the setup in the Docker Desktop UI."
233 254 else
234 - # Linux install
235 255 curl -fsSL https://get.docker.com | sudo sh
236 256 fi
237 257 fi
238 258
239 - # Post-install logic for Linux (Ubuntu/WSL)
240 259 if [[ "$OS" != "macOS" ]]; then
241 260 log "Applying Linux post-install actions..."
242 261
243 - # 1. Create docker group and add user
244 262 sudo groupadd -f docker
245 263 sudo usermod -aG docker "$USER"
246 264
247 - # 2. Enable and start Docker services
248 265 if command -v systemctl >/dev/null 2>&1; then
249 266 sudo systemctl enable --now docker.service
250 267 sudo systemctl enable --now containerd.service
@@ -252,7 +269,6 @@ install_docker() {
252 269 sudo service docker start
253 270 fi
254 271
255 - # 3. Immediate Socket Fix
256 272 if [[ -S /var/run/docker.sock ]]; then
257 273 log "Fixing ownership of /var/run/docker.sock..."
258 274 sudo chown root:docker /var/run/docker.sock
@@ -286,9 +302,13 @@ install_aws() {
286 302 install_gcloud() {
287 303 if require_cmd gcloud; then warn "Google Cloud CLI exists"; return; fi
288 304 log "Installing Google Cloud CLI..."
289 - curl -fsSL https://sdk.cloud.google.com | bash -s -- --disable-prompts
305 + curl -fsSL https://sdk.cloud.google.com | $CURRENT_SHELL -s -- --disable-prompts
290 306
291 - add_to_path_config "GCLOUD" '[ -f "$HOME/google-cloud-sdk/path.bash.inc" ] && . "$HOME/google-cloud-sdk/path.bash.inc"'
307 + if [[ "$CURRENT_SHELL" == "zsh" ]]; then
308 + add_to_path_config "GCLOUD" '[ -f "$HOME/google-cloud-sdk/path.zsh.inc" ] && source "$HOME/google-cloud-sdk/path.zsh.inc"'
309 + else
310 + add_to_path_config "GCLOUD" '[ -f "$HOME/google-cloud-sdk/path.bash.inc" ] && source "$HOME/google-cloud-sdk/path.bash.inc"'
311 + fi
292 312 }
293 313
294 314 install_firebase() {
@@ -303,9 +323,9 @@ install_firebase() {
303 323 npm install -g firebase-tools
304 324 }
305 325
306 - # =============================
326 + # =======================================================
307 327 # DEV TOOLS & SECURITY
308 - # =============================
328 + # =======================================================
309 329
310 330 install_gh() {
311 331 if require_cmd gh; then warn "GitHub CLI exists"; return; fi
@@ -331,12 +351,12 @@ install_infisical() {
331 351 npm install -g @infisical/cli
332 352 }
333 353
334 - # =============================
354 + # =======================================================
335 355 # AI & AGENTIC TOOLS
336 - # =============================
356 + # =======================================================
337 357
338 - install_claude() { log "Installing Claude Code..."; curl -fsSL https://claude.ai/install.sh | bash; }
339 - install_opencode() { log "Installing OpenCode..."; curl -fsSL https://opencode.ai/install | bash; }
358 + install_claude() { log "Installing Claude Code..."; curl -fsSL https://claude.ai/install.sh | $CURRENT_SHELL; }
359 + install_opencode() { log "Installing OpenCode..."; curl -fsSL https://opencode.ai/install | $CURRENT_SHELL; }
340 360
341 361 install_codex() {
342 362 log "Installing @openai/codex..."
@@ -344,42 +364,47 @@ install_codex() {
344 364 npm i -g @openai/codex
345 365 }
346 366
347 - # =============================
367 + # =======================================================
348 368 # MENU LOGIC
349 - # =============================
369 + # =======================================================
350 370 show_menu() {
351 371 clear
352 - echo -e "${BLUE}==================================================${NC}"
353 - echo -e "${GREEN} DEVELOPER ENVIRONMENT INSTALLER (Strict) ${NC}"
354 - echo -e "${BLUE}==================================================${NC}"
355 - echo -e "${YELLOW}--- Core Runtimes & Managers ---${NC}"
356 - echo " 1) Build Tools (GCC/Make)"
357 - echo " 2) Homebrew (Optional)"
358 - echo " 3) NVM (Node.js)"
359 - echo " 4) Python 3 (Official API)"
360 - echo " 5) Go (Official -> /usr/local)"
361 - echo " 6) SDKMAN (Java/Kotlin)"
362 - echo " 7) .NET (Official Script)"
363 - echo -e "${YELLOW}--- Cloud & Infrastructure ---${NC}"
364 - echo " 8) Docker (Official DMG/sh)"
365 - echo " 9) AWS CLI (Official Bin)"
366 - echo " 10) Google Cloud CLI (gcloud)"
367 - echo " 11) Firebase CLI (NPM/ARM64 Safe)"
368 - echo -e "${YELLOW}--- Dev Tools & Security ---${NC}"
369 - echo " 12) GitHub CLI (Official Bin)"
370 - echo " 13) Infisical (Official Bin)"
371 - echo -e "${YELLOW}--- AI & Agentic Tools ---${NC}"
372 - echo " 14) Claude Code CLI"
373 - echo " 15) OpenCode (opencode.ai)"
374 - echo " 16) OpenAI Codex CLI"
375 - echo -e "${BLUE}==================================================${NC}"
376 - echo " 99) Quit"
377 - echo -e "${BLUE}==================================================${NC}"
372 + printf "${BLUE}==================================================${NC}\n"
373 + printf "${GREEN} DEVELOPER ENVIRONMENT INSTALLER (Polyglot) ${NC}\n"
374 + printf "${BLUE}==================================================${NC}\n"
375 + printf "${YELLOW}--- Core Runtimes & Managers ---${NC}\n"
376 + printf " 1) Build Tools (GCC/Make)\n"
377 + printf " 2) Homebrew (Optional)\n"
378 + printf " 3) NVM (Node.js)\n"
379 + printf " 4) Python 3 (Official API)\n"
380 + printf " 5) Go (Official -> /usr/local)\n"
381 + printf " 6) SDKMAN (Java/Kotlin)\n"
382 + printf " 7) .NET (Official Script)\n"
383 + printf "${YELLOW}--- Cloud & Infrastructure ---${NC}\n"
384 + printf " 8) Docker (Official DMG/sh)\n"
385 + printf " 9) AWS CLI (Official Bin)\n"
386 + printf " 10) Google Cloud CLI (gcloud)\n"
387 + printf " 11) Firebase CLI (NPM/ARM64 Safe)\n"
388 + printf "${YELLOW}--- Dev Tools & Security ---${NC}\n"
389 + printf " 12) GitHub CLI (Official Bin)\n"
390 + printf " 13) Infisical (Official Bin)\n"
391 + printf "${YELLOW}--- AI & Agentic Tools ---${NC}\n"
392 + printf " 14) Claude Code CLI\n"
393 + printf " 15) OpenCode (opencode.ai)\n"
394 + printf " 16) OpenAI Codex CLI\n"
395 + printf "${BLUE}==================================================${NC}\n"
396 + printf " 99) Quit\n"
397 + printf "${BLUE}==================================================${NC}\n"
378 398 }
379 399
380 400 while true; do
381 401 show_menu
382 - read -p "Select options (space-separated): " input
402 +
403 + # Bulletproof prompt for both Bash and Zsh
404 + printf "Select options (space-separated): "
405 + read input
406 +
407 + # Thanks to 'setopt shwordsplit' in Zsh, this behaves perfectly across both shells
383 408 for choice in $input; do
384 409 case "$choice" in
385 410 1) install_build_tools ;;
@@ -402,5 +427,7 @@ while true; do
402 427 *) warn "Option $choice not valid." ;;
403 428 esac
404 429 done
405 - read -p "Press Enter to continue..."
430 +
431 + printf "Press Enter to continue..."
432 + read dummy
406 433 done

weehong ревизій цього gist 3 months ago. До ревизії

1 file changed, 35 insertions, 8 deletions

menu.sh

@@ -130,30 +130,57 @@ install_nvm() {
130 130 }
131 131
132 132 install_python() {
133 - log "Fetching latest Python 3 version from official API..."
134 - LATEST_PY=$(curl -s https://api.github.com/repos/python/cpython/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
135 - [[ -z "$LATEST_PY" ]] && LATEST_PY="3.12.3"
133 + log "Fetching latest stable Python version..."
136 134
137 - log "Installing Python $LATEST_PY directly from Python.org..."
135 + # Scrape the main downloads page for the official 'Download' button text
136 + LATEST_PY=$(curl -s https://www.python.org/downloads/ | grep -o 'Download Python 3\.[0-9]\{1,2\}\.[0-9]\{1,2\}' | head -1 | grep -o '3\.[0-9]\{1,2\}\.[0-9]\{1,2\}')
137 +
138 + # Fallback just in case curl fails
139 + [[ -z "$LATEST_PY" ]] && LATEST_PY="3.12.3"
140 +
141 + log "Detected Stable Version: $LATEST_PY"
142 +
138 143 if [[ "$OS" == "macOS" ]]; then
144 + log "Downloading official macOS package..."
139 145 PKG_URL="https://www.python.org/ftp/python/${LATEST_PY}/python-${LATEST_PY}-macos11.pkg"
140 146 curl -fsSL -o /tmp/python.pkg "$PKG_URL"
147 +
148 + log "Running installer..."
141 149 sudo installer -pkg /tmp/python.pkg -target /
142 150 rm /tmp/python.pkg
143 151 else
152 + log "Installing build dependencies (zlib, ssl, etc)..."
153 + sudo apt-get update && sudo apt-get install -y build-essential zlib1g-dev libssl-dev libffi-dev libsqlite3-dev
154 +
144 155 SRC_URL="https://www.python.org/ftp/python/${LATEST_PY}/Python-${LATEST_PY}.tgz"
145 - curl -fsSL -o /tmp/Python.tgz "$SRC_URL"
156 +
157 + log "Downloading $SRC_URL..."
158 + curl -fSL -o /tmp/Python.tgz "$SRC_URL" || err "Failed to download Python source from $SRC_URL"
159 +
146 160 cd /tmp && tar -xzf Python.tgz && cd "Python-${LATEST_PY}"
147 - ./configure --enable-optimizations
161 +
162 + log "Configuring build (with ensurepip)..."
163 + ./configure --enable-optimizations --with-ensurepip=install
164 +
165 + log "Compiling Python (this may take a few minutes)..."
148 166 sudo make altinstall
149 167
150 168 PY_MINOR=$(echo "$LATEST_PY" | cut -d. -f1,2)
151 - log "Symlinking python${PY_MINOR} to python3..."
169 +
170 + log "Setting up symlinks..."
152 171 sudo ln -sf /usr/local/bin/python${PY_MINOR} /usr/local/bin/python3
153 - sudo ln -sf /usr/local/bin/pip${PY_MINOR} /usr/local/bin/pip3
172 +
173 + if [[ -f "/usr/local/bin/pip${PY_MINOR}" ]]; then
174 + sudo ln -sf /usr/local/bin/pip${PY_MINOR} /usr/local/bin/pip3
175 + log "Successfully linked pip3!"
176 + else
177 + err "pip${PY_MINOR} was not generated during the build!"
178 + fi
154 179
155 180 cd ~ && sudo rm -rf /tmp/Python*
156 181 fi
182 +
183 + log "Python $LATEST_PY installation sequence finished!"
157 184 }
158 185
159 186 install_go() {

weehong ревизій цього gist 3 months ago. До ревизії

1 file changed, 1 insertion, 25 deletions

menu.sh

@@ -144,9 +144,7 @@ install_python() {
144 144 SRC_URL="https://www.python.org/ftp/python/${LATEST_PY}/Python-${LATEST_PY}.tgz"
145 145 curl -fsSL -o /tmp/Python.tgz "$SRC_URL"
146 146 cd /tmp && tar -xzf Python.tgz && cd "Python-${LATEST_PY}"
147 -
148 - # Added --with-ensurepip=install to guarantee pip is compiled in
149 - ./configure --enable-optimizations --with-ensurepip=install
147 + ./configure --enable-optimizations
150 148 sudo make altinstall
151 149
152 150 PY_MINOR=$(echo "$LATEST_PY" | cut -d. -f1,2)
@@ -156,28 +154,6 @@ install_python() {
156 154
157 155 cd ~ && sudo rm -rf /tmp/Python*
158 156 fi
159 -
160 - # ==========================================
161 - # NEW: Explicit Pip Bootstrap & Upgrade Step
162 - # ==========================================
163 - log "Ensuring pip3 is installed and up to date..."
164 -
165 - # Reload path temporarily just in case it was installed to a fresh directory
166 - export PATH="/usr/local/bin:$PATH"
167 -
168 - if require_cmd python3; then
169 - # 1. Bootstrap pip (in case the package or make process missed it)
170 - sudo python3 -m ensurepip --upgrade --default-pip
171 -
172 - # 2. Upgrade pip to the absolute latest version
173 - sudo python3 -m pip install --upgrade pip
174 -
175 - log "Python and Pip3 successfully installed/upgraded."
176 - python3 --version
177 - pip3 --version
178 - else
179 - err "Python3 installation failed or isn't in PATH. Cannot configure pip3."
180 - fi
181 157 }
182 158
183 159 install_go() {

weehong ревизій цього gist 3 months ago. До ревизії

1 file changed, 25 insertions, 1 deletion

menu.sh

@@ -144,7 +144,9 @@ install_python() {
144 144 SRC_URL="https://www.python.org/ftp/python/${LATEST_PY}/Python-${LATEST_PY}.tgz"
145 145 curl -fsSL -o /tmp/Python.tgz "$SRC_URL"
146 146 cd /tmp && tar -xzf Python.tgz && cd "Python-${LATEST_PY}"
147 - ./configure --enable-optimizations
147 +
148 + # Added --with-ensurepip=install to guarantee pip is compiled in
149 + ./configure --enable-optimizations --with-ensurepip=install
148 150 sudo make altinstall
149 151
150 152 PY_MINOR=$(echo "$LATEST_PY" | cut -d. -f1,2)
@@ -154,6 +156,28 @@ install_python() {
154 156
155 157 cd ~ && sudo rm -rf /tmp/Python*
156 158 fi
159 +
160 + # ==========================================
161 + # NEW: Explicit Pip Bootstrap & Upgrade Step
162 + # ==========================================
163 + log "Ensuring pip3 is installed and up to date..."
164 +
165 + # Reload path temporarily just in case it was installed to a fresh directory
166 + export PATH="/usr/local/bin:$PATH"
167 +
168 + if require_cmd python3; then
169 + # 1. Bootstrap pip (in case the package or make process missed it)
170 + sudo python3 -m ensurepip --upgrade --default-pip
171 +
172 + # 2. Upgrade pip to the absolute latest version
173 + sudo python3 -m pip install --upgrade pip
174 +
175 + log "Python and Pip3 successfully installed/upgraded."
176 + python3 --version
177 + pip3 --version
178 + else
179 + err "Python3 installation failed or isn't in PATH. Cannot configure pip3."
180 + fi
157 181 }
158 182
159 183 install_go() {

weehong ревизій цього gist 3 months ago. До ревизії

1 file changed, 36 insertions, 23 deletions

menu.sh

@@ -188,37 +188,52 @@ install_dotnet() {
188 188 # =============================
189 189
190 190 install_docker() {
191 - if require_cmd docker; then log "Docker exists"; return; fi
192 - log "Installing Docker from official source..."
191 + if require_cmd docker; then log "Docker exists"; else
192 + log "Installing Docker from official source..."
193 +
194 + if [[ "$OS" == "macOS" ]]; then
195 + [[ "$SYS_ARCH" == "arm64" ]] && DOCKER_MAC_ARCH="arm64" || DOCKER_MAC_ARCH="amd64"
196 + DMG_URL="https://desktop.docker.com/mac/main/${DOCKER_MAC_ARCH}/Docker.dmg"
197 + curl -fsSL -o /tmp/Docker.dmg "$DMG_URL"
198 + hdiutil attach /tmp/Docker.dmg -nobrowse -mountpoint /Volumes/Docker
199 + sudo cp -a /Volumes/Docker/Docker.app /Applications/
200 + hdiutil detach /Volumes/Docker
201 + rm /tmp/Docker.dmg
202 +
203 + log "Starting Docker Desktop..."
204 + open /Applications/Docker.app
205 + log "Please complete the setup in the Docker Desktop UI."
206 + else
207 + # Linux install
208 + curl -fsSL https://get.docker.com | sudo sh
209 + fi
210 + fi
193 211
194 - if [[ "$OS" == "macOS" ]]; then
195 - [[ "$SYS_ARCH" == "arm64" ]] && DOCKER_MAC_ARCH="arm64" || DOCKER_MAC_ARCH="amd64"
196 - DMG_URL="https://desktop.docker.com/mac/main/${DOCKER_MAC_ARCH}/Docker.dmg"
197 - curl -fsSL -o /tmp/Docker.dmg "$DMG_URL"
198 - hdiutil attach /tmp/Docker.dmg -nobrowse -mountpoint /Volumes/Docker
199 - sudo cp -a /Volumes/Docker/Docker.app /Applications/
200 - hdiutil detach /Volumes/Docker
201 - rm /tmp/Docker.dmg
212 + # Post-install logic for Linux (Ubuntu/WSL)
213 + if [[ "$OS" != "macOS" ]]; then
214 + log "Applying Linux post-install actions..."
202 215
203 - # macOS Post-install: Launch Docker to start the daemon process
204 - log "Starting Docker Desktop..."
205 - open /Applications/Docker.app
206 - log "Please complete the setup in the Docker Desktop UI."
207 - else
208 - # Linux install
209 - curl -fsSL https://get.docker.com | sudo sh
210 -
211 - # Linux Post-install: Add user to group
216 + # 1. Create docker group and add user
217 + sudo groupadd -f docker
212 218 sudo usermod -aG docker "$USER"
213 219
214 - # Linux Post-install: Enable and start Docker services on boot
220 + # 2. Enable and start Docker services
215 221 if command -v systemctl >/dev/null 2>&1; then
216 222 sudo systemctl enable --now docker.service
217 223 sudo systemctl enable --now containerd.service
224 + elif [[ "$OS" == "WSL" ]]; then
225 + sudo service docker start
226 + fi
227 +
228 + # 3. Immediate Socket Fix
229 + if [[ -S /var/run/docker.sock ]]; then
230 + log "Fixing ownership of /var/run/docker.sock..."
231 + sudo chown root:docker /var/run/docker.sock
232 + sudo chmod 660 /var/run/docker.sock
218 233 fi
219 234
220 235 log "Added $USER to the docker group."
221 - log "CRITICAL: To apply group changes immediately without logging out, run: newgrp docker"
236 + log "CRITICAL: To apply group changes immediately, run: newgrp docker"
222 237 fi
223 238 }
224 239
@@ -246,7 +261,6 @@ install_gcloud() {
246 261 log "Installing Google Cloud CLI..."
247 262 curl -fsSL https://sdk.cloud.google.com | bash -s -- --disable-prompts
248 263
249 - # Use the dot operator which is more POSIX compliant
250 264 add_to_path_config "GCLOUD" '[ -f "$HOME/google-cloud-sdk/path.bash.inc" ] && . "$HOME/google-cloud-sdk/path.bash.inc"'
251 265 }
252 266
@@ -254,7 +268,6 @@ install_firebase() {
254 268 if require_cmd firebase; then warn "Firebase CLI exists"; return; fi
255 269 log "Installing Firebase CLI via NPM to ensure ARM64 compatibility..."
256 270
257 - # Check if npm exists, if not, try to load nvm or warn user
258 271 if ! require_cmd npm; then
259 272 err "NPM not found. Please install NVM (Option 3) first."
260 273 return 1

weehong ревизій цього gist 3 months ago. До ревизії

1 file changed, 5 insertions, 25 deletions

menu.sh

@@ -280,35 +280,15 @@ install_gh() {
280 280 }
281 281
282 282 install_infisical() {
283 - if require_cmd infisical; then warn "Infisical exists"; return; fi
284 - log "Fetching latest Infisical binary from GitHub Releases..."
285 -
286 - # Fetch latest version and handle potential API rate limits
287 - LATEST_INF=$(curl -s https://api.github.com/repos/Infisical/infisical-cli/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
288 -
289 - if [[ -z "$LATEST_INF" ]]; then
290 - err "Failed to fetch latest Infisical version. You might have hit a GitHub API rate limit."
291 - return 1
292 - fi
293 -
294 - TAR_FILE="infisical_${LATEST_INF}_${OS_LOWER}_${SYS_ARCH}.tar.gz"
295 - DOWNLOAD_URL="https://github.com/Infisical/infisical-cli/releases/download/v${LATEST_INF}/${TAR_FILE}"
296 -
297 - log "Downloading Infisical v${LATEST_INF}..."
283 + if require_cmd infisical; then warn "Infisical CLI exists"; return; fi
284 + log "Installing Infisical CLI via NPM..."
298 285
299 - # The -f flag in curl makes it fail silently on server errors, but we check the return code
300 - if ! curl -fsSL -o /tmp/infisical.tar.gz "$DOWNLOAD_URL"; then
301 - err "Download failed! URL might be incorrect: $DOWNLOAD_URL"
302 - rm -f /tmp/infisical.tar.gz
286 + if ! require_cmd npm; then
287 + err "NPM not found. Please install NVM (Option 3) first."
303 288 return 1
304 289 fi
305 -
306 - # Extract and cleanup
307 - tar -xzf /tmp/infisical.tar.gz -C /tmp
308 - sudo mv /tmp/infisical /usr/local/bin/
309 - rm -f /tmp/infisical.tar.gz
310 290
311 - log "Infisical successfully installed."
291 + npm install -g @infisical/cli
312 292 }
313 293
314 294 # =============================

weehong ревизій цього gist 3 months ago. До ревизії

1 file changed, 22 insertions, 2 deletions

menu.sh

@@ -282,13 +282,33 @@ install_gh() {
282 282 install_infisical() {
283 283 if require_cmd infisical; then warn "Infisical exists"; return; fi
284 284 log "Fetching latest Infisical binary from GitHub Releases..."
285 +
286 + # Fetch latest version and handle potential API rate limits
285 287 LATEST_INF=$(curl -s https://api.github.com/repos/Infisical/infisical-cli/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
288 +
289 + if [[ -z "$LATEST_INF" ]]; then
290 + err "Failed to fetch latest Infisical version. You might have hit a GitHub API rate limit."
291 + return 1
292 + fi
293 +
286 294 TAR_FILE="infisical_${LATEST_INF}_${OS_LOWER}_${SYS_ARCH}.tar.gz"
295 + DOWNLOAD_URL="https://github.com/Infisical/infisical-cli/releases/download/v${LATEST_INF}/${TAR_FILE}"
287 296
288 - curl -fsSL -o /tmp/infisical.tar.gz "https://github.com/Infisical/infisical-cli/releases/download/v${LATEST_INF}/${TAR_FILE}"
297 + log "Downloading Infisical v${LATEST_INF}..."
298 +
299 + # The -f flag in curl makes it fail silently on server errors, but we check the return code
300 + if ! curl -fsSL -o /tmp/infisical.tar.gz "$DOWNLOAD_URL"; then
301 + err "Download failed! URL might be incorrect: $DOWNLOAD_URL"
302 + rm -f /tmp/infisical.tar.gz
303 + return 1
304 + fi
305 +
306 + # Extract and cleanup
289 307 tar -xzf /tmp/infisical.tar.gz -C /tmp
290 308 sudo mv /tmp/infisical /usr/local/bin/
291 - rm /tmp/infisical.tar.gz
309 + rm -f /tmp/infisical.tar.gz
310 +
311 + log "Infisical successfully installed."
292 312 }
293 313
294 314 # =============================

weehong ревизій цього gist 3 months ago. До ревизії

1 file changed, 13 insertions, 4 deletions

menu.sh

@@ -245,13 +245,22 @@ install_gcloud() {
245 245 if require_cmd gcloud; then warn "Google Cloud CLI exists"; return; fi
246 246 log "Installing Google Cloud CLI..."
247 247 curl -fsSL https://sdk.cloud.google.com | bash -s -- --disable-prompts
248 - add_to_path_config "GCLOUD" 'source "$HOME/google-cloud-sdk/path.bash.inc"'
248 +
249 + # Use the dot operator which is more POSIX compliant
250 + add_to_path_config "GCLOUD" '[ -f "$HOME/google-cloud-sdk/path.bash.inc" ] && . "$HOME/google-cloud-sdk/path.bash.inc"'
249 251 }
250 252
251 253 install_firebase() {
252 254 if require_cmd firebase; then warn "Firebase CLI exists"; return; fi
253 - log "Installing Standalone Firebase CLI..."
254 - curl -sL https://firebase.tools | bash
255 + log "Installing Firebase CLI via NPM to ensure ARM64 compatibility..."
256 +
257 + # Check if npm exists, if not, try to load nvm or warn user
258 + if ! require_cmd npm; then
259 + err "NPM not found. Please install NVM (Option 3) first."
260 + return 1
261 + fi
262 +
263 + npm install -g firebase-tools
255 264 }
256 265
257 266 # =============================
@@ -315,7 +324,7 @@ show_menu() {
315 324 echo " 8) Docker (Official DMG/sh)"
316 325 echo " 9) AWS CLI (Official Bin)"
317 326 echo " 10) Google Cloud CLI (gcloud)"
318 - echo " 11) Firebase CLI (Standalone)"
327 + echo " 11) Firebase CLI (NPM/ARM64 Safe)"
319 328 echo -e "${YELLOW}--- Dev Tools & Security ---${NC}"
320 329 echo " 12) GitHub CLI (Official Bin)"
321 330 echo " 13) Infisical (Official Bin)"

weehong ревизій цього gist 3 months ago. До ревизії

1 file changed, 17 insertions, 1 deletion

menu.sh

@@ -199,10 +199,26 @@ install_docker() {
199 199 sudo cp -a /Volumes/Docker/Docker.app /Applications/
200 200 hdiutil detach /Volumes/Docker
201 201 rm /tmp/Docker.dmg
202 +
203 + # macOS Post-install: Launch Docker to start the daemon process
204 + log "Starting Docker Desktop..."
205 + open /Applications/Docker.app
206 + log "Please complete the setup in the Docker Desktop UI."
202 207 else
208 + # Linux install
203 209 curl -fsSL https://get.docker.com | sudo sh
210 +
211 + # Linux Post-install: Add user to group
204 212 sudo usermod -aG docker "$USER"
205 - log "Added $USER to docker group. You may need to logout/login."
213 +
214 + # Linux Post-install: Enable and start Docker services on boot
215 + if command -v systemctl >/dev/null 2>&1; then
216 + sudo systemctl enable --now docker.service
217 + sudo systemctl enable --now containerd.service
218 + fi
219 +
220 + log "Added $USER to the docker group."
221 + log "CRITICAL: To apply group changes immediately without logging out, run: newgrp docker"
206 222 fi
207 223 }
208 224
Новіше Пізніше