Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ on:
workflow_dispatch:

jobs:
build:
name: Build
test:
name: Test
runs-on: macos-latest
env:
GITHUB_ACTIONS_OUTPUT: ""
Expand Down Expand Up @@ -49,3 +49,8 @@ jobs:
run: |
echo "Running in $BROWSER"
npm run test:${{ matrix.browser }}

- name: Run Build
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ordering question: is there a particular reason to have this after the Run Tests step? Logically it seems to make sense to have build before test, so that we always run the freshly rebuilt workloads, right?

run: |
echo "Running in $BROWSER"
npm run test:build
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"test:shell": "npm run test:v8 && npm run test:jsc && npm run test:spidermonkey",
"test:v8": "node tests/run-shell.mjs --shell v8",
"test:jsc": "node tests/run-shell.mjs --shell jsc",
"test:spidermonkey": "node tests/run-shell.mjs --shell spidermonkey"
"test:spidermonkey": "node tests/run-shell.mjs --shell spidermonkey",
"test:build": "node tests/run-build.mjs"
},
"devDependencies": {
"@actions/core": "^1.11.1",
Expand Down
59 changes: 58 additions & 1 deletion tests/helper.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { styleText } from "node:util";
import core from "@actions/core";
import { spawn } from "child_process";
import commandLineUsage from "command-line-usage";
import { styleText } from "node:util";

export const GITHUB_ACTIONS_OUTPUT = "GITHUB_ACTIONS_OUTPUT" in process.env;

Expand Down Expand Up @@ -30,6 +31,16 @@ export function logError(...args) {
}
}

export function logCommand(...args) {
const cmd = args.join(" ");
if (GITHUB_ACTIONS_OUTPUT) {
core.notice(styleText("blue", cmd));
} else {
console.log(styleText("blue", cmd));
}
}


