diff --git a/scripts/deploy-remote.sh b/scripts/deploy-remote.sh index 273733a..c1216ac 100755 --- a/scripts/deploy-remote.sh +++ b/scripts/deploy-remote.sh @@ -177,6 +177,17 @@ add_pending_services() { if [[ "$status" != deployed ]]; then # A pending service was intentionally skipped or its handler # failed. Retry it even when the checkout has not advanced. + # But a pending entry for a service RETIRED from this target can + # never be deployable: retrying it fails the whole run before + # the e2e gate (the frank-default-sightsound lockout, found + # 2026-09-17). Drop such entries into the host trash instead. + if ! service_is_allowed "$service"; then + local trash="$HOME/.AGENTTRASH/$(date +%Y%m%d)-retired-deploy-state" + mkdir -p "$trash" + mv -- "$state_file" "$trash/$service" + echo "WARN: $service is retired on $TARGET; dropped its stale $status state to $trash" >&2 + continue + fi SERVICES+=("$service") continue fi diff --git a/tests/deployment_flow.bats b/tests/deployment_flow.bats index f39bca2..c20c58a 100644 --- a/tests/deployment_flow.bats +++ b/tests/deployment_flow.bats @@ -98,3 +98,29 @@ load helpers grep -qF "dankuser ${hash}" <<< "$rendered" ! grep -qF '$2a$14$$2a$14$' <<< "$rendered" } + +@test "the pending pass prunes retired-service state instead of blocking the run" { + # Regression: a pending state entry for frank-default-sightsound (an + # endpoint retired 2026-09-11) made every --pending run exit 2 at the + # dispatcher before the Playwright e2e gate could execute. The pending + # pass must drop entries the target no longer allows into the trash and + # still deploy the services that remain. + local sandbox="$BATS_TEST_TMPDIR/st" + mkdir -p "$sandbox" + printf 'revision=deadbeef\nstatus=pending\n' > "$sandbox/frank-default-sightsound" + printf 'revision=deadbeef\nstatus=pending\n' > "$sandbox/searxng" + run env HOME="$BATS_TEST_TMPDIR" STATE_DIR="$sandbox" bash -c ' + set -euo pipefail + SERVICES=() + REVISION=cafebabe + TARGET=dankclaw + service_is_allowed() { [[ "$1" == searxng ]]; } + eval "$(sed -n "/^state_revision()/,/^}/p" "$1/scripts/deploy-remote.sh"; sed -n "/^state_status()/,/^}/p" "$1/scripts/deploy-remote.sh"; sed -n "/^add_pending_services()/,/^}/p" "$1/scripts/deploy-remote.sh")" + add_pending_services >/dev/null 2>&1 + printf "%s\n" "${SERVICES[@]:-}" + ' _ "$REPO_ROOT" + [ "$status" -eq 0 ] + [ "$output" = "searxng" ] + [ ! -e "$sandbox/frank-default-sightsound" ] + [ -e "$BATS_TEST_TMPDIR/.AGENTTRASH/$(date +%Y%m%d)-retired-deploy-state/frank-default-sightsound" ] +}