-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsetup.sh
More file actions
executable file
·300 lines (265 loc) · 12.2 KB
/
Copy pathsetup.sh
File metadata and controls
executable file
·300 lines (265 loc) · 12.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────────────────
# STAR Monorepo — Newcomer Setup Script
# ─────────────────────────────────────────────────────────────────────────────
#
# Dispatcher over the per-project setup scripts. Each subproject owns its own
# install steps (daq-server/setup.sh, firmware/setup.sh, EngineDesign/setup.sh,
# pid-designer/setup.sh, onshape-viewer/setup.sh) so you only pay for what you
# use — cloning the repo for the P&ID editor shouldn't force you to build
# Rust + elodin-db.
#
# ─── Usage ───────────────────────────────────────────────────────────────────
#
# bash setup.sh # interactive menu
# bash setup.sh --all # install everything
# bash setup.sh --daq-server # single project
# bash setup.sh --daq-server --firmware
# bash setup.sh --engine-design --ci # flags pass through to sub-scripts
# bash setup.sh --list # list available projects
# bash setup.sh --help
#
# Non-interactive:
# SETUP_YES=1 bash setup.sh --all # or --yes / -y
#
# ─── Windows users ───────────────────────────────────────────────────────────
#
# This repo has symlinks committed to git. macOS and Linux handle them
# automatically; Windows does not unless you enable symlink support BEFORE
# cloning:
#
# git config --global core.symlinks true
#
# (Or use WSL — strongly recommended over native Windows for this codebase.)
# Without this, files that should be symlinks become plain text files
# containing the link target, and builds will fail with confusing errors.
# ─────────────────────────────────────────────────────────────────────────────
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$REPO_ROOT"
# shellcheck disable=SC1091
source "$REPO_ROOT/scripts/setup_common.sh"
# ─── Project registry ────────────────────────────────────────────────────────
# One row per project: key | display name | script path | one-line description
# The dispatcher runs them in this order when multiple are selected — put the
# lightest ones first so quick projects finish before slow ones (daq-server).
PROJECTS=(
"pid-designer|P&ID Designer|pid-designer/setup.sh|FastAPI + React P&ID editor (quick)"
"recovery-calculator|Recovery Calculator|recovery-calculator/setup.sh|Parachute descent physics + FastAPI + React"
"onshape-viewer|Onshape CM Viewer|onshape-viewer/setup.sh|FastAPI + React/three.js CAD centre-of-mass viewer (quick)"
"engine-design|Engine Design|EngineDesign/setup.sh|Python physics pipeline + FastAPI + React"
"firmware|Firmware|firmware/setup.sh|PlatformIO for ESP32 board firmware"
"daq-server|DAQ Server|daq-server/setup.sh|C++ + Rust + Python + Node — the big one"
)
project_field() {
# $1 = row, $2 = 1..4 (key/name/path/desc)
awk -F'|' -v i="$2" '{print $i}' <<< "$1"
}
print_project_list() {
printf "\n Available projects:\n\n"
local i=1
for row in "${PROJECTS[@]}"; do
printf " %d) %-15s — %s\n" "$i" "$(project_field "$row" 1)" "$(project_field "$row" 4)"
i=$((i+1))
done
printf "\n"
}
show_help() {
awk '/^#!/{next} /^#/{sub(/^# ?/,""); print; next} {exit}' "${BASH_SOURCE[0]}"
print_project_list
cat <<'EOF'
Flags:
--all Install every project
--daq-server Install daq-server
--firmware Install firmware
--engine-design Install EngineDesign
--pid-designer Install pid-designer
--recovery-calculator Install recovery-calculator
--onshape-viewer Install onshape-viewer
--list List projects and exit
--yes, -y Accept all prompts (non-interactive)
--no-hook Don't offer daq-server pre-push format hook
--no-aliases Don't add the STAR shell aliases to your shell rc
--help, -h This help
Any additional flags are passed through to each project's setup.sh, e.g.:
bash setup.sh --engine-design --ci --no-frontend
bash setup.sh --daq-server --no-build
EOF
}
# ─── Argument parsing ────────────────────────────────────────────────────────
SELECTED=()
PASSTHRU=()
DID_LIST=0
NO_ALIASES=0
while [ $# -gt 0 ]; do
case "$1" in
--all)
for row in "${PROJECTS[@]}"; do SELECTED+=("$(project_field "$row" 1)"); done
;;
--daq-server) SELECTED+=("daq-server") ;;
--firmware) SELECTED+=("firmware") ;;
--engine-design) SELECTED+=("engine-design") ;;
--pid-designer) SELECTED+=("pid-designer") ;;
--recovery-calculator) SELECTED+=("recovery-calculator") ;;
--onshape-viewer) SELECTED+=("onshape-viewer") ;;
--list) DID_LIST=1 ;;
--yes|-y) export SETUP_YES=1; PASSTHRU+=("--yes") ;;
--no-hook) PASSTHRU+=("--no-hook") ;;
# Not passed through: aliases are monorepo-wide, installed once by the
# dispatcher rather than per project.
--no-aliases) NO_ALIASES=1 ;;
--help|-h) show_help; exit 0 ;;
# Anything else is passed through to sub-scripts (e.g. --ci, --no-build)
*) PASSTHRU+=("$1") ;;
esac
shift
done
if [ "$DID_LIST" = "1" ]; then
print_project_list
exit 0
fi
# ─── Sanity ──────────────────────────────────────────────────────────────────
step "Sanity checks"
if [ ! -d daq-server ] || [ ! -d firmware ]; then
fail "Run this from the STAR repo root (expected daq-server/ and firmware/)"
fi
ok "Repo root: $REPO_ROOT"
OS="$(detect_os)"
case "$OS" in
macOS|Linux|WSL) ok "Detected $OS" ;;
*) fail "Unsupported OS: $OS — use macOS, Linux, or WSL" ;;
esac
# ─── Interactive selection ───────────────────────────────────────────────────
if [ ${#SELECTED[@]} -eq 0 ]; then
if [ ! -t 0 ] || [ "${SETUP_YES:-0}" = "1" ]; then
# Non-interactive with no selection = default to --all (matches the
# old setup.sh behavior for CI / provisioning scripts calling us).
warn "No projects selected and non-interactive; defaulting to --all"
for row in "${PROJECTS[@]}"; do SELECTED+=("$(project_field "$row" 1)"); done
else
print_project_list
cat <<'EOF'
Which projects do you want to set up?
- Enter a comma- or space-separated list of numbers (e.g. "1 3" or "1,3")
- Enter "a" for all
- Enter "q" to quit
EOF
read -rp " Choice: " REPLY || REPLY=""
REPLY="${REPLY// /,}"
case "$REPLY" in
q|Q|"") warn "No selection — exiting"; exit 0 ;;
a|A|all)
for row in "${PROJECTS[@]}"; do SELECTED+=("$(project_field "$row" 1)"); done
;;
*)
IFS=',' read -ra CHOICES <<< "$REPLY"
for c in "${CHOICES[@]}"; do
c="${c// /}"
[ -z "$c" ] && continue
if ! [[ "$c" =~ ^[0-9]+$ ]] \
|| [ "$c" -lt 1 ] || [ "$c" -gt "${#PROJECTS[@]}" ]; then
fail "Invalid choice: '$c' (want 1..${#PROJECTS[@]})"
fi
SELECTED+=("$(project_field "${PROJECTS[$((c-1))]}" 1)")
done
;;
esac
fi
fi
# Deduplicate while preserving PROJECTS order.
FINAL=()
for row in "${PROJECTS[@]}"; do
key="$(project_field "$row" 1)"
for sel in "${SELECTED[@]}"; do
if [ "$sel" = "$key" ]; then
FINAL+=("$row")
break
fi
done
done
if [ ${#FINAL[@]} -eq 0 ]; then
fail "No valid projects selected."
fi
# ─── Shared prep ─────────────────────────────────────────────────────────────
# Global black install: format.sh and the pre-push hook run outside any venv,
# so black needs to be on the global $PATH. Every project's format-check ends
# up calling the same top-level format.sh, so we install it once here rather
# than per-project.
step "Shared: pinned global black (for format.sh + pre-push hook)"
ensure_pinned_black
# Prompted here, before the long builds, so all the questions come up front and
# you can walk away. The summary reminds you at the end.
if [ "$NO_ALIASES" = "1" ]; then
ok "Skipping shell aliases (--no-aliases)"
else
step "Shared: shell aliases"
install_star_aliases "$REPO_ROOT"
fi
# docker compose interpolates the whole file up front, so without these even
# `docker compose build` fails. Cheap to create, never overwritten.
step "Shared: deployment env files"
bootstrap_env_files "$REPO_ROOT"
# Windows-symlink foot-gun sanity: if the DAQv2-Comms symlink got turned into
# a text file by a Windows clone, every project's build later will fail with
# confusing errors. Detect it once, upfront.
LINK="$REPO_ROOT/firmware/libraries/DAQv2-Comms"
if [ -e "$LINK" ] && [ ! -L "$LINK" ] && [ -f "$LINK" ]; then
warn "firmware/libraries/DAQv2-Comms is a plain file, not a symlink."
warn "You likely cloned on Windows without symlinks enabled. Re-clone with:"
warn " git config --global core.symlinks true"
fi
# ─── Dispatch ────────────────────────────────────────────────────────────────
printf "\n${BOLD}Plan:${NC} setup will run these projects in order:\n"
for row in "${FINAL[@]}"; do
printf " - %s (%s)\n" "$(project_field "$row" 2)" "$(project_field "$row" 3)"
done
printf "\n"
FAILED=()
COMPLETED=()
for row in "${FINAL[@]}"; do
key="$(project_field "$row" 1)"
name="$(project_field "$row" 2)"
script="$(project_field "$row" 3)"
step "▶ $name — $script"
if [ ! -f "$REPO_ROOT/$script" ]; then
warn "Setup script missing: $script — skipping"
FAILED+=("$name (script missing)")
continue
fi
# We run each project's setup as a *subshell* rather than sourcing so a
# single project's failure doesn't kill the dispatcher for the others,
# and each project sees a clean environment.
if bash "$REPO_ROOT/$script" "${PASSTHRU[@]}"; then
COMPLETED+=("$name")
ok "$name setup complete"
else
rc=$?
FAILED+=("$name (exit $rc)")
warn "$name failed with exit $rc — continuing with remaining projects"
fi
done
# ─── Summary ─────────────────────────────────────────────────────────────────
step "Setup summary"
if [ ${#COMPLETED[@]} -gt 0 ]; then
printf " ${GREEN}✓ Completed:${NC}\n"
for n in "${COMPLETED[@]}"; do printf " - %s\n" "$n"; done
fi
if [ ${#FAILED[@]} -gt 0 ]; then
printf " ${RED}✗ Failed:${NC}\n"
for n in "${FAILED[@]}"; do printf " - %s\n" "$n"; done
printf "\n"
fail "One or more project setups failed. See output above."
fi
cat <<EOF
All done. Per-project next-step instructions were printed above.
To run anything:
cd <project> && ./dev.sh # starts detached; --attach to watch it
# --status, --logs, --stop; --help for all
star-help # the alias list, if you added them
# (open a new shell first)
Common reminders:
• Add \$HOME/.cargo/bin to \$PATH if you set up daq-server
• Add pip --user bin dir to \$PATH if 'black' or 'pio' aren't found
macOS: \$HOME/Library/Python/<ver>/bin
Linux: \$HOME/.local/bin
EOF