Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
cf4cd4f
wip
camillobruni Sep 22, 2025
50644f8
wip
camillobruni Sep 22, 2025
c646d71
wip
camillobruni Sep 22, 2025
c22b0b6
fix
camillobruni Sep 22, 2025
c648ba9
add missing package
camillobruni Sep 22, 2025
7f6b7f1
fixes
camillobruni Sep 22, 2025
a18962c
format
camillobruni Sep 22, 2025
fb4dce9
cleanup
camillobruni Sep 22, 2025
05bd3f6
Merge branch 'main' into 2025-09-22_test_npm_run_build
camillobruni Oct 22, 2025
62f80a8
update add build job
camillobruni Oct 22, 2025
ba1b2bd
update config
camillobruni Oct 22, 2025
e52a531
fix var names
camillobruni Oct 22, 2025
fe9ccc7
more logging
camillobruni Oct 22, 2025
97cf3a2
fix conditions
camillobruni Oct 22, 2025
b297335
more logging
camillobruni Oct 22, 2025
bd9f549
wip
camillobruni Oct 22, 2025
9e6e4f5
fix
camillobruni Oct 22, 2025
cf94d79
cleanup
camillobruni Oct 22, 2025
f21d054
quotli
camillobruni Oct 22, 2025
76dbbcc
i can't type, thanks
camillobruni Oct 22, 2025
40134cb
fix
camillobruni Oct 22, 2025
04e0029
prin
camillobruni Oct 22, 2025
c88a8b8
fix
camillobruni Oct 22, 2025
0af263b
fix
camillobruni Oct 22, 2025
fc5b76a
fix
camillobruni Oct 22, 2025
ad22ba0
fix stdot
camillobruni Oct 22, 2025
a6a0774
cleanup
camillobruni Oct 22, 2025
876b4e3
better-message
camillobruni Oct 22, 2025
2c70f04
fix
camillobruni Oct 22, 2025
3bb88e3
cleanup
camillobruni Oct 22, 2025
951429a
fix workflow
camillobruni Oct 22, 2025
524bffa
partial revert
camillobruni Oct 22, 2025
b3628d2
Merge branch 'main' into 2025-09-22_test_npm_run_build
camillobruni Oct 22, 2025
e97cc5a
fix double import
camillobruni Oct 22, 2025
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
31 changes: 29 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,30 @@ jobs:
run: |
echo "Running in $BROWSER"
npm run test:${{ matrix.browser }}

build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout Branch
uses: actions/checkout@v4
with:
fetch-depth: ${{ github.event_name == 'pull_request' && 2 || 0 }}

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version-file: package.json
cache: npm

- name: Install Node Packages
run: npm ci

- name: Run Build
run: |
if ${{ github.event_name == 'pull_request' }}; then
npm run test:build -- --diff="HEAD^...HEAD"
else
npm run test:build -- --diff="${{ github.event.before }}...${{ github.event.after }}"
fi

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
"test:shell": "npm run test:prepare && npm run test:v8 && npm run test:jsc && npm run test:spidermonkey",
"test:v8": "npm run test:prepare && node tests/run-shell.mjs --shell v8",
"test:jsc": "npm run test:prepare && node tests/run-shell.mjs --shell jsc",
"test:spidermonkey": "npm run test:prepare && node tests/run-shell.mjs --shell spidermonkey"
"test:spidermonkey": "npm run test:prepare && node tests/run-shell.mjs --shell spidermonkey",
"test:build": "npm run test:prepare && node tests/run-build.mjs"
},
"devDependencies": {
"@actions/core": "^1.11.1",
Expand Down
61 changes: 59 additions & 2 deletions tests/helper.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.

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;
export const GITHUB_ACTIONS_OUTPUT = ("GITHUB_ACTIONS_OUTPUT" in process.env) || ("GITHUB_EVENT_PATH" in process.env);

export function logInfo(...args) {
const text = args.join(" ")
Expand Down Expand Up @@ -53,6 +54,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 @@ -103,3 +114,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);
})
}
104 changes: 104 additions & 0 deletions tests/run-build.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#! /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, logInfo } from "./helper.mjs";

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

const optionDefinitions = [
{ name: "help", alias: "h", description: "Print this help text." },
{ name: "diff", type: String, description: "A git commit range to determine which builds to run (e.g. main...HEAD)." },
];

const options = commandLineArgs(optionDefinitions);

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


if (options.diff) {
const { stdoutString } = await sh("git", "diff", "--name-only", options.diff);
const changedDirs = new Set();
const changedFiles = stdoutString.trim().split("\n");
for (const file of changedFiles) {
let currentDir = path.dirname(file)
while (currentDir !== ".") {
changedDirs.add(path.join(SRC_DIR, currentDir));
currentDir = path.dirname(currentDir);
}
}
options.changedDirs = changedDirs;
} else {
options.changedDirs = undefined;
}

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;

logInfo(`Found ${packageJsonFiles.length} package.json files`);
let filteredPackageJsonFiles = packageJsonFiles;
if (options.changedDirs?.size === 0) {
logInfo("No file changes detected, skipping all");
}
if (options.changedDirs?.size > 0) {
filteredPackageJsonFiles = packageJsonFiles.filter(file => {
const dir = path.dirname(file);
return options.changedDirs.has(dir);
});
logInfo(`Found ${filteredPackageJsonFiles.length} modified package.json files to build`);
}

for (const file of filteredPackageJsonFiles) {
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");
}
};

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

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

setImmediate(runBuilds);
58 changes: 3 additions & 55 deletions tests/run-shell.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,12 @@
// THE POSSIBILITY OF SUCH DAMAGE.

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 @@ -78,55 +75,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