Skip to content
This repository was archived by the owner on Apr 13, 2025. It is now read-only.

Commit cccac31

Browse files
authored
ci/improve itegration test (#582)
* ci(scripts): Update type and log tsconfig update * ci(scripts): Refactor NodeCG integration test - Use `@manypkg/get-packages` to collect the packages in the workspace (like in our other scripts). Thus improving the legibility. - Improving the log output by decluttering it - Add confirmation, in case no errors were thrown * ci: Use timeout option from child_process.spawn The implications of https://nodejs.org/api/child_process.html#subprocesskillsignal and the possibility of killing other process, implied using the integrated timeout option. Also, `stdout` is now collected in a Buffer and is only converted after NodeCG stopped. This is needed in case the data of a single line is split up into to calls which would brake the previous implementation. * ci(scripts): Add back null check for windows
1 parent 837c6ea commit cccac31

File tree

3 files changed

+32
-60
lines changed

3 files changed

+32
-60
lines changed

.scripts/ci-nodecg-integration.mjs

+30-59
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as fs from "fs";
22
import * as path from "path";
33
import * as child_process from "child_process";
4+
import { getPackages } from "@manypkg/get-packages";
45

56
const cwd = path.parse(process.cwd());
67
const nodecgiodir = fs.readdirSync(process.cwd()).some((v) => v === "nodecg-io-core");
@@ -9,83 +10,53 @@ const nodecgiodir = fs.readdirSync(process.cwd()).some((v) => v === "nodecg-io-c
910
if (!nodecgiodir) {
1011
throw new Error("You will have to run this script from inside the nodecg-io folder!");
1112
}
12-
/**
13-
* expected data:
14-
*
15-
* ~~~json
16-
* {
17-
* name: 'nodecg-io',
18-
* dependencies: {
19-
* 'name': {
20-
* version: 'version',
21-
* resolved: 'optional'
22-
* },
23-
* }
24-
* }
25-
* ~~~
26-
*/
27-
const npm = JSON.parse(child_process.execSync("npm ls --json").toString());
2813

29-
// Filter out any dependencies which are not resolved locally in samples or services because the other npm packages will not be loaded by NodeCG
30-
let bundles = Object.entries(npm.dependencies)
31-
.filter((i) =>
32-
Object.entries(i[1]).some(
33-
(j) =>
34-
j[0] === "resolved" &&
35-
(`${j[1]}`.startsWith("file:../samples/") ||
36-
`${j[1]}`.startsWith("file:../services/") ||
37-
`${j[1]}` === "file:../nodecg-io-core"),
38-
),
39-
)
40-
.map((v) => v[0]);
14+
const { packages } = await getPackages(process.cwd());
4115

42-
console.log(`Found ${bundles.length} bundles in this install.`);
16+
// Filter out packages other than core, samples and services, because they should not be NodeCG-bundles (dashboard, utils)
17+
const bundles = packages.filter(
18+
(v) =>
19+
v.packageJson.name === "nodecg-io-core" ||
20+
path.parse(v.dir).dir.endsWith("samples") ||
21+
path.parse(v.dir).dir.endsWith("services"),
22+
);
4323

44-
console.log("");
45-
console.log("NodeCG sterr");
24+
console.log(`Found ${bundles.length} bundles in this install.`);
25+
console.log("\nStarted NodeCG");
4626
console.log("--------------------------------------------------------------------------------");
4727

48-
// Spawn a process that runs NodeCG
49-
const child = child_process.spawn("node", ["index.js"], { cwd: cwd.dir });
28+
// Spawn a process that runs NodeCG and let it run for 15 seconds to load all bundles
29+
const child = child_process.spawn("node", ["index.js"], { cwd: cwd.dir, timeout: 15000 });
5030

51-
// Store stdout in lines and stream stderr to stderr of this process
52-
const lines = [];
53-
child.stdout.on("data", (data) => lines.push(data.toString()));
54-
child.stderr.on("data", (data) => console.error(data.toString()));
31+
// Store stdout and pipe the output of the child process to the output of this process
32+
const buffer = [];
33+
child.stdout.on("data", (data) => buffer.push(data));
34+
child.stdout.pipe(process.stdout);
35+
child.stderr.pipe(process.stderr);
5536

56-
// Let NodeCG run for 15 seconds to load all bundles
57-
setTimeout(() => {
58-
// We don't want to leave NodeCG running, if it was loaded successfully.
59-
// If it has errored, it will not be running anymore.
60-
if (child.pid) {
61-
child.kill();
62-
}
37+
child.once("exit", (exitCode, signal) => {
38+
console.log("--------------------------------------------------------------------------------");
39+
console.log("Stopped NodeCG\n");
6340

6441
// Check exit code for failure
65-
const exitCode = child.exitCode;
6642
if (exitCode !== null && exitCode !== 0) {
67-
throw new Error(`NodeCG exited with code ${exitCode}`);
43+
throw new Error(`NodeCG exited with code ${exitCode} ${signal}`);
6844
}
6945

46+
const log = Buffer.concat(buffer).toString();
47+
7048
// Try to find each bundle in the logs.
7149
const missing = bundles.filter(
72-
/*Using endsWith here to remove possible ansi styling of "[info]" caused by ModeCG's logger when run locally*/
73-
(i) => !lines.some((j) => j.includes("[nodecg/lib/server/extensions] Mounted " + i + " extension")),
50+
(i) => !log.includes(`[nodecg/lib/server/extensions] Mounted ${i.packageJson.name} extension`),
7451
);
7552

7653
// Fail the run if there are missing bundles.
7754
if (missing.length > 0) {
78-
// Only log stout if the run has failed because otherwise its unimportant and everything important should be in stderr
79-
console.log("");
80-
console.log("NodeCG stout");
81-
console.log("--------------------------------------------------------------------------------");
82-
console.log(lines.join(""));
83-
84-
console.log("");
85-
console.log("Missing Bundles");
86-
console.log("--------------------------------------------------------------------------------");
87-
console.log(missing);
55+
console.log("Missing Bundles:");
56+
console.log(missing.map((v) => v.packageJson.name));
8857

8958
throw new Error(`NodeCG did not mount ${missing.length} bundle(s).`);
9059
}
91-
}, 15000);
60+
61+
console.log("No Errors!");
62+
});

.scripts/exec.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import concurrently from "concurrently";
33

44
const COMMAND = process.argv[2];
55

6-
/**@type {import('concurrently').CommandObj[]}*/
6+
/**@type {import('concurrently').ConcurrentlyCommandInput[]}*/
77
const commands = packages
88
.filter((v) => v.packageJson["scripts"] && v.packageJson["scripts"][COMMAND])
99
.map((v) => ({

.scripts/update-paths.mjs

+1
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ const tsconfig = {
1414
};
1515

1616
let content = "// This file will be overwritten automatically! Do not store options here.\n" + JSON.stringify(tsconfig);
17+
console.log("Update root tsconfig.json…");
1718
fs.writeFileSync(rootTSconfig, content, { encoding: "utf8" });

0 commit comments

Comments
 (0)