#!/usr/bin/env node import { createHash } from "node:crypto"; import { execFileSync } from "node:child_process"; import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; const scriptDir = path.dirname(fileURLToPath(import.meta.url)); const repoRoot = path.join(scriptDir, "../.."); const baseUrl = process.env.TABULARRR_SMOKE_BASE_URL ?? "http://127.0.0.1:3000"; function run(command, args) { return execFileSync(command, args, { cwd: repoRoot, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], }).trim(); } function sha256(filePath) { return createHash("sha256") .update(fs.readFileSync(filePath)) .digest("hex"); } async function requirePage(route) { let lastError; for (let attempt = 1; attempt <= 30; attempt += 1) { try { const response = await fetch(`${baseUrl}${route}`, { redirect: "follow", signal: AbortSignal.timeout(20_000), }); if (!response.ok) { throw new Error(`${route} returned HTTP ${response.status}`); } const html = await response.text(); if (!html.includes("Tabularrr")) { throw new Error(`${route} did not render Tabularrr branding`); } return html; } catch (error) { lastError = error; if (attempt < 30) { await new Promise((resolve) => setTimeout(resolve, 1_000)); } } } throw new Error( `${route} was not ready after 30 attempts: ${lastError?.message ?? lastError}`, ); } const runningServices = new Set( run("docker", ["compose", "ps", "--status", "running", "--services"]) .split(/\r?\n/) .filter(Boolean), ); for (const service of [ "mike-postgres", "python-service", "backend", "frontend", ]) { if (!runningServices.has(service)) { throw new Error(`Docker service ${service} is not running`); } } const loginHtml = await requirePage("/login"); await requirePage("/signup"); if (!loginHtml.includes("Tabularrr - AI Legal Platform")) { throw new Error("The runtime page title is not the canonical Tabularrr title"); } const pythonTitle = run("docker", [ "compose", "exec", "-T", "python-service", "python", "-c", "from main import app; print(app.title)", ]); if (pythonTitle !== "Tabularrr Playbook Review Service") { throw new Error(`Unexpected Python service title: ${pythonTitle}`); } const containerManifestSha = run("docker", [ "compose", "exec", "-T", "python-service", "python", "-c", "from inference.config import manifest_sha256; print(manifest_sha256())", ]); const hostManifestSha = sha256( path.join(repoRoot, "backend/config/inference.manifest.json"), ); if (containerManifestSha !== hostManifestSha) { throw new Error( `Python manifest SHA mismatch: container=${containerManifestSha} host=${hostManifestSha}`, ); } console.log("TABULARRR_RUNTIME_SMOKE_PASSED"); console.log(`BASE_URL=${baseUrl}`); console.log(`PYTHON_MANIFEST_SHA256=${containerManifestSha}`);