easy-devops 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +325 -0
- package/cli/index.js +91 -0
- package/cli/managers/domain-manager.js +451 -0
- package/cli/managers/nginx-manager.js +329 -0
- package/cli/managers/node-manager.js +275 -0
- package/cli/managers/ssl-manager.js +397 -0
- package/cli/menus/.gitkeep +0 -0
- package/cli/menus/dashboard.js +223 -0
- package/cli/menus/domains.js +5 -0
- package/cli/menus/nginx.js +5 -0
- package/cli/menus/nodejs.js +5 -0
- package/cli/menus/settings.js +83 -0
- package/cli/menus/ssl.js +5 -0
- package/core/config.js +37 -0
- package/core/db.js +30 -0
- package/core/detector.js +257 -0
- package/core/nginx-conf-generator.js +309 -0
- package/core/shell.js +151 -0
- package/dashboard/lib/.gitkeep +0 -0
- package/dashboard/lib/cert-reader.js +59 -0
- package/dashboard/lib/domains-db.js +51 -0
- package/dashboard/lib/nginx-conf-generator.js +16 -0
- package/dashboard/lib/nginx-service.js +282 -0
- package/dashboard/public/js/app.js +486 -0
- package/dashboard/routes/.gitkeep +0 -0
- package/dashboard/routes/auth.js +30 -0
- package/dashboard/routes/domains.js +300 -0
- package/dashboard/routes/nginx.js +151 -0
- package/dashboard/routes/settings.js +78 -0
- package/dashboard/routes/ssl.js +105 -0
- package/dashboard/server.js +79 -0
- package/dashboard/views/index.ejs +327 -0
- package/dashboard/views/partials/domain-form.ejs +229 -0
- package/dashboard/views/partials/domains-panel.ejs +66 -0
- package/dashboard/views/partials/login.ejs +50 -0
- package/dashboard/views/partials/nginx-panel.ejs +90 -0
- package/dashboard/views/partials/overview.ejs +67 -0
- package/dashboard/views/partials/settings-panel.ejs +37 -0
- package/dashboard/views/partials/sidebar.ejs +45 -0
- package/dashboard/views/partials/ssl-panel.ejs +53 -0
- package/data/.gitkeep +0 -0
- package/install.bat +41 -0
- package/install.ps1 +653 -0
- package/install.sh +452 -0
- package/lib/installer/.gitkeep +0 -0
- package/lib/installer/detect.sh +88 -0
- package/lib/installer/node-versions.sh +109 -0
- package/lib/installer/nvm-bootstrap.sh +77 -0
- package/lib/installer/picker.sh +163 -0
- package/lib/installer/progress.sh +25 -0
- package/package.json +67 -0
package/install.sh
ADDED
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# install.sh — Easy DevOps Bootstrap Installer (Linux / macOS)
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# bash install.sh [OPTIONS]
|
|
6
|
+
#
|
|
7
|
+
# Options:
|
|
8
|
+
# --help, -h Print this help and exit 0
|
|
9
|
+
# --version VERSION Skip picker; use the specified Node.js version
|
|
10
|
+
# --keep-node Skip Node.js management; proceed to dependency install
|
|
11
|
+
#
|
|
12
|
+
# Exit codes:
|
|
13
|
+
# 0 Installation completed successfully
|
|
14
|
+
# 1 Unrecoverable error
|
|
15
|
+
# 2 User cancelled
|
|
16
|
+
|
|
17
|
+
set -euo pipefail
|
|
18
|
+
|
|
19
|
+
# ---------------------------------------------------------------------------
|
|
20
|
+
# Resolve script and project directory
|
|
21
|
+
# ---------------------------------------------------------------------------
|
|
22
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
23
|
+
EASYDEVOPS_DIR="${EASYDEVOPS_DIR:-$SCRIPT_DIR}"
|
|
24
|
+
|
|
25
|
+
# ---------------------------------------------------------------------------
|
|
26
|
+
# Source lib modules
|
|
27
|
+
# ---------------------------------------------------------------------------
|
|
28
|
+
LIB_DIR="$SCRIPT_DIR/lib/installer"
|
|
29
|
+
|
|
30
|
+
for _module in progress.sh detect.sh node-versions.sh picker.sh nvm-bootstrap.sh; do
|
|
31
|
+
if [ ! -f "$LIB_DIR/$_module" ]; then
|
|
32
|
+
printf 'Error: Required module not found: %s/%s\n' "$LIB_DIR" "$_module" >&2
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
# shellcheck source=/dev/null
|
|
36
|
+
. "$LIB_DIR/$_module"
|
|
37
|
+
done
|
|
38
|
+
|
|
39
|
+
# ---------------------------------------------------------------------------
|
|
40
|
+
# Result tracking (mirrors install.ps1 summary table)
|
|
41
|
+
# ---------------------------------------------------------------------------
|
|
42
|
+
_RESULT_NAMES=()
|
|
43
|
+
_RESULT_STATUS=() # "ok" or "fail"
|
|
44
|
+
_RESULT_DETAILS=()
|
|
45
|
+
|
|
46
|
+
add_result() {
|
|
47
|
+
local name="$1" ok="$2" detail="${3:-}"
|
|
48
|
+
_RESULT_NAMES+=("$name")
|
|
49
|
+
_RESULT_STATUS+=("$ok")
|
|
50
|
+
_RESULT_DETAILS+=("$detail")
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
# ---------------------------------------------------------------------------
|
|
54
|
+
# Error / cancellation helpers
|
|
55
|
+
# ---------------------------------------------------------------------------
|
|
56
|
+
|
|
57
|
+
# die <step_name> <reason> [recovery_cmd...]
|
|
58
|
+
die() {
|
|
59
|
+
local step="$1"
|
|
60
|
+
local reason="$2"
|
|
61
|
+
shift 2
|
|
62
|
+
step_failed "$step"
|
|
63
|
+
add_result "$step" "fail" "$reason"
|
|
64
|
+
printf '\nInstallation failed: %s. See above for details.\n' "$reason" >&2
|
|
65
|
+
if [ "$#" -gt 0 ]; then
|
|
66
|
+
printf '\nManual recovery:\n' >&2
|
|
67
|
+
local cmd
|
|
68
|
+
for cmd in "$@"; do
|
|
69
|
+
printf ' %s\n' "$cmd" >&2
|
|
70
|
+
done
|
|
71
|
+
fi
|
|
72
|
+
exit 1
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
# check_error <exit_code> <step_name> <reason> [recovery_cmd...]
|
|
76
|
+
check_error() {
|
|
77
|
+
local code="$1"
|
|
78
|
+
shift
|
|
79
|
+
if [ "$code" -ne 0 ]; then
|
|
80
|
+
die "$@"
|
|
81
|
+
fi
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
# ---------------------------------------------------------------------------
|
|
85
|
+
# --help flag
|
|
86
|
+
# ---------------------------------------------------------------------------
|
|
87
|
+
print_help() {
|
|
88
|
+
cat <<'EOF'
|
|
89
|
+
Easy DevOps Bootstrap Installer
|
|
90
|
+
|
|
91
|
+
Usage:
|
|
92
|
+
bash install.sh [OPTIONS]
|
|
93
|
+
|
|
94
|
+
Options:
|
|
95
|
+
--help, -h Print this help and exit
|
|
96
|
+
--version VERSION Skip the version picker; install the specified Node.js
|
|
97
|
+
version directly (e.g., --version 20.11.1)
|
|
98
|
+
--keep-node Skip Node.js management entirely; proceed straight to
|
|
99
|
+
dependency installation with whatever Node.js is active
|
|
100
|
+
|
|
101
|
+
Exit codes:
|
|
102
|
+
0 Installation completed successfully
|
|
103
|
+
1 Unrecoverable error (network failure, permission denied, etc.)
|
|
104
|
+
2 User cancelled / aborted at a prompt
|
|
105
|
+
|
|
106
|
+
Examples:
|
|
107
|
+
bash install.sh # Interactive install
|
|
108
|
+
bash install.sh --version 20 # Install Node.js 20.x (latest patch)
|
|
109
|
+
bash install.sh --keep-node # Skip Node.js management
|
|
110
|
+
EOF
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
# ---------------------------------------------------------------------------
|
|
114
|
+
# Parse CLI flags
|
|
115
|
+
# ---------------------------------------------------------------------------
|
|
116
|
+
FORCED_VERSION=""
|
|
117
|
+
KEEP_NODE=false
|
|
118
|
+
|
|
119
|
+
while [ "$#" -gt 0 ]; do
|
|
120
|
+
case "$1" in
|
|
121
|
+
--help|-h)
|
|
122
|
+
print_help
|
|
123
|
+
exit 0
|
|
124
|
+
;;
|
|
125
|
+
--version)
|
|
126
|
+
if [ -z "${2:-}" ]; then
|
|
127
|
+
printf 'Error: --version requires a value (e.g., --version 20.11.1)\n' >&2
|
|
128
|
+
exit 1
|
|
129
|
+
fi
|
|
130
|
+
FORCED_VERSION="$2"
|
|
131
|
+
shift 2
|
|
132
|
+
;;
|
|
133
|
+
--version=*)
|
|
134
|
+
FORCED_VERSION="${1#--version=}"
|
|
135
|
+
shift
|
|
136
|
+
;;
|
|
137
|
+
--keep-node)
|
|
138
|
+
KEEP_NODE=true
|
|
139
|
+
shift
|
|
140
|
+
;;
|
|
141
|
+
*)
|
|
142
|
+
printf 'Unknown option: %s\n' "$1" >&2
|
|
143
|
+
printf 'Run "bash install.sh --help" for usage.\n' >&2
|
|
144
|
+
exit 1
|
|
145
|
+
;;
|
|
146
|
+
esac
|
|
147
|
+
done
|
|
148
|
+
|
|
149
|
+
# ---------------------------------------------------------------------------
|
|
150
|
+
# Source mode / package mode detection (mirrors install.ps1)
|
|
151
|
+
#
|
|
152
|
+
# Package mode: easy-devops already on PATH (installed via npm -g)
|
|
153
|
+
# -> skip npm install + npm link
|
|
154
|
+
# Source mode: running from cloned repo or fresh directory
|
|
155
|
+
# -> run all 7 steps
|
|
156
|
+
# ---------------------------------------------------------------------------
|
|
157
|
+
PACKAGE_MODE=false
|
|
158
|
+
EXISTING_CMD=""
|
|
159
|
+
|
|
160
|
+
if command -v easy-devops >/dev/null 2>&1; then
|
|
161
|
+
EXISTING_CMD="$(command -v easy-devops)"
|
|
162
|
+
PACKAGE_MODE=true
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
# ---------------------------------------------------------------------------
|
|
166
|
+
# Banner
|
|
167
|
+
# ---------------------------------------------------------------------------
|
|
168
|
+
printf '\n'
|
|
169
|
+
printf '╔══════════════════════════════════════╗\n'
|
|
170
|
+
printf '║ Easy DevOps -- Bootstrap Installer ║\n'
|
|
171
|
+
printf '╚══════════════════════════════════════╝\n'
|
|
172
|
+
printf '\n'
|
|
173
|
+
|
|
174
|
+
if [ "$PACKAGE_MODE" = "true" ]; then
|
|
175
|
+
printf ' Mode: package (easy-devops already installed at %s)\n' "$EXISTING_CMD"
|
|
176
|
+
printf ' Skipping npm install / npm link steps.\n'
|
|
177
|
+
printf '\n'
|
|
178
|
+
else
|
|
179
|
+
printf ' Mode: source (installing from project directory)\n'
|
|
180
|
+
printf '\n'
|
|
181
|
+
fi
|
|
182
|
+
|
|
183
|
+
# ---------------------------------------------------------------------------
|
|
184
|
+
# 7-step install sequence
|
|
185
|
+
# ---------------------------------------------------------------------------
|
|
186
|
+
STEPS=(
|
|
187
|
+
"Detecting system"
|
|
188
|
+
"Fetching Node.js release list"
|
|
189
|
+
"Node.js version selection"
|
|
190
|
+
"Installing nvm"
|
|
191
|
+
"Installing Node.js via nvm"
|
|
192
|
+
"Installing Easy DevOps dependencies"
|
|
193
|
+
"Registering global command"
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
# Print all steps as pending initially
|
|
197
|
+
for _s in "${STEPS[@]}"; do
|
|
198
|
+
step_pending "$_s"
|
|
199
|
+
done
|
|
200
|
+
printf '\n'
|
|
201
|
+
|
|
202
|
+
# ---------------------------------------------------------------------------
|
|
203
|
+
# Step 1: Detect system
|
|
204
|
+
# ---------------------------------------------------------------------------
|
|
205
|
+
step_running "${STEPS[0]}"
|
|
206
|
+
detect_system
|
|
207
|
+
step_done "${STEPS[0]}"
|
|
208
|
+
add_result "System detection" "ok" "$SYSINFO_OS"
|
|
209
|
+
|
|
210
|
+
# Abort if no internet (unless --keep-node is set and we won't need the network)
|
|
211
|
+
if [ "$SYSINFO_HAS_INTERNET" = "false" ] && [ "$KEEP_NODE" = "false" ]; then
|
|
212
|
+
die "${STEPS[0]}" "No internet connectivity -- cannot reach nodejs.org" \
|
|
213
|
+
"Check your network connection and retry: bash install.sh"
|
|
214
|
+
fi
|
|
215
|
+
|
|
216
|
+
# ---------------------------------------------------------------------------
|
|
217
|
+
# Node.js decision tree
|
|
218
|
+
# ---------------------------------------------------------------------------
|
|
219
|
+
|
|
220
|
+
# NodeChoice variables
|
|
221
|
+
NODE_ACTION="" # keep | upgrade | switch
|
|
222
|
+
NODE_TARGET="" # version string or empty
|
|
223
|
+
|
|
224
|
+
if [ "$KEEP_NODE" = "true" ]; then
|
|
225
|
+
# --keep-node flag: skip all Node.js management steps
|
|
226
|
+
NODE_ACTION="keep"
|
|
227
|
+
NODE_TARGET=""
|
|
228
|
+
step_done "${STEPS[1]} (skipped -- --keep-node)"
|
|
229
|
+
add_result "Node.js release list" "ok" "Skipped (--keep-node)"
|
|
230
|
+
step_done "${STEPS[2]} (skipped -- --keep-node)"
|
|
231
|
+
add_result "Node.js selection" "ok" "Skipped (--keep-node)"
|
|
232
|
+
elif [ -n "$FORCED_VERSION" ]; then
|
|
233
|
+
# --version VERSION flag: version already known
|
|
234
|
+
NODE_ACTION="switch"
|
|
235
|
+
NODE_TARGET="$FORCED_VERSION"
|
|
236
|
+
step_done "${STEPS[1]} (skipped -- version specified)"
|
|
237
|
+
add_result "Node.js release list" "ok" "Skipped (--version $FORCED_VERSION)"
|
|
238
|
+
step_done "${STEPS[2]} (skipped -- version specified: $FORCED_VERSION)"
|
|
239
|
+
add_result "Node.js selection" "ok" "$FORCED_VERSION"
|
|
240
|
+
else
|
|
241
|
+
# ---------------------------------------------------------------------------
|
|
242
|
+
# Step 2: Fetch Node.js release list
|
|
243
|
+
# ---------------------------------------------------------------------------
|
|
244
|
+
step_running "${STEPS[1]}"
|
|
245
|
+
if ! fetch_node_versions; then
|
|
246
|
+
die "${STEPS[1]}" "Failed to fetch Node.js release list from nodejs.org" \
|
|
247
|
+
"Check internet connection and retry: bash install.sh"
|
|
248
|
+
fi
|
|
249
|
+
step_done "${STEPS[1]}"
|
|
250
|
+
add_result "Node.js release list" "ok" "${#NODE_RELEASES[@]} versions fetched"
|
|
251
|
+
|
|
252
|
+
# ---------------------------------------------------------------------------
|
|
253
|
+
# Step 3: Version selection
|
|
254
|
+
# ---------------------------------------------------------------------------
|
|
255
|
+
step_running "${STEPS[2]}"
|
|
256
|
+
|
|
257
|
+
if [ -n "$SYSINFO_NODE_VERSION" ]; then
|
|
258
|
+
# Node.js already installed -- present 3-option menu (matches install.ps1)
|
|
259
|
+
printf '\nNode.js %s is already installed.\n' "$SYSINFO_NODE_VERSION"
|
|
260
|
+
printf 'What would you like to do?\n\n'
|
|
261
|
+
printf ' 1) Keep current version (%s)\n' "$SYSINFO_NODE_VERSION"
|
|
262
|
+
printf ' 2) Upgrade to latest LTS automatically\n'
|
|
263
|
+
printf ' 3) Switch to a different version (opens picker)\n'
|
|
264
|
+
printf '\n'
|
|
265
|
+
|
|
266
|
+
local_choice=""
|
|
267
|
+
while true; do
|
|
268
|
+
printf 'Enter 1, 2, or 3 (q to quit): '
|
|
269
|
+
IFS= read -r local_choice
|
|
270
|
+
case "$local_choice" in
|
|
271
|
+
1)
|
|
272
|
+
NODE_ACTION="keep"
|
|
273
|
+
NODE_TARGET=""
|
|
274
|
+
break
|
|
275
|
+
;;
|
|
276
|
+
2)
|
|
277
|
+
NODE_ACTION="upgrade"
|
|
278
|
+
NODE_TARGET=""
|
|
279
|
+
_upgrade_lts=""
|
|
280
|
+
for _upgrade_rel in "${NODE_RELEASES[@]}"; do
|
|
281
|
+
_upgrade_lts="$(printf '%s' "$_upgrade_rel" | cut -d'|' -f3)"
|
|
282
|
+
if [ "$_upgrade_lts" != "false" ]; then
|
|
283
|
+
NODE_TARGET="$(printf '%s' "$_upgrade_rel" | cut -d'|' -f1)"
|
|
284
|
+
break
|
|
285
|
+
fi
|
|
286
|
+
done
|
|
287
|
+
if [ -z "$NODE_TARGET" ]; then
|
|
288
|
+
die "${STEPS[2]}" "Could not determine latest LTS version" \
|
|
289
|
+
"Run: bash install.sh --version <version>"
|
|
290
|
+
fi
|
|
291
|
+
break
|
|
292
|
+
;;
|
|
293
|
+
3)
|
|
294
|
+
NODE_ACTION="switch"
|
|
295
|
+
_pick_rc=0
|
|
296
|
+
pick_version "$SYSINFO_NODE_VERSION" || _pick_rc=$?
|
|
297
|
+
if [ "$_pick_rc" -eq 2 ]; then
|
|
298
|
+
printf '\nInstallation cancelled by user.\n'
|
|
299
|
+
exit 2
|
|
300
|
+
fi
|
|
301
|
+
check_error "$_pick_rc" "${STEPS[2]}" "Version selection failed"
|
|
302
|
+
NODE_TARGET="$PICKED_VERSION"
|
|
303
|
+
break
|
|
304
|
+
;;
|
|
305
|
+
q|Q)
|
|
306
|
+
printf '\nInstallation cancelled by user.\n'
|
|
307
|
+
exit 2
|
|
308
|
+
;;
|
|
309
|
+
*)
|
|
310
|
+
printf 'Invalid choice. Please enter 1, 2, or 3.\n' >&2
|
|
311
|
+
;;
|
|
312
|
+
esac
|
|
313
|
+
done
|
|
314
|
+
else
|
|
315
|
+
# No Node.js installed -- go straight to picker
|
|
316
|
+
_pick_rc=0
|
|
317
|
+
pick_version "" || _pick_rc=$?
|
|
318
|
+
if [ "$_pick_rc" -eq 2 ]; then
|
|
319
|
+
printf '\nInstallation cancelled by user.\n'
|
|
320
|
+
exit 2
|
|
321
|
+
fi
|
|
322
|
+
check_error "$_pick_rc" "${STEPS[2]}" "Version selection failed"
|
|
323
|
+
NODE_ACTION="switch"
|
|
324
|
+
NODE_TARGET="$PICKED_VERSION"
|
|
325
|
+
fi
|
|
326
|
+
|
|
327
|
+
step_done "${STEPS[2]}"
|
|
328
|
+
add_result "Node.js selection" "ok" "${NODE_ACTION}${NODE_TARGET:+ -> $NODE_TARGET}"
|
|
329
|
+
fi
|
|
330
|
+
|
|
331
|
+
# ---------------------------------------------------------------------------
|
|
332
|
+
# Steps 4 + 5: nvm bootstrap + Node.js install
|
|
333
|
+
# ---------------------------------------------------------------------------
|
|
334
|
+
if [ "$NODE_ACTION" = "keep" ]; then
|
|
335
|
+
step_done "${STEPS[3]} (skipped -- keeping current Node.js)"
|
|
336
|
+
add_result "nvm" "ok" "Skipped (keep)"
|
|
337
|
+
step_done "${STEPS[4]} (skipped -- keeping current Node.js)"
|
|
338
|
+
add_result "Node.js install" "ok" "Skipped (keep)"
|
|
339
|
+
else
|
|
340
|
+
# Step 4: bootstrap nvm
|
|
341
|
+
step_running "${STEPS[3]}"
|
|
342
|
+
if ! bootstrap_nvm; then
|
|
343
|
+
die "${STEPS[3]}" "nvm installation failed" \
|
|
344
|
+
"curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/HEAD/install.sh | bash" \
|
|
345
|
+
"source ~/.nvm/nvm.sh" \
|
|
346
|
+
"bash install.sh --version $NODE_TARGET"
|
|
347
|
+
fi
|
|
348
|
+
step_done "${STEPS[3]}"
|
|
349
|
+
add_result "nvm" "ok" ""
|
|
350
|
+
|
|
351
|
+
# Step 5: install chosen Node.js version
|
|
352
|
+
step_running "${STEPS[4]}"
|
|
353
|
+
printf 'Installing Node.js %s via nvm...\n' "$NODE_TARGET"
|
|
354
|
+
if ! nvm install "$NODE_TARGET" 2>&1; then
|
|
355
|
+
die "${STEPS[4]}" "Failed to install Node.js $NODE_TARGET via nvm" \
|
|
356
|
+
"nvm install $NODE_TARGET" \
|
|
357
|
+
"nvm use $NODE_TARGET" \
|
|
358
|
+
"npm install" \
|
|
359
|
+
"npm link"
|
|
360
|
+
fi
|
|
361
|
+
if ! nvm use "$NODE_TARGET" 2>&1; then
|
|
362
|
+
die "${STEPS[4]}" "Failed to activate Node.js $NODE_TARGET" \
|
|
363
|
+
"nvm use $NODE_TARGET" \
|
|
364
|
+
"npm install" \
|
|
365
|
+
"npm link"
|
|
366
|
+
fi
|
|
367
|
+
step_done "${STEPS[4]}"
|
|
368
|
+
add_result "Node.js install" "ok" "$NODE_TARGET"
|
|
369
|
+
fi
|
|
370
|
+
|
|
371
|
+
# ---------------------------------------------------------------------------
|
|
372
|
+
# Step 6: npm install
|
|
373
|
+
# ---------------------------------------------------------------------------
|
|
374
|
+
if [ "$PACKAGE_MODE" = "true" ]; then
|
|
375
|
+
step_done "${STEPS[5]} (skipped -- package mode)"
|
|
376
|
+
add_result "npm install" "ok" "Skipped (package mode)"
|
|
377
|
+
else
|
|
378
|
+
step_running "${STEPS[5]}"
|
|
379
|
+
printf 'Running npm install in %s...\n' "$EASYDEVOPS_DIR"
|
|
380
|
+
if ! npm install --prefix "$EASYDEVOPS_DIR" 2>&1; then
|
|
381
|
+
die "${STEPS[5]}" "npm install failed" \
|
|
382
|
+
"cd $EASYDEVOPS_DIR && npm install" \
|
|
383
|
+
"npm link"
|
|
384
|
+
fi
|
|
385
|
+
step_done "${STEPS[5]}"
|
|
386
|
+
add_result "npm install" "ok" ""
|
|
387
|
+
fi
|
|
388
|
+
|
|
389
|
+
# ---------------------------------------------------------------------------
|
|
390
|
+
# Step 7: npm link -- register global command
|
|
391
|
+
# ---------------------------------------------------------------------------
|
|
392
|
+
if [ "$PACKAGE_MODE" = "true" ]; then
|
|
393
|
+
step_done "${STEPS[6]} (skipped -- package mode)"
|
|
394
|
+
add_result "CLI registered" "ok" "Skipped (package mode)"
|
|
395
|
+
else
|
|
396
|
+
step_running "${STEPS[6]}"
|
|
397
|
+
printf 'Registering global command via npm link...\n'
|
|
398
|
+
_link_ok=false
|
|
399
|
+
if npm link --prefix "$EASYDEVOPS_DIR" 2>&1; then
|
|
400
|
+
_link_ok=true
|
|
401
|
+
elif (cd "$EASYDEVOPS_DIR" && npm link 2>&1); then
|
|
402
|
+
_link_ok=true
|
|
403
|
+
fi
|
|
404
|
+
|
|
405
|
+
if [ "$_link_ok" = "false" ]; then
|
|
406
|
+
die "${STEPS[6]}" "npm link failed -- could not register global command" \
|
|
407
|
+
"cd $EASYDEVOPS_DIR && npm link" \
|
|
408
|
+
"If permission denied, try: sudo npm link"
|
|
409
|
+
fi
|
|
410
|
+
|
|
411
|
+
# Verify the command is on PATH
|
|
412
|
+
if ! command -v easy-devops >/dev/null 2>&1; then
|
|
413
|
+
printf 'Warning: easy-devops command not found on PATH yet.\n' >&2
|
|
414
|
+
printf 'You may need to open a new terminal or run:\n' >&2
|
|
415
|
+
printf ' export PATH="$(npm bin -g):$PATH"\n' >&2
|
|
416
|
+
fi
|
|
417
|
+
|
|
418
|
+
step_done "${STEPS[6]}"
|
|
419
|
+
add_result "CLI registered" "ok" ""
|
|
420
|
+
fi
|
|
421
|
+
|
|
422
|
+
# ---------------------------------------------------------------------------
|
|
423
|
+
# Summary (mirrors install.ps1 summary table)
|
|
424
|
+
# ---------------------------------------------------------------------------
|
|
425
|
+
printf '\n'
|
|
426
|
+
printf '=== Installation Summary ===\n\n'
|
|
427
|
+
|
|
428
|
+
_allOK=true
|
|
429
|
+
for _i in "${!_RESULT_NAMES[@]}"; do
|
|
430
|
+
if [ "${_RESULT_STATUS[$_i]}" = "ok" ]; then
|
|
431
|
+
_icon=" OK "
|
|
432
|
+
else
|
|
433
|
+
_icon="FAIL"
|
|
434
|
+
_allOK=false
|
|
435
|
+
fi
|
|
436
|
+
_d="${_RESULT_DETAILS[$_i]}"
|
|
437
|
+
if [ -n "$_d" ]; then _d=" ($_d)"; fi
|
|
438
|
+
printf ' [%s] %s%s\n' "$_icon" "${_RESULT_NAMES[$_i]}" "$_d"
|
|
439
|
+
done
|
|
440
|
+
printf '\n'
|
|
441
|
+
|
|
442
|
+
if [ "$_allOK" = "true" ]; then
|
|
443
|
+
printf ' All steps completed successfully!\n\n'
|
|
444
|
+
printf ' Run the CLI:\n'
|
|
445
|
+
printf ' easy-devops\n'
|
|
446
|
+
else
|
|
447
|
+
printf ' Some steps need attention -- see warnings above.\n\n'
|
|
448
|
+
printf ' Fallback:\n'
|
|
449
|
+
printf ' node cli/index.js\n'
|
|
450
|
+
fi
|
|
451
|
+
printf '\n'
|
|
452
|
+
exit 0
|
|
File without changes
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# detect.sh — System detection helpers
|
|
3
|
+
# Sourced by install.sh; not executed directly.
|
|
4
|
+
#
|
|
5
|
+
# Exports (as shell variables):
|
|
6
|
+
# SYSINFO_OS — OS name + version string
|
|
7
|
+
# SYSINFO_ARCH — CPU architecture
|
|
8
|
+
# SYSINFO_SHELL — Shell name
|
|
9
|
+
# SYSINFO_SHELL_VERSION — Shell version
|
|
10
|
+
# SYSINFO_NODE_VERSION — Installed Node.js version, or ""
|
|
11
|
+
# SYSINFO_NPM_VERSION — Installed npm version, or ""
|
|
12
|
+
# SYSINFO_NVM_INSTALLED — "true" or "false"
|
|
13
|
+
# SYSINFO_HAS_INTERNET — "true" or "false"
|
|
14
|
+
# SYSINFO_IS_ROOT — "true" or "false"
|
|
15
|
+
#
|
|
16
|
+
# Functions:
|
|
17
|
+
# detect_system — populate all SYSINFO_* vars and print a summary block
|
|
18
|
+
|
|
19
|
+
detect_system() {
|
|
20
|
+
# OS name + version
|
|
21
|
+
if [ -f /etc/os-release ]; then
|
|
22
|
+
# shellcheck source=/dev/null
|
|
23
|
+
. /etc/os-release
|
|
24
|
+
SYSINFO_OS="${NAME:-unknown} ${VERSION_ID:-}"
|
|
25
|
+
SYSINFO_OS="${SYSINFO_OS%% }" # trim trailing space when VERSION_ID is empty
|
|
26
|
+
elif [ "$(uname -s)" = "Darwin" ]; then
|
|
27
|
+
SYSINFO_OS="macOS $(sw_vers -productVersion 2>/dev/null || echo '')"
|
|
28
|
+
else
|
|
29
|
+
SYSINFO_OS="$(uname -s) $(uname -r)"
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
# CPU architecture
|
|
33
|
+
SYSINFO_ARCH="$(uname -m)"
|
|
34
|
+
|
|
35
|
+
# Shell name + version
|
|
36
|
+
SYSINFO_SHELL="${SHELL##*/}"
|
|
37
|
+
# shellcheck disable=SC2016
|
|
38
|
+
SYSINFO_SHELL_VERSION="$("$SHELL" --version 2>&1 | head -1 | grep -oE '[0-9]+\.[0-9]+(\.[0-9]+)?' | head -1 || true)"
|
|
39
|
+
|
|
40
|
+
# Node.js version (empty if not installed)
|
|
41
|
+
if command -v node >/dev/null 2>&1; then
|
|
42
|
+
SYSINFO_NODE_VERSION="$(node --version 2>/dev/null | tr -d 'v' || true)"
|
|
43
|
+
else
|
|
44
|
+
SYSINFO_NODE_VERSION=""
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
# npm version (empty if not installed)
|
|
48
|
+
if command -v npm >/dev/null 2>&1; then
|
|
49
|
+
SYSINFO_NPM_VERSION="$(npm --version 2>/dev/null || true)"
|
|
50
|
+
else
|
|
51
|
+
SYSINFO_NPM_VERSION=""
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
# nvm installed?
|
|
55
|
+
local nvm_dir="${NVM_DIR:-$HOME/.nvm}"
|
|
56
|
+
if [ -d "$nvm_dir" ] && [ -f "$nvm_dir/nvm.sh" ]; then
|
|
57
|
+
SYSINFO_NVM_INSTALLED="true"
|
|
58
|
+
else
|
|
59
|
+
SYSINFO_NVM_INSTALLED="false"
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# Internet connectivity (reach nodejs.org)
|
|
63
|
+
if curl -s --max-time 5 --head https://nodejs.org >/dev/null 2>&1 \
|
|
64
|
+
|| ping -c 1 -W 3 nodejs.org >/dev/null 2>&1; then
|
|
65
|
+
SYSINFO_HAS_INTERNET="true"
|
|
66
|
+
else
|
|
67
|
+
SYSINFO_HAS_INTERNET="false"
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# Root / Administrator check
|
|
71
|
+
if [ "$(id -u)" = "0" ]; then
|
|
72
|
+
SYSINFO_IS_ROOT="true"
|
|
73
|
+
else
|
|
74
|
+
SYSINFO_IS_ROOT="false"
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# Print formatted summary block
|
|
78
|
+
printf '\n=== System Information ===\n'
|
|
79
|
+
printf ' OS : %s\n' "$SYSINFO_OS"
|
|
80
|
+
printf ' Architecture: %s\n' "$SYSINFO_ARCH"
|
|
81
|
+
printf ' Shell : %s %s\n' "$SYSINFO_SHELL" "$SYSINFO_SHELL_VERSION"
|
|
82
|
+
printf ' Node.js : %s\n' "${SYSINFO_NODE_VERSION:-not installed}"
|
|
83
|
+
printf ' npm : %s\n' "${SYSINFO_NPM_VERSION:-not installed}"
|
|
84
|
+
printf ' nvm : %s\n' "$SYSINFO_NVM_INSTALLED"
|
|
85
|
+
printf ' Internet : %s\n' "$SYSINFO_HAS_INTERNET"
|
|
86
|
+
printf ' Root : %s\n' "$SYSINFO_IS_ROOT"
|
|
87
|
+
printf '==========================\n\n'
|
|
88
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# node-versions.sh — Fetch and parse Node.js release list from nodejs.org
|
|
3
|
+
# Sourced by install.sh; not executed directly.
|
|
4
|
+
#
|
|
5
|
+
# Functions:
|
|
6
|
+
# fetch_node_versions — populate NODE_RELEASES array
|
|
7
|
+
#
|
|
8
|
+
# Exports:
|
|
9
|
+
# NODE_RELEASES — indexed array, each element: "version|major|lts_label|display_label"
|
|
10
|
+
# Up to 3 most-recent LTS majors (latest patch each) + 1 latest Current.
|
|
11
|
+
# Sorted descending by version.
|
|
12
|
+
|
|
13
|
+
fetch_node_versions() {
|
|
14
|
+
local url="https://nodejs.org/dist/index.json"
|
|
15
|
+
local raw=""
|
|
16
|
+
|
|
17
|
+
# Fetch release index
|
|
18
|
+
if command -v curl >/dev/null 2>&1; then
|
|
19
|
+
raw="$(curl -fsSL --max-time 30 "$url" 2>/dev/null || true)"
|
|
20
|
+
fi
|
|
21
|
+
if [ -z "$raw" ] && command -v wget >/dev/null 2>&1; then
|
|
22
|
+
raw="$(wget -qO- --timeout=30 "$url" 2>/dev/null || true)"
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
if [ -z "$raw" ]; then
|
|
26
|
+
printf 'Error: Failed to fetch Node.js release list from %s\n' "$url" >&2
|
|
27
|
+
return 1
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
# Parse JSON using awk (no jq dependency).
|
|
31
|
+
# Strategy: normalise the JSON blob to one object per line, then extract
|
|
32
|
+
# "version" and "lts" fields with awk string operations.
|
|
33
|
+
#
|
|
34
|
+
# Output format (one release per line): version|major|lts_label|display_label
|
|
35
|
+
local parsed
|
|
36
|
+
parsed="$(
|
|
37
|
+
printf '%s' "$raw" \
|
|
38
|
+
| tr -d '\n\r' \
|
|
39
|
+
| sed 's/},{/}\n{/g' \
|
|
40
|
+
| awk '
|
|
41
|
+
BEGIN { lts_count = 0; current_done = 0; seen_majors = " " }
|
|
42
|
+
{
|
|
43
|
+
line = $0
|
|
44
|
+
|
|
45
|
+
# --- extract "version":"vX.Y.Z" ---
|
|
46
|
+
ver = ""
|
|
47
|
+
tmp = line
|
|
48
|
+
n = split(tmp, dummy, "\"version\":\"")
|
|
49
|
+
if (n >= 2) {
|
|
50
|
+
seg = dummy[2]
|
|
51
|
+
ver_end = index(seg, "\"")
|
|
52
|
+
if (ver_end > 0) ver = substr(seg, 1, ver_end - 1)
|
|
53
|
+
}
|
|
54
|
+
if (ver == "") next
|
|
55
|
+
|
|
56
|
+
# strip leading "v"
|
|
57
|
+
ver_bare = ver
|
|
58
|
+
sub(/^v/, "", ver_bare)
|
|
59
|
+
|
|
60
|
+
# major version number
|
|
61
|
+
split(ver_bare, vparts, ".")
|
|
62
|
+
major = vparts[1]
|
|
63
|
+
|
|
64
|
+
# --- extract "lts":"CodeName" or "lts":false ---
|
|
65
|
+
lts_val = "false"
|
|
66
|
+
tmp2 = line
|
|
67
|
+
m = split(tmp2, dummy2, "\"lts\":")
|
|
68
|
+
if (m >= 2) {
|
|
69
|
+
seg2 = dummy2[2]
|
|
70
|
+
# Remove leading whitespace
|
|
71
|
+
gsub(/^[ \t]+/, "", seg2)
|
|
72
|
+
if (substr(seg2, 1, 1) == "\"") {
|
|
73
|
+
# String value: "CodeName"
|
|
74
|
+
seg2 = substr(seg2, 2)
|
|
75
|
+
q_end = index(seg2, "\"")
|
|
76
|
+
if (q_end > 0) lts_val = substr(seg2, 1, q_end - 1)
|
|
77
|
+
}
|
|
78
|
+
# else lts_val stays "false"
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# --- accumulate up to 3 LTS majors + 1 Current ---
|
|
82
|
+
if (lts_val != "false" && lts_val != "") {
|
|
83
|
+
# LTS release — only first occurrence of each major
|
|
84
|
+
if (index(seen_majors, " " major " ") == 0 && lts_count < 3) {
|
|
85
|
+
seen_majors = seen_majors major " "
|
|
86
|
+
lts_count++
|
|
87
|
+
print ver_bare "|" major "|" lts_val "|" ver " LTS (" lts_val ")"
|
|
88
|
+
}
|
|
89
|
+
} else if (current_done == 0) {
|
|
90
|
+
current_done = 1
|
|
91
|
+
print ver_bare "|" major "|false|" ver " (Current)"
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (lts_count >= 3 && current_done == 1) exit
|
|
95
|
+
}
|
|
96
|
+
'
|
|
97
|
+
)"
|
|
98
|
+
|
|
99
|
+
# Load into NODE_RELEASES array
|
|
100
|
+
NODE_RELEASES=()
|
|
101
|
+
while IFS= read -r line; do
|
|
102
|
+
[ -n "$line" ] && NODE_RELEASES+=("$line")
|
|
103
|
+
done <<< "$parsed"
|
|
104
|
+
|
|
105
|
+
if [ "${#NODE_RELEASES[@]}" -eq 0 ]; then
|
|
106
|
+
printf 'Error: Could not parse any Node.js releases from the release index.\n' >&2
|
|
107
|
+
return 1
|
|
108
|
+
fi
|
|
109
|
+
}
|