mirror of
https://github.com/devkitshq/notifkit.git
synced 2026-10-19 18:24:52 +02:00
fix(ci): fix cross-platform test spawning, redis disconnect handling, and ci step guards
- Fix worker spawning in tests/chaos/crash.test.ts to support Linux runners - Gracefully handle closed connections during RedisClient.disconnect() - Detach SIGINT/SIGTERM process listeners on NotifkitServer.stop() - Only run coverage badge generation if the test step was not skipped
This commit is contained in:
@@ -50,12 +50,14 @@ jobs:
|
||||
# though they cannot locally. This is the only place the real coverage
|
||||
# number exists.
|
||||
- name: Test
|
||||
id: test
|
||||
run: npm test
|
||||
|
||||
- name: Generate coverage badge
|
||||
# Runs even when the suite fails its thresholds, so the badge reports
|
||||
# what coverage actually is rather than going stale on a red build.
|
||||
if: always()
|
||||
# Only runs if the test step was actually executed (not skipped due to earlier failure).
|
||||
if: always() && steps.test.outcome != 'skipped'
|
||||
id: badge
|
||||
run: node scripts/coverage-badge.mjs --out badge/coverage.json
|
||||
|
||||
|
||||
+12
-1
@@ -58,9 +58,20 @@ export class RedisClient {
|
||||
}
|
||||
|
||||
async disconnect(): Promise<void> {
|
||||
if (this.isClosing) return;
|
||||
this.isClosing = true;
|
||||
this.logger?.info("disconnecting redis");
|
||||
await this.native.quit();
|
||||
try {
|
||||
if (this.native.status !== "end" && this.native.status !== "close") {
|
||||
await this.native.quit();
|
||||
}
|
||||
} catch {
|
||||
try {
|
||||
this.native.disconnect();
|
||||
} catch {
|
||||
// ignore errors on forced disconnect
|
||||
}
|
||||
}
|
||||
this.logger?.info("redis disconnected");
|
||||
}
|
||||
}
|
||||
|
||||
+14
-4
@@ -31,6 +31,8 @@ export class NotifkitServer extends EventEmitter {
|
||||
private redisContainer: any = null;
|
||||
private eventCleanupFns: (() => void)[] = [];
|
||||
private signalHandlersAttached = false;
|
||||
private sigintHandler?: () => void;
|
||||
private sigtermHandler?: () => void;
|
||||
private logger: Logger;
|
||||
|
||||
constructor(options: NotifkitOptions) {
|
||||
@@ -192,12 +194,14 @@ export class NotifkitServer extends EventEmitter {
|
||||
};
|
||||
|
||||
if (!this.signalHandlersAttached) {
|
||||
process.once("SIGINT", () => {
|
||||
this.sigintHandler = () => {
|
||||
void handleSignal("SIGINT");
|
||||
});
|
||||
process.once("SIGTERM", () => {
|
||||
};
|
||||
this.sigtermHandler = () => {
|
||||
void handleSignal("SIGTERM");
|
||||
});
|
||||
};
|
||||
process.once("SIGINT", this.sigintHandler);
|
||||
process.once("SIGTERM", this.sigtermHandler);
|
||||
this.signalHandlersAttached = true;
|
||||
}
|
||||
|
||||
@@ -205,6 +209,12 @@ export class NotifkitServer extends EventEmitter {
|
||||
}
|
||||
|
||||
async stop() {
|
||||
if (this.signalHandlersAttached) {
|
||||
if (this.sigintHandler) process.removeListener("SIGINT", this.sigintHandler);
|
||||
if (this.sigtermHandler) process.removeListener("SIGTERM", this.sigtermHandler);
|
||||
this.signalHandlersAttached = false;
|
||||
}
|
||||
|
||||
// Cleanup event listeners to prevent memory leaks
|
||||
for (const cleanup of this.eventCleanupFns) {
|
||||
cleanup();
|
||||
|
||||
@@ -26,16 +26,23 @@ describe("Crash Testing (Chaos Monkey)", () => {
|
||||
|
||||
const spawnWorker = (type: string, id: string) => {
|
||||
logger.info(`Spawning worker: ${type} (${id})`);
|
||||
const cp = spawn("cmd", ["/c", "npx", "--no-install", "tsx", "tests/chaos/worker-runner.ts"], {
|
||||
env: {
|
||||
...process.env,
|
||||
WORKER_TYPE: type,
|
||||
DATABASE_URL: dbUrl,
|
||||
REDIS_URL: redisUrl,
|
||||
LOG_LEVEL: "silent",
|
||||
const isWin = process.platform === "win32";
|
||||
const cp = spawn(
|
||||
isWin ? "cmd.exe" : "npx",
|
||||
isWin
|
||||
? ["/c", "npx", "--no-install", "tsx", "tests/chaos/worker-runner.ts"]
|
||||
: ["--no-install", "tsx", "tests/chaos/worker-runner.ts"],
|
||||
{
|
||||
env: {
|
||||
...process.env,
|
||||
WORKER_TYPE: type,
|
||||
DATABASE_URL: dbUrl,
|
||||
REDIS_URL: redisUrl,
|
||||
LOG_LEVEL: "silent",
|
||||
},
|
||||
stdio: "ignore", // ignore output to keep logs clean
|
||||
},
|
||||
stdio: "ignore", // ignore output to keep logs clean
|
||||
});
|
||||
);
|
||||
|
||||
cp.on("exit", (code, signal) => {
|
||||
logger.info(`Worker ${type} (${id}) exited with signal ${signal} (code ${code})`);
|
||||
|
||||
Reference in New Issue
Block a user