integration: preserve deployed 1.8.0 OTA work
This commit is contained in:
@@ -29,6 +29,7 @@ CASCADE_CONFIG="${ARCHY_CASCADE_CONFIG:-{\"ports\":[\"3000:3000\"],\"volumes\":[
|
||||
CASCADE_DATA_DIR="${ARCHY_CASCADE_DATA_DIR:-/var/lib/archipelago/${CASCADE_APP}}"
|
||||
|
||||
setup_file() {
|
||||
cascade_enabled || return 0
|
||||
: "${ARCHY_PASSWORD:?Set ARCHY_PASSWORD env var to the UI password}"
|
||||
export ARCHY_FORCE_LOGIN=1
|
||||
rpc_login
|
||||
@@ -55,6 +56,71 @@ app_state() {
|
||||
| jq -r --arg id "$CASCADE_APP" '.data["package-data"][$id].state // "absent"'
|
||||
}
|
||||
|
||||
# Live uninstall stage shown by My Apps, or an empty string when the entry is gone
|
||||
# or the backend has not emitted a stage yet.
|
||||
app_uninstall_stage() {
|
||||
rpc_result server.get-state '{}' 2>/dev/null \
|
||||
| jq -r --arg id "$CASCADE_APP" '.data["package-data"][$id]["uninstall-stage"] // ""'
|
||||
}
|
||||
|
||||
# Mirror the frontend's AppCard.vue mapping so the gate proves the UI has
|
||||
# backend data that can render as a monotonic, non-fake progress bar.
|
||||
uninstall_stage_percent() {
|
||||
local stage="$1"
|
||||
if [[ "$stage" =~ \(([0-9]+)[[:space:]]*/[[:space:]]*([0-9]+)\) ]]; then
|
||||
local done="${BASH_REMATCH[1]}" total="${BASH_REMATCH[2]}"
|
||||
if (( total > 0 )); then
|
||||
(( done > total )) && done="$total"
|
||||
echo $(( 10 + (done * 40 / total) ))
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
if [[ "$stage" =~ [Vv]olume ]]; then echo 70; return 0; fi
|
||||
if [[ "$stage" =~ [Dd]ata ]]; then echo 90; return 0; fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# Poll until CASCADE_APP disappears while enforcing the progress contract:
|
||||
# stages must be parseable, monotonic, below 100 before terminal absence, and
|
||||
# the operation must emit at least one visible stage instead of silently hanging.
|
||||
wait_absent_with_truthful_uninstall_progress() {
|
||||
local timeout="${1:-180}"
|
||||
local deadline=$(( $(date +%s) + timeout ))
|
||||
local saw_stage=0 last_percent=0
|
||||
while (( $(date +%s) < deadline )); do
|
||||
local state stage percent
|
||||
state="$(app_state)"
|
||||
[[ "$state" == "absent" ]] && {
|
||||
(( saw_stage == 1 )) || {
|
||||
echo "uninstall progress: no uninstall-stage observed before terminal absence" >&2
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
stage="$(app_uninstall_stage)"
|
||||
if [[ -n "$stage" ]]; then
|
||||
if ! percent="$(uninstall_stage_percent "$stage")"; then
|
||||
echo "uninstall progress: unparseable stage '$stage'" >&2
|
||||
return 1
|
||||
fi
|
||||
(( percent >= last_percent )) || {
|
||||
echo "uninstall progress regressed: ${percent}% after ${last_percent}% (stage '$stage')" >&2
|
||||
return 1
|
||||
}
|
||||
(( percent < 100 )) || {
|
||||
echo "uninstall progress reached ${percent}% before terminal absence (stage '$stage')" >&2
|
||||
return 1
|
||||
}
|
||||
saw_stage=1
|
||||
last_percent="$percent"
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
echo "wait_absent_with_truthful_uninstall_progress: $CASCADE_APP did not disappear within ${timeout}s (last='$(app_state)', stage='$(app_uninstall_stage)')" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
# Poll My Apps until CASCADE_APP reaches $1 (a state, or "absent").
|
||||
wait_app_state() {
|
||||
local target="$1" timeout="${2:-180}"
|
||||
@@ -102,7 +168,7 @@ wait_app_state() {
|
||||
[ "$saw_transitional" -eq 1 ] || echo "# note: no transitional install state observed (image likely cached)" >&3
|
||||
}
|
||||
|
||||
@test "uninstall ${CASCADE_APP} clears it from My Apps — NO ghost (#13)" {
|
||||
@test "uninstall ${CASCADE_APP} reports truthful progress and clears My Apps — NO ghost (#13)" {
|
||||
cascade_enabled || skip "ARCHY_ALLOW_CASCADE_DESTRUCTIVE not set"
|
||||
app_in_my_apps || skip "${CASCADE_APP} not installed (install step must have failed)"
|
||||
|
||||
@@ -114,8 +180,9 @@ wait_app_state() {
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
# …AND the My Apps entry must be GONE — the #13 ghost was the entry lingering
|
||||
# with a stale state / stuck uninstall stage. Poll: removal trails teardown.
|
||||
run wait_app_state absent 120
|
||||
# with a stale state / stuck uninstall stage. While polling, prove the backend
|
||||
# emits stage data the UI can render as monotonic, non-full progress.
|
||||
run wait_absent_with_truthful_uninstall_progress 120
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
# Belt-and-suspenders: the key is truly absent from package-data.
|
||||
@@ -148,6 +215,6 @@ wait_app_state() {
|
||||
[ "$status" -eq 0 ]
|
||||
run wait_for_container_status "$CASCADE_APP" absent 180
|
||||
[ "$status" -eq 0 ]
|
||||
run wait_app_state absent 120
|
||||
run wait_absent_with_truthful_uninstall_progress 120
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user