Strengthen release verification gates
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
import { spawn } from "node:child_process";
|
||||
import { spawn, spawnSync } from "node:child_process";
|
||||
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
|
||||
const command = process.argv[2];
|
||||
const args = process.argv.slice(3);
|
||||
@@ -7,9 +10,12 @@ if (!command) {
|
||||
throw new Error("usage: node scripts/smoke-web-search.mjs <command> [args...]");
|
||||
}
|
||||
|
||||
const tmpDir = mkdtempSync(join(tmpdir(), "context-kit-web-search-smoke-"));
|
||||
const cidFile = join(tmpDir, "container.cid");
|
||||
|
||||
const child = spawn(command, args, {
|
||||
cwd: new URL("..", import.meta.url).pathname,
|
||||
env: process.env,
|
||||
env: { ...process.env, CONTEXT_KIT_DOCKER_CIDFILE: cidFile },
|
||||
stdio: ["pipe", "pipe", "pipe"]
|
||||
});
|
||||
|
||||
@@ -19,18 +25,28 @@ let stdoutBuffer = "";
|
||||
let stderrBuffer = "";
|
||||
let childExited = false;
|
||||
|
||||
child.once("exit", () => {
|
||||
child.once("exit", (code, signal) => {
|
||||
childExited = true;
|
||||
if (pending.size > 0) {
|
||||
const error = new Error(`MCP child exited before responding (code=${code}, signal=${signal}). stderr: ${stderrBuffer.slice(-2000)}`);
|
||||
for (const { reject } of pending.values()) reject(error);
|
||||
pending.clear();
|
||||
}
|
||||
});
|
||||
|
||||
function stopChild() {
|
||||
return new Promise(resolve => {
|
||||
if (childExited) {
|
||||
stopContainer();
|
||||
rmSync(tmpDir, { recursive: true, force: true });
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
child.stdin.end();
|
||||
const stopTimer = setTimeout(() => {
|
||||
stopContainer();
|
||||
}, 1000);
|
||||
const termTimer = setTimeout(() => {
|
||||
if (!childExited) child.kill("SIGTERM");
|
||||
}, 3000);
|
||||
@@ -39,13 +55,23 @@ function stopChild() {
|
||||
}, 6000);
|
||||
|
||||
child.once("exit", () => {
|
||||
stopContainer();
|
||||
clearTimeout(stopTimer);
|
||||
clearTimeout(termTimer);
|
||||
clearTimeout(killTimer);
|
||||
rmSync(tmpDir, { recursive: true, force: true });
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function stopContainer() {
|
||||
if (!existsSync(cidFile)) return;
|
||||
const containerId = readFileSync(cidFile, "utf8").trim();
|
||||
if (!containerId) return;
|
||||
spawnSync("docker", ["stop", containerId], { stdio: "ignore" });
|
||||
}
|
||||
|
||||
const timeout = setTimeout(async () => {
|
||||
await stopChild();
|
||||
console.error(`MCP smoke timed out. stderr: ${stderrBuffer.slice(-2000)}`);
|
||||
@@ -79,6 +105,9 @@ child.stdout.on("data", chunk => {
|
||||
});
|
||||
|
||||
function request(method, params = {}) {
|
||||
if (childExited) {
|
||||
return Promise.reject(new Error(`MCP child already exited. stderr: ${stderrBuffer.slice(-2000)}`));
|
||||
}
|
||||
const id = nextId++;
|
||||
child.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", id, method, params })}\n`);
|
||||
return new Promise((resolve, reject) => pending.set(id, { resolve, reject }));
|
||||
|
||||
Reference in New Issue
Block a user