From 8aea38fc673b81fe4ff35fcaf24d1ee917cc5244 Mon Sep 17 00:00:00 2001 From: Lotus CI Date: Tue, 20 Oct 2026 02:28:52 -0400 Subject: [PATCH] feat(cinny-deploy): fail and alert when a deployed page references missing files After copying, check every script/stylesheet the app and call pages reference (src/href in both index.html files) exists in the webroot. If any is missing, log it, post an alert with the upstream checker's Matrix credentials (/etc/cinny-monitor.env, best effort) and exit 1. This would have caught the 2026-10-20 call-page outage at deploy time. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5 --- cinny/lotus_deploy.sh | 44 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/cinny/lotus_deploy.sh b/cinny/lotus_deploy.sh index f7adeeb..4829048 100755 --- a/cinny/lotus_deploy.sh +++ b/cinny/lotus_deploy.sh @@ -177,6 +177,50 @@ for dir in assets public/element-call/assets; do find "$WEBROOT/$dir" -type f -mtime +14 -delete done +# Every script/stylesheet the app and call pages reference must exist in the +# webroot. 2026-10-20: the call page's index.html pointed at scripts the deploy +# never copied and calls failed to load; this check would have caught it. +missing_assets() { # + grep -oE '(src|href)="[^"]+\.(js|css)"' "$1" | sed -E 's/^(src|href)="//; s/"$//' | + while read -r ref; do + case "$ref" in + http://*|https://*|//*) continue ;; + /*) path="$WEBROOT$ref" ;; + *) path="$2/${ref#./}" ;; + esac + [ -f "$path" ] || echo "$ref" + done +} +deploy_alert() { # best effort: the upstream checker's Matrix credentials + [ -r /etc/cinny-monitor.env ] || return 0 + ( + set -a + # shellcheck source=/dev/null + source /etc/cinny-monitor.env + set +a + _ALERT="$1" python3 - <<'PYEOF' +import json, os, time, urllib.parse, urllib.request +server = os.environ.get("MATRIX_SERVER", "").rstrip("/") +room, token = os.environ.get("MATRIX_ROOM", ""), os.environ.get("MATRIX_TOKEN", "") +if server and room and token: + url = f"{server}/_matrix/client/v3/rooms/{urllib.parse.quote(room, safe='')}/send/m.room.message/deploy{int(time.time() * 1000)}" + req = urllib.request.Request(url, method="PUT", data=json.dumps({"msgtype": "m.text", "body": os.environ["_ALERT"]}).encode(), + headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"}) + try: + urllib.request.urlopen(req, timeout=10) + except Exception as exc: + print(f"alert failed: {exc}") +PYEOF + ) || true +} +MISSING=$(missing_assets "$WEBROOT/index.html" "$WEBROOT"; missing_assets "$WEBROOT/public/element-call/index.html" "$WEBROOT/public/element-call") +if [ -n "$MISSING" ]; then + echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: deployed pages reference missing files:" + echo "$MISSING" + deploy_alert "⚠️ Lotus Chat deploy ($VITE_APP_VERSION): the live pages reference files that are not on the server, so the app or calls may not load: $(echo "$MISSING" | tr '\n' ' ')" + exit 1 +fi + echo "[$(date '+%Y-%m-%d %H:%M:%S')] ===== Deploy complete ($VITE_APP_VERSION) =====" # A trigger arrived while we were deploying: release the lock and run once more