From f09a5bc442855e4537a5ad420f6d5946954fd9b6 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Wed, 14 Aug 2024 14:23:15 +0200 Subject: [PATCH] Add start command to avoid make subgraphs (#62) --- makefile | 2 +- src/cli.ts | 104 +++++++++++++++--- .../requires-requires/d.subgraph.ts | 2 +- src/test-suites/requires-requires/test.ts | 10 +- 4 files changed, 96 insertions(+), 22 deletions(-) diff --git a/makefile b/makefile index 4d1be09..f0a5d95 100644 --- a/makefile +++ b/makefile @@ -16,7 +16,7 @@ endef define RUN_GATEWAY run-$(1): - (cd gateways/$(1) && ./run.sh $(TEST_SUITE)) + npm start -- start --test $(TEST_SUITE) --cwd ./gateways/$(1) --run-script ./run.sh --graphql $(shell jq -r .graphql ./gateways/$(1)/gateway.json) --healthcheck $(shell jq -r .health ./gateways/$(1)/gateway.json) endef install: diff --git a/src/cli.ts b/src/cli.ts index ef9d618..28b1e97 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -36,7 +36,7 @@ function resolvePath( argv: { cwd: string; }, - path: string, + path: string ) { if (path.startsWith("/")) { return path; @@ -47,7 +47,7 @@ function resolvePath( yargs(hideBin(process.argv)) .scriptName("graphql-federation-audit") .epilogue( - "for more information, find our manual at https://github.com/the-guild-org/federation-compatibility", + "for more information, find our manual at https://github.com/the-guild-org/federation-compatibility" ) .version(readVersion() ?? "local") .recommendCommands() @@ -68,7 +68,7 @@ yargs(hideBin(process.argv)) async (argv) => { await serve(argv.port); console.log("Server started on port", argv.port); - }, + } ) .command( "supergraph", @@ -87,7 +87,7 @@ yargs(hideBin(process.argv)) }, async (argv) => { const res = await fetch( - `http://localhost:${argv.port}/${argv.test}/supergraph`, + `http://localhost:${argv.port}/${argv.test}/supergraph` ); if (!res.ok) { @@ -99,7 +99,7 @@ yargs(hideBin(process.argv)) writeFileSync(resolvePath(argv, "supergraph.graphql"), await res.text()); process.exit(0); - }, + } ) .command( "subgraphs", @@ -133,7 +133,81 @@ yargs(hideBin(process.argv)) writeFileSync(resolvePath(argv, "subgraphs.json"), await res.text()); process.exit(0); + } + ) + .command( + "start", + "start a gateway for a requested test group", + (yargs) => { + return yargs + .option("test", { + describe: "Test group id", + type: "string", + }) + .option("run-script", { + describe: "Path to a bash script to run before each test", + type: "string", + }) + .option("graphql", { + describe: "GraphQL endpoint serving the supergraph", + type: "string", + }) + .option("healthcheck", { + describe: "Health check endpoint", + type: "string", + }) + .option("port", { + describe: "Port to bind on", + default: defaultPort, + }) + .demandOption("test") + .demandOption("graphql") + .demandOption("healthcheck") + .demandOption("run-script"); }, + async (argv) => { + const abortSignal = new AbortController(); + process.once("SIGINT", () => { + if (!abortSignal.signal.aborted) { + abortSignal.abort(); + } + }); + process.once("SIGTERM", () => { + if (!abortSignal.signal.aborted) { + abortSignal.abort(); + } + }); + + const port = argv.port ?? (await getPort()); + await serve(port); + + process.stdout.write("\n"); + + await killPortProcess(readPort(argv.graphql)).catch(() => {}); + + const gatewayExit = Promise.withResolvers(); + let gatewayExited = false; + const gateway = spawn("sh", [argv.runScript, argv.test], { + signal: abortSignal.signal, + stdio: "inherit", + cwd: dirname(resolvePath(argv, argv.runScript)), + }); + + gateway.on("error", (err) => { + if (err.message.includes("aborted")) { + return; + } + + process.stderr.write(err.message); + }); + + gateway.once("exit", () => { + gatewayExited = true; + gatewayExit.resolve(); + }); + + await gatewayExit.promise; + } ) .command( "test-suite", @@ -204,7 +278,7 @@ yargs(hideBin(process.argv)) resolvePath(argv, `./logs/${argv.test}-gateway.log`), { flags: "w+", - }, + } ); const gatewayExit = Promise.withResolvers(); @@ -240,7 +314,7 @@ yargs(hideBin(process.argv)) } else { process.exit(0); } - }, + } ) .command( "test", @@ -328,7 +402,7 @@ yargs(hideBin(process.argv)) resolvePath(argv, `./logs/${id}-gateway.log`), { flags: "w+", - }, + } ); const gatewayExit = Promise.withResolvers(); @@ -384,22 +458,22 @@ yargs(hideBin(process.argv)) process.stdout.write("-----------\n"); process.stdout.write(`Total: ${total}\n`); process.stdout.write( - `Passed: ${styleText("greenBright", passed + "")}\n`, + `Passed: ${styleText("greenBright", passed + "")}\n` ); if (failed > 0) { process.stdout.write( - `Failed: ${styleText("redBright", failed + "")}\n`, + `Failed: ${styleText("redBright", failed + "")}\n` ); } process.stdout.write("\n"); if (failed > 0) { process.stdout.write( - styleText("redBright", "Your gateway is not fully compatible\n"), + styleText("redBright", "Your gateway is not fully compatible\n") ); } else { process.stdout.write( - styleText("greenBright", "Your gateway is fully compatible\n"), + styleText("greenBright", "Your gateway is fully compatible\n") ); } @@ -414,14 +488,14 @@ yargs(hideBin(process.argv)) `Passed: ${passed}`, `Failed: ${failed}`, ]) - .join("\n"), + .join("\n") ); if (argv["exit-on-fail"] && failed > 0) { process.exit(1); } process.exit(0); - }, + } ) .demandCommand(1) .parse(); @@ -442,7 +516,7 @@ async function runTest(args: { resolvePath({ cwd: args.cwd }, `./logs/${args.test}-tests.log`), { flags: "w+", - }, + } ); if (args.healthcheck) { diff --git a/src/test-suites/requires-requires/d.subgraph.ts b/src/test-suites/requires-requires/d.subgraph.ts index fef1191..084a1d1 100644 --- a/src/test-suites/requires-requires/d.subgraph.ts +++ b/src/test-suites/requires-requires/d.subgraph.ts @@ -60,7 +60,7 @@ export default createSubgraph("d", { typeof key.isExpensiveWithDiscount !== "undefined" ) { return new GraphQLError( - "Product.isExpensiveWithDiscount must be a boolean" + "Product.isExpensiveWithDiscount must be a boolean", ); } diff --git a/src/test-suites/requires-requires/test.ts b/src/test-suites/requires-requires/test.ts index 2f27549..b2b8e5b 100644 --- a/src/test-suites/requires-requires/test.ts +++ b/src/test-suites/requires-requires/test.ts @@ -15,7 +15,7 @@ export default [ canAfford: false, }, }, - } + }, ), createTest( /* GraphQL */ ` @@ -31,7 +31,7 @@ export default [ isExpensive: true, }, }, - } + }, ), createTest( /* GraphQL */ ` @@ -49,7 +49,7 @@ export default [ canAfford: false, }, }, - } + }, ), createTest( /* GraphQL */ ` @@ -65,7 +65,7 @@ export default [ canAffordWithDiscount: true, }, }, - } + }, ), createTest( /* GraphQL */ ` @@ -83,6 +83,6 @@ export default [ canAffordWithDiscount: true, }, }, - } + }, ), ];