fix: harden release gate and page delivery
Memind CI / Test, build, and release guards (push) Failing after 12m3s
Memind CI / Test, build, and release guards (push) Failing after 12m3s
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
#!/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}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user