Files
EasyFlow/easyflow-ui-admin/scripts/deploy/smoke-test.mjs
陈子默 cb06599dca test: 增加管理端部署契约验证
- 增加生产构建与 Nginx 镜像冒烟命令

- 校验根路径跳转、静态资源前缀和错误分享地址
2026-07-24 19:03:08 +08:00

93 lines
2.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { execFileSync } from 'node:child_process';
const image = process.env.EASYFLOW_FRONTEND_IMAGE || 'easyflow-frontend:0.1';
const containerName = `easyflow-frontend-smoke-${process.pid}`;
function docker(args) {
return execFileSync('docker', args, {
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'pipe'],
}).trim();
}
async function waitForServer(origin) {
let lastError;
for (let attempt = 0; attempt < 40; attempt += 1) {
try {
const response = await fetch(`${origin}/flow/`);
if (response.ok) {
return;
}
lastError = new Error(`HTTP ${response.status}`);
} catch (error) {
lastError = error;
}
await new Promise((resolve) => setTimeout(resolve, 250));
}
throw new Error(`Nginx 未在预期时间内启动: ${String(lastError)}`);
}
function assert(condition, message) {
if (!condition) {
throw new Error(message);
}
}
try {
docker([
'run',
'--detach',
'--rm',
'--publish',
'127.0.0.1::80',
'--name',
containerName,
image,
]);
const portBinding = docker(['port', containerName, '80/tcp'])
.split('\n')
.find((line) => line.startsWith('127.0.0.1:'));
const port = portBinding?.match(/:(\d+)$/)?.[1];
assert(port, `无法解析容器端口: ${portBinding || 'empty'}`);
const origin = `http://127.0.0.1:${port}`;
await waitForServer(origin);
const rootResponse = await fetch(`${origin}/`, { redirect: 'manual' });
assert(rootResponse.status === 302, `根路径状态异常: ${rootResponse.status}`);
const rootLocation = rootResponse.headers.get('location');
assert(
rootLocation && new URL(rootLocation, origin).pathname === '/flow/',
`根路径重定向异常: ${rootLocation}`,
);
const flowResponse = await fetch(`${origin}/flow/`);
const indexHtml = await flowResponse.text();
assert(flowResponse.ok, `/flow/ 状态异常: ${flowResponse.status}`);
assert(indexHtml.includes('<div id="app">'), '/flow/ 未返回应用入口');
const assetPath = indexHtml.match(/(?:src|href)="(\/flow\/[^"]+)"/)?.[1];
assert(assetPath, '构建产物未使用 /flow/ 静态资源前缀');
const assetResponse = await fetch(`${origin}${assetPath}`);
assert(assetResponse.ok, `静态资源状态异常: ${assetResponse.status}`);
const invalidRootShareResponse = await fetch(
`${origin}/share/knowledge?shareKey=smoke-test`,
);
assert(
invalidRootShareResponse.status === 404,
`根路径分享地址应返回 404实际为 ${invalidRootShareResponse.status}`,
);
console.log(
'部署冒烟通过:根路径重定向、/flow/ 入口、静态资源前缀和错误分享路径均符合预期。',
);
} finally {
try {
docker(['rm', '--force', containerName]);
} catch {
// 容器可能因 --rm 已自动删除。
}
}