2f240e7500
Shared paths like db.mjs were pulling PAGE/DATA live agent suites into every hotfix. Keep those cases for actual page-data changes, resume passed suites on the same artifact, and fail fast on Docker/port issues instead of rerunning 100+ scenarios. Co-authored-by: Cursor <cursoragent@cursor.com>
80 lines
2.3 KiB
JavaScript
80 lines
2.3 KiB
JavaScript
import fs from 'node:fs';
|
|
import net from 'node:net';
|
|
import { spawnSync } from 'node:child_process';
|
|
|
|
export const GATE_SUITE_PORTS = Object.freeze({
|
|
'runtime-sanitized-data-upgrade': 19085,
|
|
'page-data-product-scenarios': 19086,
|
|
'page-content-delivery-scenarios': 19087,
|
|
'runtime-production-homolog-cold-start': 19081,
|
|
});
|
|
|
|
const DOCKER_SOCKET_CANDIDATES = [
|
|
process.env.DOCKER_HOST?.replace(/^unix:\/\//, ''),
|
|
`${process.env.HOME ?? ''}/.docker/run/docker.sock`,
|
|
'/var/run/docker.sock',
|
|
].filter(Boolean);
|
|
|
|
export function dockerSocketExists() {
|
|
return DOCKER_SOCKET_CANDIDATES.some((socketPath) => {
|
|
try {
|
|
return fs.existsSync(socketPath);
|
|
} catch {
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
|
|
export function assertDockerDaemonAvailable() {
|
|
if (!dockerSocketExists()) {
|
|
throw new Error(
|
|
'Release gate REL-11 needs Docker; start Docker Desktop and retry. Missing docker.sock.',
|
|
);
|
|
}
|
|
const result = spawnSync('docker', ['info'], {
|
|
encoding: 'utf8',
|
|
timeout: 15_000,
|
|
});
|
|
if (result.status !== 0) {
|
|
throw new Error(
|
|
`Release gate REL-11 needs a running Docker daemon: ${(result.stderr || result.error?.message || 'docker info failed').trim().slice(0, 500)}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
export function assertLoopbackPortAvailable(port, host = '127.0.0.1') {
|
|
return new Promise((resolve, reject) => {
|
|
const server = net.createServer();
|
|
server.once('error', (error) => {
|
|
if (error?.code === 'EADDRINUSE') {
|
|
reject(new Error(
|
|
`Release gate port ${host}:${port} is already in use; stop the stale local gate process before retrying`,
|
|
));
|
|
return;
|
|
}
|
|
reject(error);
|
|
});
|
|
server.once('listening', () => {
|
|
server.close((closeError) => {
|
|
if (closeError) reject(closeError);
|
|
else resolve();
|
|
});
|
|
});
|
|
server.listen(port, host);
|
|
});
|
|
}
|
|
|
|
export async function preflightImpactSuites(suites) {
|
|
const ports = [...new Set(
|
|
suites
|
|
.map((suite) => GATE_SUITE_PORTS[suite.id])
|
|
.filter((port) => Number.isInteger(port)),
|
|
)].sort((left, right) => left - right);
|
|
for (const port of ports) {
|
|
await assertLoopbackPortAvailable(port);
|
|
}
|
|
if (suites.some((suite) => suite.id === 'runtime-linux-dependency-closure')) {
|
|
assertDockerDaemonAvailable();
|
|
}
|
|
}
|