#!/usr/bin/env node import mysql from 'mysql2/promise'; import path from 'node:path'; import { assertPortalRuntimePath, hashArtifact } from '../release-gate/artifact.mjs'; import { createLocalGateStack } from '../release-gate/local-stack.mjs'; const ROOT = path.resolve(new URL('..', import.meta.url).pathname); const runtimeRoot = assertPortalRuntimePath(path.join(ROOT, '.runtime', 'portal'), { repoRoot: ROOT }); const artifactBefore = await hashArtifact(runtimeRoot); const runId = `cold-${new Date().toISOString().replace(/\D/g, '').slice(0, 14)}`; const port = Number(process.env.MEMIND_RELEASE_GATE_COLD_PORT ?? 19084); const stack = await createLocalGateStack({ root: ROOT, runId, port, portalRoot: runtimeRoot, nodeEnv: 'production', runtimeProfile: 'production', }); try { const firstStatus = await fetch(`${stack.baseUrl}/auth/status`, { signal: AbortSignal.timeout(5_000), }); if (!firstStatus.ok) throw new Error(`first health check failed: ${firstStatus.status}`); const connection = await mysql.createConnection(stack.mysqlUrl); let initializedTables; try { const [rows] = await connection.query( `SELECT COUNT(*) AS count FROM information_schema.tables WHERE table_schema = DATABASE()`, ); initializedTables = Number(rows[0]?.count ?? 0); } finally { await connection.end(); } if (initializedTables < 10) { throw new Error(`database initialization is incomplete: ${initializedTables} tables`); } await stack.restartPortal(); const restartedStatus = await fetch(`${stack.baseUrl}/auth/status`, { signal: AbortSignal.timeout(5_000), }); if (!restartedStatus.ok) throw new Error(`restart health check failed: ${restartedStatus.status}`); console.log('PASS REL-06 packaged runtime cold-starts with NODE_ENV=production'); console.log(`PASS REL-06 isolated database initialized ${initializedTables} tables and restart is idempotent`); } finally { await stack.cleanup(); const artifactAfter = await hashArtifact(runtimeRoot); if (artifactAfter.sha256 !== artifactBefore.sha256) { throw new Error( `packaged runtime mutated its own artifact during cold start: ${artifactBefore.sha256} -> ${artifactAfter.sha256}`, ); } }