export async function logGroup(name, body) {
if (GITHUB_ACTIONS_OUTPUT) {
core.startGroup(name);
Expand Down Expand Up @@ -80,3 +91,49 @@ export async function runTest(label, testFunction) {
}
return true;
}


export async function sh(binary, ...args) {
const cmd = `${binary} ${args.join(" ")}`;
if (GITHUB_ACTIONS_OUTPUT)
core.startGroup(binary);
logCommand(cmd);
try {
return await spawnCaptureStdout(binary, args);
} catch(e) {
logError(e.stdoutString);
throw e;
} finally {
if (GITHUB_ACTIONS_OUTPUT)
core.endGroup();
}
}

const SPAWN_OPTIONS = Object.freeze({
stdio: ["inherit", "pipe", "inherit"]
});

async function spawnCaptureStdout(binary, args, options={}) {
options = Object.assign(options, SPAWN_OPTIONS);
const childProcess = spawn(binary, args, options);
childProcess.stdout.pipe(process.stdout);
return new Promise((resolve, reject) => {
childProcess.stdoutString = "";
childProcess.stdio[1].on("data", (data) => {
childProcess.stdoutString += data.toString();
});
childProcess.on("close", (code) => {
if (code === 0) {
resolve(childProcess);
} else {
// Reject the Promise with an Error on failure
const error = new Error(`Command failed with exit code ${code}: ${binary} ${args.join(" ")}`);
error.process = childProcess;
error.stdout = childProcess.stdoutString;
error.exitCode = code;
reject(error);
}
});
childProcess.on("error", reject);
})
}
73 changes: 73 additions & 0 deletions tests/run-build.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#! /usr/bin/env node

import commandLineArgs from "command-line-args";
import fs from "fs";
import { fileURLToPath } from "url";
import path from "path";

import { logError, logCommand, printHelp, runTest, sh } from "./helper.mjs";

const optionDefinitions = [
{ name: "help", alias: "h", description: "Print this help text." },
];

const options = commandLineArgs(optionDefinitions);

if ("help" in options)
printHelp(optionDefinitions);

const FILE_PATH = fileURLToPath(import.meta.url);
const SRC_DIR = path.dirname(path.dirname(FILE_PATH));

async function findPackageJsonFiles(dir, accumulator=[]) {
const dirEntries = fs.readdirSync(dir, { withFileTypes: true });
for (const dirent of dirEntries) {
if (dirent.name === "node_modules" || dirent.name === ".git")
continue;
const fullPath = path.join(dir, dirent.name);
if (dirent.isDirectory())
findPackageJsonFiles(fullPath, accumulator);
else if (dirent.name === "package.json")
accumulator.push(fullPath)
}
return accumulator;
}

async function runBuilds() {
const packageJsonFiles = await findPackageJsonFiles(SRC_DIR);
let success = true;

for (const file of packageJsonFiles) {
const content = fs.readFileSync(file, "utf-8");
const packageJson = JSON.parse(content);
if (!packageJson.scripts?.build) {
continue;
}

const dir = path.dirname(file);
const relativeDir = path.relative(SRC_DIR, dir);
const testName = `Building ${relativeDir}`;

const buildTask = async () => {
const oldCWD = process.cwd();
try {
logCommand("cd", dir);
process.chdir(dir);
await sh("npm", "ci");
await sh("npm", "run", "build");
} finally {
process.chdir(oldCWD);
// await sh("git", "reset", "--hard");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove or add a comment maybe? Otherwise it looks like it's potentially forgotten/accidentally committed code.

}
};

success &&= await runTest(testName, buildTask);
}

if (!success) {
logError("One or more builds failed.");
process.exit(1);
}
}

setImmediate(runBuilds);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: add newline

58 changes: 3 additions & 55 deletions tests/run-shell.mjs
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
#! /usr/bin/env node

import commandLineArgs from "command-line-args";
import { spawn } from "child_process";
import { fileURLToPath } from "url";
import { styleText } from "node:util";
import * as path from "path";
import * as fs from "fs";
import * as os from "os";
import core from "@actions/core";
import * as path from "path";
import { fileURLToPath } from "url";

import {logInfo, logError, logGroup, printHelp, runTest, GITHUB_ACTIONS_OUTPUT} from "./helper.mjs";
import { logGroup, logInfo, printHelp, runTest, sh } from "./helper.mjs";

const optionDefinitions = [
{ name: "shell", type: String, description: "Set the shell to test, choices are [jsc, v8, spidermonkey]." },
Expand Down Expand Up @@ -55,55 +52,6 @@ function convertCliArgs(cli, ...cliArgs) {
}


const SPAWN_OPTIONS = {
stdio: ["inherit", "inherit", "inherit"]
};

async function sh(binary, ...args) {
const cmd = `${binary} ${args.join(" ")}`;
if (GITHUB_ACTIONS_OUTPUT) {
core.startGroup(binary);
core.notice(styleText("blue", cmd));
} else {
console.log(styleText("blue", cmd));
}
try {
const result = await spawnCaptureStdout(binary, args, SPAWN_OPTIONS);
if (result.status || result.error) {
logError(result.error);
throw new Error(`Shell CMD failed: ${binary} ${args.join(" ")}`);
}
return result;
} finally {
if (GITHUB_ACTIONS_OUTPUT)
core.endGroup();
}
}

async function spawnCaptureStdout(binary, args) {
const childProcess = spawn(binary, args);
childProcess.stdout.pipe(process.stdout);
return new Promise((resolve, reject) => {
childProcess.stdoutString = "";
childProcess.stdio[1].on("data", (data) => {
childProcess.stdoutString += data.toString();
});
childProcess.on('close', (code) => {
if (code === 0) {
resolve(childProcess);
} else {
// Reject the Promise with an Error on failure
const error = new Error(`Command failed with exit code ${code}: ${binary} ${args.join(" ")}`);
error.process = childProcess;
error.stdout = childProcess.stdoutString;
error.exitCode = code;
reject(error);
}
});
childProcess.on('error', reject);
})
}

async function runTests() {
const shellBinary = await logGroup(`Installing JavaScript Shell: ${SHELL_NAME}`, testSetup);
let success = true;
Expand Down
7 changes: 7 additions & 0 deletions web-ssr/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions web-ssr/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@babel/node": "^7.28.0",
"@babel/preset-env": "^7.28.0",
"@babel/preset-react": "^7.27.1",
"@dapplets/unicode-escape-webpack-plugin": "^0.1.1",
"assert": "^2.1.0",
"babel-loader": "^10.0.0",
"babel-node": "^0.0.1-security",
Expand Down
Loading