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

Commit 207bef3

Browse files
authored
Merge pull request #445 from daniel0611/nodecg-test-windows
Run NodeCG test in CI on Windows
2 parents 06d451d + befd108 commit 207bef3

File tree

2 files changed

+82
-32
lines changed

2 files changed

+82
-32
lines changed

.github/workflows/ci.yml

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,31 +59,63 @@ jobs:
5959
# are mounted by NodeCG. It will fail if one of them is not mounted.
6060
# You may check for other NodeCG runtime errors in the output (these
6161
# may not fail the run).
62-
runs-on: ubuntu-latest
62+
strategy:
63+
matrix:
64+
os: [ubuntu-latest, windows-latest]
65+
runs-on: ${{ matrix.os }}
6366
steps:
6467
- uses: actions/setup-node@v2
6568
with:
6669
node-version: "16"
6770

68-
- name: Install nodecg-cli
69-
run: npm install --global nodecg-cli
71+
- name: Download NodeCG
72+
uses: actions/checkout@v2
73+
with:
74+
repository: nodecg/nodecg
75+
76+
- name: Get NodeCG commit hash
77+
id: nodecgHash
78+
shell: bash
79+
run: echo "::set-output name=nodecgHash::$(git rev-parse HEAD)"
80+
81+
- name: Cache NodeCG dependencies
82+
id: cache-nodecg
83+
uses: actions/cache@v2
84+
with:
85+
path: 'node_modules'
86+
key: ${{ runner.os }}-${{ steps.nodecgHash.outputs.nodecgHash }}-nodecg
7087

71-
- name: Setup NodeCG
72-
run: nodecg setup
88+
- name: Install NodeCG dependencies
89+
# Only get dependencies if we didn't get them from the cache
90+
if: steps.cache-nodecg.outputs.cache-hit != 'true'
91+
run: npm install --prod
7392

74-
- name: Setup NodeCG config
93+
- name: Setup NodeCG config linux
94+
if: matrix.os == 'ubuntu-latest'
7595
run: |
7696
mkdir cfg
7797
echo '{"bundles": {"paths": ["'${GITHUB_WORKSPACE}'/nodecg-io","'${GITHUB_WORKSPACE}'/nodecg-io/services","'${GITHUB_WORKSPACE}'/nodecg-io/samples"]}}' > ./cfg/nodecg.json
7898
79-
# nodecg-io needs to be cloned after NodeCG setup because the nodecg-cli requires an empty directory.
99+
- name: Setup NodeCG config windows
100+
if: matrix.os == 'windows-latest'
101+
shell: bash
102+
run: |
103+
mkdir cfg
104+
# We need to escape backslashes to get valid json. Replaces each "\" with "\\"
105+
echo '{"bundles": {"paths": ["'${GITHUB_WORKSPACE//\\/\\\\}'\\nodecg-io","'${GITHUB_WORKSPACE//\\/\\\\}'\\nodecg-io\\services","'${GITHUB_WORKSPACE//\\/\\\\}'\\nodecg-io\\samples"]}}' > ./cfg/nodecg.json
106+
80107
- uses: actions/checkout@v2
81108
with:
82109
path: "nodecg-io"
83110

84111
- name: Install system dependencies
112+
if: matrix.os == 'ubuntu-latest'
85113
run: sudo apt update && sudo apt-get -y install libusb-1.0-0-dev libasound2-dev libudev-dev
86114

115+
- name: Install node native development files
116+
shell: bash
117+
run: npx node-gyp install
118+
87119
- name: Install nodejs dependencies
88120
run: npm ci
89121
working-directory: ./nodecg-io
@@ -93,6 +125,7 @@ jobs:
93125
working-directory: ./nodecg-io
94126

95127
- name: Run test
128+
shell: bash
96129
run: node .scripts/ci-nodecg-integration.mjs
97130
working-directory: ./nodecg-io
98131

.scripts/ci-nodecg-integration.mjs

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ if (!nodecgiodir) {
2424
* }
2525
* ~~~
2626
*/
27-
const npm = JSON.parse(child_process.execSync("npm ls --json"));
27+
const npm = JSON.parse(child_process.execSync("npm ls --json").toString());
2828

2929
// Filter out any dependencies which are not resolved locally in samples or services because the other npm packages will not be loaded by NodeCG
3030
let bundles = Object.entries(npm.dependencies)
@@ -33,7 +33,8 @@ let bundles = Object.entries(npm.dependencies)
3333
(j) =>
3434
j[0] === "resolved" &&
3535
(`${j[1]}`.startsWith("file:../samples/") ||
36-
`${j[1]}`.startsWith("file:../services/" || `${j[1]}` === "file:../nodecg-io-core")),
36+
`${j[1]}`.startsWith("file:../services/") ||
37+
`${j[1]}` === "file:../nodecg-io-core"),
3738
),
3839
)
3940
.map((v) => v[0]);
@@ -44,31 +45,47 @@ console.log("");
4445
console.log("NodeCG sterr");
4546
console.log("--------------------------------------------------------------------------------");
4647

47-
// expects a NodeCG folder be the parent of the cwd needs timeout
48-
const log = child_process
49-
.execSync("timeout --preserve-status 15s node " + cwd.dir + path.sep + "index.js", { cwd: cwd.dir })
50-
.toString("utf8");
48+
// Spawn a process that runs NodeCG
49+
const child = child_process.spawn("node", ["index.js"], { cwd: cwd.dir });
5150

52-
const lines = log.split("\n");
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()));
5355

54-
// Try to find each bundle in the logs.
55-
const missing = bundles.filter(
56-
/*Using endsWith here to remove possible ansi styling of "[info]" caused by ModeCG's logger when run locally*/
57-
(i) => !lines.some((j) => j.endsWith("[nodecg/lib/server/extensions] Mounted " + i + " extension")),
58-
);
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+
}
5963

60-
// Fail the run if there are missing bundles.
61-
if (missing.length > 0) {
62-
// Only log stout if the run has failed because otherwise its unimportant and everything important should be in stderr
63-
console.log("");
64-
console.log("NodeCG stout");
65-
console.log("--------------------------------------------------------------------------------");
66-
console.log(log);
64+
// Check exit code for failure
65+
const exitCode = child.exitCode;
66+
if (exitCode !== null && exitCode !== 0) {
67+
throw new Error(`NodeCG exited with code ${exitCode}`);
68+
}
6769

68-
console.log("");
69-
console.log("Missing Bundles");
70-
console.log("--------------------------------------------------------------------------------");
71-
console.log(missing);
70+
// Try to find each bundle in the logs.
71+
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")),
74+
);
7275

73-
throw new Error(`NodeCG did not mount ${missing.length} bundle(s).`);
74-
}
76+
// Fail the run if there are missing bundles.
77+
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);
88+
89+
throw new Error(`NodeCG did not mount ${missing.length} bundle(s).`);
90+
}
91+
}, 15000);

0 commit comments

Comments
 (0)