build: pre-deploy HTML inline-script syntax guard

A missing brace in a home.html inline <script> caused an app-wide login
outage (the whole block failed to parse, so boot never ran). Nothing in the
deploy path checked HTML syntax. Add tools/check-syntax.js: parses (never
runs) every inline <script> in server/public/*.html with vm and exits non-zero
on any syntax error, reporting the file + line.

Wired in two places:
- Dockerfile RUN after COPY server/ ./ — a syntax error now FAILS the build,
  so it can't deploy.
- redeploy.sh pre-flight — fast local feedback before triggering the remote
  build.

Verified: passes on current pages (16 blocks / 9 files); fails with the exact
location when a brace is removed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
SravanandClaude Opus 4.8 committed 2026-11-03 21:33:01 +05:30
1 parent c9bb9c75d1
commit a1f7eef28a
4 files changed
+78 -1

No files matched your search

+5
View File
@@ -16,6 +16,11 @@ RUN npm install --omit=dev --no-audit --no-fund
# App source
COPY server/ ./
# Pre-deploy guard: FAIL the build if any inline <script> in the served HTML pages has a JS syntax error. A
# broken inline script takes down the whole page (one missing brace in home.html once caused an app-wide login
# outage). This turns that into a failed build instead of a production incident. See tools/check-syntax.js.
RUN node tools/check-syntax.js
# Served HTTP port (NPM terminates TLS and proxies here). The DB is Postgres (DATABASE_URL, set via .env);
# the /data volume holds uploads / recordings / transcripts / downloads (see docker-compose.yml).
ENV PORT=8090
+6 -1
View File
@@ -1,6 +1,6 @@
# Tech Stack — BizGaze Connect
> Living document. **Last updated: 2026-11-03** (rev 4). Update this file whenever a dependency, platform, service, or
> Living document. **Last updated: 2026-11-03** (rev 5). Update this file whenever a dependency, platform, service, or
> tool is added/removed/version-bumped. See [Maintaining this file](#maintaining-this-file) and the
> [Changelog](#changelog) at the bottom.
@@ -203,6 +203,11 @@ Bump the **Last updated** date at the top and add a line to the Changelog below.
## Changelog
- **2026-11-03 (rev 5)** — Reliability: Postgres pool safety timeouts (`connectionTimeoutMillis`,
`statement_timeout`, `idle_in_transaction_session_timeout`, max 10→20) so a saturated pool fails fast instead
of hanging forever; and a **pre-deploy HTML syntax guard** (`server/tools/check-syntax.js`) run in the Docker
build and `redeploy.sh` — a JS syntax error in an inline `<script>` now fails the build instead of reaching
production (it had caused an app-wide login hang).
- **2026-11-03 (rev 4)** — Android native call **video** (Increment 2b): `CallVideo` renders camera/screen tiles
with LiveKit `TextureViewRenderer` hole-punched behind a transparent WebView; `CallMedia` gains camera
publish/flip + track lookup; new `ANDROID_NATIVE_VIDEO` server flag. Also fixed the white meeting background
+9
View File
@@ -39,5 +39,14 @@ if [ -z "$PW" ]; then
read -rsp "Server password for $USER@$HOST: " PW; echo
fi
# Pre-flight: catch inline-<script> syntax errors in the served HTML BEFORE triggering a remote build (fast
# local feedback — the Docker build runs the same check authoritatively and would fail anyway). A syntax error
# in a big inline script breaks the whole page (it once caused an app-wide login outage). Skipped if node isn't
# on PATH. Checks the local tree, which matches origin/master once you've pushed.
if command -v node >/dev/null 2>&1; then
echo "==> Checking HTML inline-script syntax …"
node "$DIR/server/tools/check-syntax.js" || { echo "ERROR: HTML syntax check failed — fix before deploying (the build would fail too)."; exit 1; }
fi
echo "==> Triggering deploy on $USER@$HOST ($APPDIR) …"
exec "$PLINK" -ssh -batch -hostkey "$HOSTKEY" -P "$PORT" -pw "$PW" "$USER@$HOST" "cd $APPDIR && bash deploy.sh $*"
+58
View File
@@ -0,0 +1,58 @@
#!/usr/bin/env node
// Pre-deploy syntax guard for the served HTML pages.
//
// WHY: our pages carry large INLINE <script> blocks. A single JavaScript syntax error in one block makes the
// WHOLE block fail to parse — every function/handler it defines becomes undefined. That is exactly what caused
// an app-wide login outage (home.html's `callConnected` listener was missing one `}`: the boot code never ran,
// so after login the splash spun forever). The browser catches it instantly; our deploy did not. This script
// turns that class of bug into a FAILED BUILD (exit 1) instead of a production outage.
//
// It parses — but never executes — every inline <script> in server/public/*.html with Node's `vm`, so it only
// checks SYNTAX (browser globals like `document` are irrelevant to parsing). Runs in the Docker build (see
// Dockerfile, right after `COPY server/ ./`) and locally from redeploy.sh for fast feedback.
const fs = require('fs');
const path = require('path');
const vm = require('vm');
const dir = path.join(__dirname, '..', 'public');
let files;
try {
files = fs.readdirSync(dir).filter((f) => f.toLowerCase().endsWith('.html'));
} catch (e) {
console.error('[check-syntax] cannot read ' + dir + ': ' + e.message);
process.exit(1);
}
// Inline <script> … </script> (skip ones with a src= attribute — those are external files, nothing inline).
const re = /<script\b([^>]*)>([\s\S]*?)<\/script\s*>/gi;
let errors = 0;
let blocks = 0;
for (const f of files) {
const html = fs.readFileSync(path.join(dir, f), 'utf8');
re.lastIndex = 0;
let m;
while ((m = re.exec(html))) {
if (/\bsrc\s*=/i.test(m[1] || '')) continue; // external script
blocks++;
const code = m[2];
// File line where this block's body starts, so the reported line is file-relative (not block-relative).
const openTagEnd = m.index + m[0].indexOf('>') + 1;
const startLine = html.slice(0, openTagEnd).split('\n').length - 1; // 0-indexed offset
try {
new vm.Script(code, { filename: f, lineOffset: startLine });
} catch (e) {
errors++;
const loc = (String(e.stack || '').split('\n')[0] || '').trim(); // e.g. "home.html:4398"
console.error('[check-syntax] ' + f + ' — ' + (e.message || 'syntax error') +
(loc && /:\d+$/.test(loc) ? (' @ ' + loc) : (' (inline <script> near line ' + (startLine + 1) + ')')));
}
}
}
if (errors) {
console.error('[check-syntax] FAILED: ' + errors + ' inline <script> block(s) with syntax errors. Aborting deploy.');
process.exit(1);
}
console.log('[check-syntax] OK: ' + blocks + ' inline <script> block(s) parsed across ' + files.length + ' HTML file(s).');
process.exit(0);