159 lines
4.6 KiB
Bash
Executable File
159 lines
4.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Local smoke test for the foreground installer UI supervisor.
|
|
# Runs without rebuilding the ISO.
|
|
set -euo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
DASHBOARD="$ROOT/configs/airootfs/usr/local/bin/omarchy-install-dashboard"
|
|
AUTOMATED="$ROOT/configs/airootfs/root/.automated_script.sh"
|
|
ORCH="$ROOT/configs/airootfs/usr/share/omarchy-iso/orchestrator"
|
|
OMARCHY_PATH_FOR_TEST="${OMARCHY_PATH_FOR_TEST:-$ROOT/../omarchy-installer}"
|
|
|
|
tmp="$(mktemp -d)"
|
|
trap 'rm -rf "$tmp"' EXIT
|
|
|
|
strip_ansi() {
|
|
python - "$1" <<'PY'
|
|
from pathlib import Path
|
|
import re, sys
|
|
s = Path(sys.argv[1]).read_text(errors="ignore")
|
|
s = re.sub(r"\x1b\[[0-9;?]*[A-Za-z]", "", s)
|
|
sys.stdout.write(s)
|
|
PY
|
|
}
|
|
|
|
assert_contains() {
|
|
local file="$1" needle="$2" stripped
|
|
stripped="$tmp/stripped.$(basename "$file")"
|
|
strip_ansi "$file" >"$stripped"
|
|
if ! grep -Fq "$needle" "$stripped"; then
|
|
echo "Expected $file to contain: $needle" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
assert_not_contains() {
|
|
local file="$1" needle="$2" stripped
|
|
stripped="$tmp/stripped.$(basename "$file")"
|
|
strip_ansi "$file" >"$stripped"
|
|
if grep -Fq "$needle" "$stripped"; then
|
|
echo "Expected $file not to contain: $needle" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
write_state_py='import json, sys, time, pathlib
|
|
path=pathlib.Path(sys.argv[1]); phase=sys.argv[2]
|
|
state={"started_at":time.time(),"current_phase":phase,"phase_started_at":time.time(),"phases":[]}
|
|
tmp=path.with_name(".state.json.tmp")
|
|
tmp.write_text(json.dumps(state))
|
|
tmp.replace(path)'
|
|
|
|
success_worker="$tmp/success-worker"
|
|
cat >"$success_worker" <<EOF
|
|
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
state="\$1"; log="\$2"
|
|
mkdir -p "\$(dirname "\$state")" "\$(dirname "\$log")"
|
|
python - "\$state" "Preparing live environment" <<'PY'
|
|
$write_state_py
|
|
PY
|
|
sleep 0.2
|
|
python - "\$state" "Installing Arch + Omarchy" <<'PY'
|
|
$write_state_py
|
|
PY
|
|
sleep 0.4
|
|
python - "\$state" "Validating boot setup" <<'PY'
|
|
$write_state_py
|
|
PY
|
|
sleep 0.2
|
|
cat >>"\$log" <<'LOG'
|
|
=== Installation Time Summary ===
|
|
Omarchy: 1m 40s
|
|
=================================
|
|
LOG
|
|
EOF
|
|
chmod +x "$success_worker"
|
|
|
|
no_duration_worker="$tmp/no-duration-worker"
|
|
cat >"$no_duration_worker" <<EOF
|
|
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
state="\$1"
|
|
mkdir -p "\$(dirname "\$state")"
|
|
python - "\$state" "Validating boot setup" <<'PY'
|
|
$write_state_py
|
|
PY
|
|
sleep 0.2
|
|
EOF
|
|
chmod +x "$no_duration_worker"
|
|
|
|
fail_worker="$tmp/fail-worker"
|
|
cat >"$fail_worker" <<EOF
|
|
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
state="\$1"
|
|
mkdir -p "\$(dirname "\$state")"
|
|
python - "\$state" "Installing Arch + Omarchy" <<'PY'
|
|
$write_state_py
|
|
PY
|
|
sleep 0.2
|
|
exit 7
|
|
EOF
|
|
chmod +x "$fail_worker"
|
|
|
|
success_state="$tmp/success-state.json"
|
|
success_log="$tmp/success.log"
|
|
success_capture="$tmp/success.capture"
|
|
OMARCHY_UI_AUTO_REBOOT=no OMARCHY_PATH="$OMARCHY_PATH_FOR_TEST" script -qfec \
|
|
"$DASHBOARD '$success_log' '$success_state' -- '$success_worker' '$success_state' '$success_log'" \
|
|
"$success_capture" >/dev/null
|
|
assert_contains "$success_capture" "Installing Omarchy"
|
|
assert_contains "$success_capture" "Installed in 1m 40s"
|
|
|
|
no_duration_state="$tmp/no-duration-state.json"
|
|
no_duration_log="$tmp/no-duration.log"
|
|
no_duration_capture="$tmp/no-duration.capture"
|
|
OMARCHY_UI_AUTO_REBOOT=no OMARCHY_PATH="$OMARCHY_PATH_FOR_TEST" script -qfec \
|
|
"$DASHBOARD '$no_duration_log' '$no_duration_state' -- '$no_duration_worker' '$no_duration_state'" \
|
|
"$no_duration_capture" >/dev/null
|
|
assert_contains "$no_duration_capture" "Finished installing"
|
|
|
|
fail_state="$tmp/fail-state.json"
|
|
fail_log="$tmp/fail.log"
|
|
fail_capture="$tmp/fail.capture"
|
|
set +e
|
|
OMARCHY_UI_AUTO_REBOOT=no OMARCHY_PATH="$OMARCHY_PATH_FOR_TEST" script -qfec \
|
|
"$DASHBOARD '$fail_log' '$fail_state' -- '$fail_worker' '$fail_state'" \
|
|
"$fail_capture" >/dev/null
|
|
fail_status=$?
|
|
set -e
|
|
if [[ $fail_status -ne 7 ]]; then
|
|
echo "Expected failure worker status 7, got $fail_status" >&2
|
|
exit 1
|
|
fi
|
|
assert_not_contains "$fail_capture" "Installed in"
|
|
assert_not_contains "$fail_capture" "Finished installing"
|
|
|
|
bash -n "$DASHBOARD" "$AUTOMATED"
|
|
python -m py_compile "$ORCH"/*.py
|
|
git -C "$ROOT" diff --check
|
|
|
|
if rg -n 'dashboard\.pid|dashboard\.stop|OMARCHY_INSTALL_DASHBOARD|_stop_install_dashboard|_dashboard_|killpg|current_phase.*Finishing|confirm\(|Reboot now' \
|
|
"$AUTOMATED" "$DASHBOARD" "$ORCH"; then
|
|
echo "Forbidden legacy dashboard lifecycle pattern found" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if ! grep -Fq '/usr/local/bin/omarchy-install-dashboard \' "$AUTOMATED"; then
|
|
echo "Expected .automated_script.sh to call dashboard in foreground" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if grep -Eq 'omarchy-install-dashboard .*&' "$AUTOMATED"; then
|
|
echo "Dashboard must not be launched in background" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "installer UI flow smoke test passed"
|