35 lines
2.0 KiB
JavaScript
35 lines
2.0 KiB
JavaScript
#!/usr/bin/env node
|
|||
|
|
import { createHash } from 'node:crypto';
|
||
|
|
import { readFile } from 'node:fs/promises';
|
||
|
|
import { resolve } from 'node:path';
|
||
|
|
|
||
|
|
const base = (process.argv[2] || 'http://127.0.0.1:8080').replace(/\/$/, '');
|
||
|
|
const manifestPath = resolve(process.cwd(), 'asset-manifest.json');
|
||
|
|
const manifest = JSON.parse(await readFile(manifestPath, 'utf8'));
|
||
|
|
const assets = [...new Set([...(manifest.entrypoints || []), ...(manifest.publicAssets || [])])];
|
||
|
|
const failures = [];
|
||
|
|
const secretPattern = /(api[_-]?key|secret|token|password|private[_-]?key|authorization)\s*[:=]\s*["'][^"']+/i;
|
||
|
|
|
||
|
|
async function check(path, expected = {}) {
|
||
|
|
const response = await fetch(`${base}/${path}`);
|
||
|
|
const body = await response.text();
|
||
|
|
if (!response.ok) failures.push(`${path}: HTTP ${response.status}`);
|
||
|
|
if (expected.contentType && !response.headers.get('content-type')?.includes(expected.contentType)) failures.push(`${path}: unexpected content type`);
|
||
|
|
if (expected.marker && !body.includes(expected.marker)) failures.push(`${path}: missing marker ${expected.marker}`);
|
||
|
|
if (expected.integrity) {
|
||
|
|
const digest = `sha256-${createHash('sha256').update(body).digest('hex')}`;
|
||
|
|
if (digest !== expected.integrity) failures.push(`${path}: integrity mismatch`);
|
||
|
|
}
|
||
|
|
if (secretPattern.test(body)) failures.push(`${path}: possible hardcoded secret`);
|
||
|
|
console.log(`${response.ok ? 'PASS' : 'FAIL'} ${path} (${response.status})`);
|
||
|
|
}
|
||
|
|
|
||
|
|
const expectations = {
|
||
|
|
'index.html': { contentType: 'text/html', marker: 'ProspectOS' },
|
||
|
|
'health.html': { contentType: 'text/html', marker: 'Ready' },
|
||
|
|
'error.html': { contentType: 'text/html', marker: 'Something went wrong' },
|
||
|
|
healthz: { marker: 'ok' }
|
||
|
|
};
|
||
|
|
for (const asset of assets) await check(asset, { ...expectations[asset], integrity: manifest.integrity?.[asset] });
|
||
|
|
if (failures.length) { console.error(`\n${failures.length} deployment smoke check(s) failed`); for (const failure of failures) console.error(`- ${failure}`); process.exitCode = 1; } else console.log(`\nDeployment smoke checks passed for ${base}`);
|