Compare commits

..
Author SHA1 Message Date
Lotus CIandClaude Opus 5.5 8aea38fc67 feat(cinny-deploy): fail and alert when a deployed page references missing files
Lint / No secrets in webhook configs (pull_request) Successful in 24s
Lint / Landing page is rendered (matrix (pull_request) Successful in 18s
Lint / Python (ruff) (pull_request) Successful in 10s
Lint / Python deps (pip-audit) (pull_request) Successful in 1m0s
Lint / Secret scan (gitleaks) (pull_request) Successful in 8s
Lint / Shell (shellcheck) (push) Successful in 15s
Lint / JS (eslint) (push) Successful in 16s
Lint / No secrets in webhook configs (push) Successful in 10s
Lint / Landing page is rendered (matrix (push) Successful in 9s
Lint / Python (ruff) (push) Successful in 10s
Lint / Python deps (pip-audit) (push) Successful in 1m17s
Lint / Shell (shellcheck) (pull_request) Successful in 13s
Lint / JS (eslint) (pull_request) Successful in 7s
Lint / Secret scan (gitleaks) (push) Successful in 5s
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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-20 02:28:52 -04:00
jared 963bc87c54 Merge pull request 'fix(cinny-deploy): the call page's scripts are deployed again (regression from #30)' (#38) from fix/deploy-call-assets into main
Lint / Shell (shellcheck) (push) Successful in 16s
Lint / JS (eslint) (push) Successful in 13s
Lint / No secrets in webhook configs (push) Successful in 10s
Lint / Landing page is rendered (matrix (push) Successful in 8s
Lint / Python (ruff) (push) Successful in 12s
Lint / Python deps (pip-audit) (push) Successful in 1m31s
Lint / Secret scan (gitleaks) (push) Successful in 7s
2026-10-20 01:55:37 -04:00
Lotus CIandClaude Opus 5.5 85c58d5ed0 fix(cinny-deploy): the call page's scripts are deployed again
Lint / No secrets in webhook configs (pull_request) Successful in 11s
Lint / Landing page is rendered (matrix (pull_request) Successful in 8s
Lint / Python (ruff) (pull_request) Successful in 7s
Lint / Python deps (pip-audit) (pull_request) Successful in 44s
Lint / Secret scan (gitleaks) (pull_request) Successful in 9s
Lint / Shell (shellcheck) (push) Successful in 14s
Lint / JS (eslint) (push) Successful in 9s
Lint / No secrets in webhook configs (push) Successful in 6s
Lint / Landing page is rendered (matrix (push) Successful in 5s
Lint / Python (ruff) (push) Successful in 7s
Lint / Python deps (pip-audit) (push) Successful in 40s
Lint / Secret scan (gitleaks) (push) Successful in 6s
Lint / Shell (shellcheck) (pull_request) Successful in 14s
Lint / JS (eslint) (pull_request) Successful in 10s
#30 added `rsync --exclude assets/` to keep old app assets, but an
unanchored exclude matches every directory named assets, including
public/element-call/assets/. Each deploy then updated the call page's
index.html but not its hashed scripts, so after the lotus.28 deploy the
call page requested files that did not exist (66 x 404 from 00:05 on
2026-10-20 until the assets were copied in by hand).

The excludes are now anchored (/assets/, /public/element-call/assets/), and
both asset directories get the same treatment: copied without --delete,
pruned after 14 days, so an open call page keeps its scripts across a
deploy. config.json stays unanchored on purpose (the production call
config lives at public/element-call/config.json).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-20 00:19:47 -04:00
jared 8e5cdf50b5 Merge pull request 'feat(voice-limit-guard): enforce the limit at connect time too (#25)' (#37) from feat/voice-limit-connect-time into main
Lint / Shell (shellcheck) (push) Successful in 8s
Lint / JS (eslint) (push) Successful in 8s
Lint / No secrets in webhook configs (push) Successful in 11s
Lint / Landing page is rendered (matrix (push) Successful in 10s
Lint / Python (ruff) (push) Successful in 12s
Lint / Python deps (pip-audit) (push) Successful in 1m9s
Lint / Secret scan (gitleaks) (push) Successful in 4s
2026-10-19 23:34:04 -04:00
+56 -3
View File
@@ -164,9 +164,62 @@ echo "[$(date '+%Y-%m-%d %H:%M:%S')] Deploying to $WEBROOT..."
# still holding an older index.html (or service-worker precache) asks for its
# assets/index-<old hash>.js, and deleting them on every deploy broke the app
# for those users until their cached shell expired. Prune after 14 days.
rsync -a --delete --exclude config.json --exclude assets/ dist/ "$WEBROOT/"
rsync -a dist/assets/ "$WEBROOT/assets/"
find "$WEBROOT/assets" -type f -mtime +14 -delete
# The asset excludes are ANCHORED (leading /): an unanchored `assets/` also
# matched public/element-call/assets/, so the call page's index.html was
# updated while its hashed scripts never were, and calls failed to load.
# config.json stays unanchored on purpose: public/element-call/config.json is
# the production call config too.
rsync -a --delete --exclude config.json \
--exclude /assets/ --exclude /public/element-call/assets/ dist/ "$WEBROOT/"
for dir in assets public/element-call/assets; do
mkdir -p "$WEBROOT/$dir"
rsync -a "dist/$dir/" "$WEBROOT/$dir/"
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() { # <index.html> <its directory>
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) ====="